fix(tests): tray source checks fail when the checkout is LF - #1518
Conversation
Multiline source-contract asserts compared against a hardcoded CRLF snippet. An LF checkout does not contain that snippet, so five Tray checks failed while the product source was unchanged. Normalize CRLF to LF on the compared text. A CRLF checkout still matches. Validation: ./build.ps1 exit 0. Shared 4107 passed, 32 skipped, 0 failed (4139 total). Tray 3072 passed, 0 failed. Focused filter 5 passed. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs maintainer review before merge. Reviewed September 25, 2026, 1:29 PM ET / 17:29 UTC (Revision 2). ClawSweeper reviewWhat this changesThe branch normalizes line endings in six Tray source-contract assertions so developers can run the tests from LF or CRLF checkouts. Merge readiness✅ Ready for maintainer review This remains a useful, focused fix. Current main still contains the line-ending-sensitive assertions, while the PR makes them work with LF and CRLF source files. The prior review reported no findings, and no new blocking defect is evident. Priority: P2 Review scores
Verification
How this fits togetherThe Tray test suite reads WinUI source files from the checkout and checks that important UI behavior remains present. These assertions affect developer validation, not the running app. flowchart LR
A[Source checkout] --> B[Tray test suite]
B --> C[Read WinUI source]
C --> D[Normalize line endings]
D --> E[Check behavior snippets]
E --> F[Test result]
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Keep these source-contract assertions line-ending agnostic so both supported checkout forms validate the same behavior. Do we have a high-confidence way to reproduce the issue? Yes. On baseline code, an LF source file cannot contain the CRLF literal required by these assertions; the related PR reports also record the five failing checks on LF checkouts. This read-only review did not execute them. Is this the best way to solve the issue? Yes. Normalizing the compared source text is a narrow fix consistent with an existing Tray test pattern, and it preserves the checks for the intended snippets. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 7d92747e193c. LabelsLabel changes: No label changes. Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (1 earlier review cycle)
|
ConnectWithSharedTokenAsync treated a still-connecting operator as success, so a gateway auth failure that arrived later left the rejected token committed. When a bootstrap or SSH setup credential is at risk, wait for that failure, then restore saved settings and reconnect a connection that was already live. Connection tests: 804 passed, 1 skipped. Shared tests: 4107 passed, 32 skipped. Tray tests: 3067 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
… late After the deferred auth wait, roll the registry back only when this attempt still owns the connection generation. When another gateway was active, the settings callback receives that gateway's record so saved settings match the restored active id. Connection tests: 806 passed, 1 skipped. Shared tests: 4106 passed and 32 skipped, then the one dispose failure passed alone. Tray tests: 3067 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A shared-token replacement that is still connecting after the wait rolls the rejected token back instead of returning success. If settings or the runtime tunnel fail while applying the restored gateway, the callback retries that gateway and reports an out-of-sync error instead of writing the rejected snapshot back. Connection tests: 807 passed, 1 skipped. Shared tests: 4107 passed, 32 skipped. Tray tests: 3068 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
When the handshake wait ends while the operator is still connecting, disconnect that attempt so its generation is cancelled and the operator is Idle before the previous gateway is opened again. The restore then waits for a terminal result. When rollback clears the active gateway, the settings callback restores the snapshot taken before the rejected record was applied. Connection tests: 808 passed, 1 skipped. Shared tests: 4107 passed, 32 skipped. Tray tests: 3069 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
ApplySettings saves the candidate gateway before runtime tunnel reconciliation. If that reconciliation fails on the retry as well, write the snapshot taken before the apply back to settings and still throw, so the connection manager can roll the registry back without leaving the rejected gateway saved. Tray tests: 3069 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Shared tests: 4107 passed, 32 skipped. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
The rollback callback was capturing settings again after the candidate had been saved, so a second tunnel failure wrote the rejected gateway back. Capture the snapshot once per shared-token attempt and reuse it when the rollback callback fails. Tray tests: 3070 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Shared tests: 4107 passed, 32 skipped. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
BeginSharedTokenSettingsAttempt captures the snapshot, so the candidate callback must not clear it on success. The rollback callback still uses that snapshot when tunnel reconciliation fails twice. Tray tests: 3071 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Shared tests: 4107 passed, 32 skipped. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
The settings snapshot lived on the tray service and was captured before the connection manager took its lock, so a second connect could replace it. Each connect now captures its own attempt and passes that object into the settings callback. Shared tests: 4107 passed, 32 skipped. Tray suite: 3071 passed, 6 failed. Five failures are the LF source-contract mismatch tracked in openclaw#1518. CredentialReplacementFlows_DoNotBlindlyClearDeviceTokens then passed after its expected call was updated. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
…lock The tray captured the settings snapshot before ConnectWithSharedTokenAsync took the transition lock, so a second request could snapshot a baseline from before the first transaction. The capture now runs inside that lock, and the second request cannot start until the first has entered it. Connection tests: 809 passed, 1 skipped. Shared tests: 4107 passed, 32 skipped. Tray tests: 3072 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
bash script.sh -c value and pwsh -File script.ps1 /c value are direct script invocations. Scanning past the script operand classified those arguments as inline shell commands and blocked reusable approval. Inline -c and /c before the script operand still stay one-time. Shared tests: 4125 passed, 32 skipped. Tray tests: 3067 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A single-dash letter cluster that contains c, such as -ec or -ce, is an inline shell command. The next argument is the payload. Scanning still stops at the script name, so bash script.sh -ec value stays a direct script. Shared tests: 4128 passed, 32 skipped. Tray tests: 3067 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A combined flag is inline only when it contains a lowercase c. Uppercase C is noclobber, so bash -C and bash -eC script.sh stay direct scripts. bash -ec remains inline. Exact POSIX flags are case-sensitive, so -C does not match -c. Shared tests: 4129 passed, 32 skipped. Tray tests: 3067 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A sensitive string array, including webhookUrls, uses a password box and does not copy the stored value into it. A blank box keeps the existing item. The schema JSON view and the fallback array view do the same. ./build.ps1 exit 0. Shared tests: 4107 passed, 32 skipped. Tray tests: 3087 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. ConfigPathSensitivityTests: 20 passed. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
…es exactly A stored webhook URL array stays in the editor, not on the password box. A blank box still keeps that item. webhookUrl and webhookUrls are exact path segments, so webhookUrlExtra stays a normal field. ./build.ps1 exit 0. Shared tests: 4107 passed, 32 skipped. Tray tests: 3089 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. ConfigPathSensitivityTests: 22 passed. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A loaded webhook URL row is remembered even when its stored value is empty. Editing another item no longer drops that row from the whole-array patch. A newly added blank row is still omitted until it has a value. ./build.ps1 exit 0. Shared tests: 4107 passed, 32 skipped. Tray tests: 3089 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. ConfigPathSensitivityTests: 22 passed. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A sensitive array of objects stays masked. The note above it no longer tells the user to edit JSON below a disabled field. It says the stored values stay hidden and cannot be edited on this page. ./build.ps1 exit 0. Shared tests: 4107 passed, 32 skipped. Tray tests: 3089 passed, 5 failed on the LF source-contract mismatch tracked in openclaw#1518. ConfigPathSensitivityTests: 22 passed. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
…ad-only Sensitive complex arrays stay hidden and show only a count. Replace all opens a blank editor and sends only the new JSON. Clear all asks, then sends an empty array. Cancel leaves the stored array out of the patch. The same editor is used when the page has no schema. ./build.ps1 exit 0. Shared 4106 passed, 32 skipped, and the dispose flake passed alone. Tray 3094 passed, 5 failed, the LF source checks tracked in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
Sensitive schema objects, and schema-less sensitive objects, use the same blank replace and confirmed clear editor as complex arrays. Stored values stay off the control. Replace all checks the JSON kind and each array item kind before staging. Invalid input keeps the original value and blocks Save. Cancelling Clear all drops the abandoned validation error. ./build.ps1 exit 0. Shared 4107 passed, 32 skipped. Tray 3100 passed, 5 failed on the known LF source contracts (openclaw#1518). Focused editor and model tests passed. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A PowerShell option value named -File stopped classification before a later -c, so the binder could save that inline command. A positional script made a later /c look like a host switch. fish -C is an init command and stays a wrapper. bash -C stays noclobber. Validation: ./build.ps1 exit 0. Shared 4132 passed, 32 skipped. ExecApprovalV2NormalizationTests 120 passed. Tray 3067 passed and 5 failed, the LF source-contract mismatch in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
…celed A valid Replace all stayed on the edit session after a later invalid draft was rejected. Canceling Clear all cleared the error and left the pending change removed, so a later save kept the stored secret. Cancel clear now stages the committed replacement again. SensitiveArray_RejectedRetryThenCanceledClear_RestoresCommittedReplacement passed. ./build.ps1 exit 0. Shared 4107 passed, 32 skipped. Tray 3102 passed and 5 failed, the LF source-contract mismatch in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
A JSON object editor stages the parent path. An account label change under that parent was dropped with the non-id array, and a label changed from ordinary text to *** was removed as if it were an untouched secret mask. Ancestor edits now refuse that unsafe array save, and a non-secret literal is kept when the loaded value was not a mask. Validation: ./build.ps1 exit 0. Shared 4099 passed, 32 skipped. ConfigEditorModelTests 21 passed. Tray 3080 passed, 5 failed, the LF source-contract mismatch in openclaw#1518. Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
What Problem This Solves
Fixes five Tray source-contract tests that fail when the working tree uses LF line endings.
User Impact
No change in the running app. Developers with an LF checkout can run the Tray suite without five false failures.
Why This Change Was Made
These checks read C# source from disk and look for multiline snippets. The expected text was hardcoded with CRLF, so the snippets were not found in LF checkouts even though the production source was unchanged. The comparisons now normalize CRLF source text to LF before checking the same exact snippets. This preserves statement order, adjacency, and indentation in both checkout modes and follows an existing Tray source-test pattern.
Evidence
Reviewed head:
a660b7af669bf518c332ee682823e5af2df562b1.Contributor evidence on native Windows AMD64 with
core.autocrlf=false:./build.ps1: exit 0.ConnectionPage.xaml.cscontained 0 CR bytes and 3760 LF bytes. The old CRLF needle was absent and the equivalent LF needle was present.Maintainer exact-head evidence on native Windows ARM64 with current
mainat7d92747e193caa08833ea07f3cd08d365268f3de:./build.ps1: exit 0.dotnet test .\tests\OpenClaw.Shared.Tests\OpenClaw.Shared.Tests.csproj --no-restore: 4104 passed, 35 skipped, 0 failed, 4139 total.dotnet test .\tests\OpenClaw.Tray.Tests\OpenClaw.Tray.Tests.csproj --no-restore: 3072 passed, 0 skipped, 0 failed, 3072 total.OPENCLAW_REPO_ROOTpointed at an LF-only scratch source root (CR=0,LF=21220across the required source files): 5 passed, 0 failed.main: clean.--mode branch --base origin/main,gpt-5.6-sol, high reasoning): clean, no accepted/actionable findings, 0.99 confidence.Change Type
Scope
winnodeRequired proof pools
none: test-only source-text comparisons changed. No Tray UI, node command, gateway, installer, or runtime behavior changed.Validation
Real Behavior Proof
a660b7af669bf518c332ee682823e5af2df562b1.N/A, test-only change with no visible product behavior.Security Impact
NoNoNoNoNoCompatibility and Migration
YesNoNoReview Conversations