Skip to content

test(console): kill surviving mutants in the harness lock, JSON scan and recovery card - #2892

Merged
freeqaz merged 21 commits into
mainfrom
ux-fixes-123-tests
Oct 19, 2026
Merged

freeqaz merged 21 commits into
mainfrom
ux-fixes-123-tests

Conversation

@freeqaz

@freeqaz freeqaz commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

bughunt-123 found six gaps around the 10-18 console landings:

  • 1954: the harness-lock fixes from fix(console): Create Agent harness outcome copy and workspace missing-file copy #2875 had no test. Three mutants survived every Create Agent browser file:
  • 1950: three JSON-scan mutants survived console-json-errors:
    • an uppercase E exponent;
    • the \/ escape;
    • the column fallback used when Intl.Segmenter is missing.
  • 1949: zero-width and format characters earlier on the line each counted as a column, so the reported column pointed past the error. Affected characters: ZWSP, BOM, LRM/RLM, soft hyphen, word joiner. For example, {"name": "a<LRM>b<SHY>c<WJ>d", x} reported column 21, but the x is the 18th visible character.
  • 1951: you could delete the focusConfiguration() call on Create Agent's primary-model mismatch (the most common mismatch) and every test stayed green.
  • 1958: the recovery card's secondary action has a white fill and a --color-border-strong edge. On the card's warning tint that edge measures 2.83:1, below the 3:1 minimum for non-text contrast.
  • 1948: nothing tested the /var/lock -> /run/lock symlink entry in the chart and in render-installation-profile.mjs. Deleting it from both left the database CA mount tests green. Without the entry, /var/lock/../openclaw-worker (which is /run/openclaw-worker at runtime) renders.

Change

Mostly tests. There are two small product changes:

  • dom.mjs visibleLength skips graphemes made only of Default_Ignorable_Code_Point characters, with or without Intl.Segmenter (1949). A non-breaking space still counts, because it shows as a space. So do the Hangul fillers U+115F, U+1160, U+3164 and U+FFA0: they are default-ignorable, but fonts draw them as blank cells that advance the text. The messages are unchanged.
  • console.css: the secondary action's edge in .deployment-recovery-actions now uses --color-text-muted, an existing token. That gives 4.59:1 on the tint (1958). The primary action keeps its own, more specific rule.

Storybook: a new story, Pages/Agent detail → Invalid Configuration JSON after invisible characters (invalidConfigurationInvisibleCharacters), sits next to Invalid Configuration JSON. Its JSON is {"name": "a<LRM>b<SHY>c<WJ>d", x} with the real characters, and the error names column 18, the visible position of the x. The recovery card's secondary action already appears in Pages/Agent detail → New version failed, deploy again (deploymentFailedDeployAgain), as Open v7 Logs beside Deploy again.

Tests:

  • 1954 (console-create-agent-provisioning-400), using hold-until-released fakes:
    • OpenClaw on an installation without a Sandbox Driver. While the validate request is held (pending, nothing saved), the hint still offers Codex. While the Agent save is held (Configuration saved), the hint drops the Codex choice.
    • When a dropped Configuration save leaves the outcome unknown, the hint also drops the Codex choice.
    • A Codex service account token keeps its outcome hint while Create is pending. It switches to the saved-token hint only once the Configuration is saved.
  • 1950 (console-json-errors):
    • positions after 1E5, -2.5E-3 and an escaped-slash URL;
    • a second copy of dom.mjs loaded with Intl.Segmenter removed (and restored), which must count code points;
    • the engine cross-check's base document now uses E, \/ and CRLF, and its edit alphabet adds E + / u \r.
  • 1949: assertions for LRM, soft hyphen, word joiner, ZWSP, BOM and RLM. A ZWJ emoji still counts as one column, and so do NBSP and the four Hangul fillers: {"a": "p<FILLER>q", x} reports column 14 for each of U+115F, U+1160, U+3164 and U+FFA0, with and without Intl.Segmenter, as on main.
  • 1951 (console-json-error-feedback): a primary model under the wrong prefix (openai/gpt-4.1 for Codex) must focus the Configuration JSON.
  • 1958 (console-agent-deploy-again): reads the painted border colour of the secondary action. It composites the card tint over the first opaque background behind it, then asserts at least 3:1. It also asserts at least 3:1 between the edge and the button's own fill.
  • 1948 (production-kubernetes-packaging, profile-preflight-chart-parity): adds /var/lock/..<path> and /run/lock/..<path> to the alias probes. Both must be refused.

Verification

Mutants, each run by hand against the touched files:

Finding Mutant Result
1954 nativeRefused && !harnessChoiceLocked -> nativeRefused killed
1954 harnessChoiceLocked && usesPat -> harness.disabled && usesPat killed
1954 pending || added to harnessChoiceLocked killed
1954 outcomeUnknown dropped from harnessChoiceLocked (extra) killed
1950 exponent check "e" only killed (new test and extended cross-check, each alone)
1950 \/ dropped from the escape set killed (new test and extended cross-check, each alone)
1950 no-segmenter fallback counts UTF-16 units killed
1949 no invisible filter / unanchored invisible regex killed / killed
1949 Hangul filler exception removed, or the old U+3164/U+FFA0-only exception killed on both paths (Segmenter and fallback)
1949 U+115F, U+1160, U+3164 or U+FFA0 dropped from the exception, one at a time each killed on both paths, with the dropped filler named
1951 delete focusConfiguration() on the primary mismatch killed
1951 delete it on the fallback mismatch (existing guard) still killed
1948 delete /var/lock from the chart dict and runtimeImageLinks killed in both files (main's tests: 1/1 green under it)
1948 control: delete /var/run killed in both files
1958 edge back to --color-border-strong / dark fill behind the muted edge killed / killed

Fail on main:

  • 1949: the new conformance test fails on main (columns 21, 14, 13).
  • 1958: the new test fails on main with edge 147,139,127 on card 242,234,228: 2.83:1.

Contrast (WCAG 2), with the card tint rgba(146,64,14,.08) over --color-bg, which is #f2eae4:

Edge On the tint On the white fill
before: --color-border-strong #938b7f 2.83:1 3.37:1
after: --color-text-muted #6e6960 4.59:1 5.45:1

Pins, 20 sequential runs per file on 2 CPUs, after the review follow-ups (5480549c8, main at 245d17083):

  • console-create-agent-provisioning-400: 20/20
  • console-json-error-feedback: 20/20
  • console-agent-deploy-again: 20/20

After merging main again for #2891 (26d630c43), which changed detail.mjs and console.css:

  • console-agent-deploy-again: 20/20
  • console-create-agent-provisioning-400 and console-json-error-feedback: one full run each, green.

After merging main for #2895 and #2896 (ba68022bb), which changed the deploy-again test, detail.mjs, dom.mjs and console.css:

  • console-agent-deploy-again: 20/20
  • one full run each, all green: console-create-agent-provisioning-400 (40/40), console-json-error-feedback (3/3), console-json-errors (13/13) and main's new console-button-hierarchy (4/4).

After the Hangul follow-up (2c3fa4f24, which changes only dom.mjs and the conformance file): console-json-errors 13/13, and one full run each, all green, of console-json-error-feedback (3/3), console-create-agent-provisioning-400 (40/40) and console-agent-deploy-again (12/12).

The full touched files are green:

File Tests
console-create-agent-provisioning-400 40/40
console-json-error-feedback 3/3
console-agent-deploy-again 10/10
console-json-errors 13/13
production-kubernetes-packaging 91/91
profile-preflight-chart-parity 30/30

Main's own tests let the 1950 and 1951 mutants through (re-checked: 10/10 and 3/3 green under each).

Lint: eslint and prettier are clean on the touched files.

Screenshots of the recovery card on a failed redeploy, from a browser fixture (simulated UI evidence). They were committed in 851bb69e2 and removed again in 49f8c7a33; the native attachments below preserve those before/after captures.

Before (edge 2.83:1) After (edge 4.59:1)
1440 before 1440 after 1440
390 before 390 after 390
Secondary action, 1440 before action after action

Storybook frames, rendered from the prepared Storybook assets at ba68022bb (simulated UI evidence). They were committed in 05ba56f91 and removed again in 586036171; the links below point at 05ba56f91.

Story 1440 390
Invalid Configuration JSON after invisible characters 1440 390
The error line, close up error 1440
New version failed, deploy again (recovery card) recovery 1440 recovery 390

Walkthrough video (15 s, webm, simulated UI evidence from the prepared Storybook assets with this branch's CSS):

  • the story Invalid Configuration JSON after invisible characters, showing the column 18 error with the stray x selected;
  • then New version failed, deploy again, with keyboard Tab focus moving to the secondary action Open v7 Logs.

It was committed in 4cd9b0b7b and removed again in 595569598: walkthrough.webm.

All media here is attached natively and absent from the landing diff. The before/after images are the historical fixture captures identified above. The video capture commit and reviewed head 595569598 have identical trees outside the evidence path. These are simulated UI states, not a deployed Agent or assistive-technology run.

Conflicts with open PRs

Conflict hunks of each PR merged with origin/main, compared with the same PR merged with this head:

PR Shared file main this head new
#2899, #2898 touched files 0 0 0
#2893 dom.mjs, console.css, scenarios.mjs 0 0 0
#2860 scenarios.mjs or agent-detail stories 0 0 0
#2518, #2505, #2502, #2253, #878 scenarios.mjs or agent-detail stories 11, 2, 6, 3, 2 same 0
#2833 create.mjs (not changed here) 0 0 0
#2409, #2258, #2255 create.mjs (not changed here) 15, 3, 5 15, 3, 5 0
#2599, #2596, #2524, #2445, #1619, #906 console.css 33, 0, 4, 4, 17, 5 same 0
#2259 production-kubernetes-packaging.test.mjs 1 1 0

This branch adds no conflict hunk. #2878, #2886, #2894, #2891, #2895 and #2896 landed during review (#2891 and #2896 had 0 hunks with this branch before they landed); this branch has merged main after them (90c63bf8e).

Review response (freeqaz-openai, 26d630c)

  • Count the other two Hangul fillers: 2c3fa4f24 adds U+115F and U+1160 to the exception, so it is now [\u115F\u1160\u3164\uFFA0]. The conformance cases check {"a": "p<FILLER>q", x} at column 14 for all four fillers, on both the Segmenter and the no-Segmenter path. With the old exception, U+115F and U+1160 report column 13 on both paths and the new cases fail. Dropping any one filler fails both paths and names that filler.
  • Finish the UI proof:
    • 1b4e4c48a updates the Storybook scenarios with the story Invalid Configuration JSON after invisible characters, next to the existing invalid-Configuration story.
    • The recovery card's secondary action is shown by the existing story New version failed, deploy again.
    • Screenshots are at 05ba56f91 and the walkthrough video at 4cd9b0b7b. Both are linked by SHA above and removed from the diff again in 586036171 and 595569598, preserved in the native attachments above.

Risks

  • The 1958 change is one border colour on recovery-card secondary actions; the primary action is untouched.
  • visibleLength runs whenever the JSON is invalid, including while someone is typing, and only on the line up to the error. It stays cheap. Measured for the whole jsonObjectProblem call on 2 CPUs: a 1 KB pretty-printed Configuration takes about 0.03 ms (0.02 ms before), and one 300 KB minified line takes about 28 ms (18 ms before).
  • \p{Default_Ignorable_Code_Point} needs ES2018 regex property escapes, which every supported browser has.
  • The tests are test-only otherwise. The 1954 tests hold requests with the shared holdRequests helper; there are no wall-clock windows.

Findings 1948, 1949, 1950, 1951, 1954, 1958 (bughunt-123).

…ce the harness is locked

Kills three surviving mutants from finding 1954 (bughunt-123): the Codex
suggestion under a locked harness, the token hint keyed on harness.disabled,
and pending counted as a lock.
…segmenter column fallback

Kills the three JSON scan mutants that survived the conformance file
(finding 1950, bughunt-123). The engine cross-check base now uses E, \/ and
CRLF, and its edit alphabet adds E, +, /, u and CR.
…ions

Zero-width spaces, direction marks, the soft hyphen, the word joiner and a
byte order mark earlier on the line each counted as a column, so the reported
column pointed past the error (finding 1949, bughunt-123). Default-ignorable
graphemes are now skipped, with and without Intl.Segmenter.
Deleting the focus call on the primary-model mismatch survived every browser
file (finding 1951, bughunt-123).
Deleting the /var/lock -> /run/lock entry from both the chart and the profile
renderer left both database CA mount tests green (finding 1948, bughunt-123).
/var/lock/../openclaw-worker is /run/openclaw-worker inside the image.
On the card's warning tint the input edge token was 2.83:1. The muted text
token gives 4.59:1 there (finding 1958, bughunt-123); the test reads the
painted colours and checks the ratio.
@freeqaz
freeqaz requested a review from a team as a code owner October 19, 2026 00:37
@clawsweeper

clawsweeper Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@freeqaz
freeqaz temporarily deployed to integration-qa-pr October 19, 2026 00:37 — with GitHub Actions Inactive
@freeqaz
freeqaz temporarily deployed to integration-qa-pr October 19, 2026 00:37 — with GitHub Actions Inactive
@clawsweeper clawsweeper Bot added clawsweeper:intake:bug Preliminary submission classification; full source review pending. clawsweeper:intake:needs-environment Preliminary submission classification; full source review pending. clawsweeper:intake:needs-repro Preliminary submission classification; full source review pending. P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed clawsweeper:intake:bug Preliminary submission classification; full source review pending. clawsweeper:intake:needs-environment Preliminary submission classification; full source review pending. clawsweeper:intake:needs-repro Preliminary submission classification; full source review pending. labels Oct 19, 2026
@clawsweeper

clawsweeper Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge.

What this changes

This PR corrects JSON error columns around invisible characters, strengthens recovery-button borders, and adds focused regression coverage.

Example: Configuration JSON contains {"name": "a<LRM>b<SHY>c<WJ>d", x}, with the named marks represented by their actual Unicode characters.

  • Before: The error reports column 21.
  • After: The error reports visible column 18.

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) Focused implementation, distinct regression coverage, and direct visual evidence support landing; the supplied UI evidence appropriately claims simulated behavior only.
Proof confidence 🐚 platinum hermit (4/6) This collaborator-authored PR is outside the ordinary contributor proof gate; inspected native screenshots show the changed console diagnostics and recovery border in simulated UI states, while walkthrough playback was unavailable in the review environment.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Product

Kind: Bug fix · Worth it: Yes · Fix scope: Complete
User problem: Invisible characters shift JSON error locations, and secondary deployment-recovery controls have insufficient border contrast.
Reason: The maintainer-authored direction repairs concrete diagnostic and accessibility defects without adding configuration, contracts, or deployment behavior.

Merge readiness

✅ Ready for maintainer review

This PR resolves both prior findings and retains useful diagnostic, accessibility, and regression-coverage improvements; no actionable patch defects remain.

Priority: P3
Reviewed head: 5955695985b0a07e22bbf5c6a71eedb4c696c977

Before merge

None.

Findings

None.

Agent review details

How this fits together

The controller serves a console whose shared JSON helper converts invalid Configuration input into field feedback and whose stylesheet presents deployment recovery controls.

flowchart LR
  User[Console user] --> Editor[Configuration editor]
  Editor --> Diagnostics[Shared JSON diagnostics]
  Diagnostics --> Feedback[Field error and position]
  User --> Recovery[Deployment recovery controls]
  Tokens[Console design tokens] --> Recovery
Loading

Technical review

Best possible solution:

Land the focused fixes and regression coverage with the existing diagnostic, stylesheet, and packaging owners.

Do we have a high-confidence way to reproduce the issue?

Current-main source establishes both defects, and the PR records baseline failures for invisible-character columns and border contrast; no target code was executed during this review.

Is this the best way to solve the issue?

The patch extends the existing column-counting helper and reuses an existing color token, while the tests protect independently observable regressions.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 90c63bf8e7c2.

Provenance checked

  • Visible JSON error columns keeps the original intent (09f7545: Report positions as readers see characters, independently of engine-specific UTF-16 diagnostics.)
  • Recovery-action border token changes intended behavior with a stated reason (39dead5: Replace raw colors with shared design tokens; this PR explains that the selected border token falls below 3:1 against the warning tint.)

Testing

Proof path: in-process harness.

Security

None.

Evidence

What I checked:

Likely related people:

  • Free Wortley: Raw commit 09f7545 adds apps/controller/src/console/dom.mjs:319 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 09f754513b23; files: apps/controller/src/console/dom.mjs)
  • Eric Cai: Raw commit 839abfa adds tests/integration/production-kubernetes-packaging.test.mjs:3087 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 839abfa12358; files: tests/integration/production-kubernetes-packaging.test.mjs)

Review metrics

Metric Value Why it matters
Production versus regression coverage Production +16/-11; tests +224/-8; Storybook +20 The added coverage protects distinct failures without introducing production test seams or another runtime owner.

Labels

Label changes:

  • add proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence.
  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster. Replaced prior rating: 🦪 silver shellfish.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR.
  • remove rating: 🦪 silver shellfish: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.
  • remove status: ⏳ waiting on author: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P3: Focused diagnostic and accessibility polish with limited runtime impact.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🐚 platinum hermit and patch quality is 🦞 diamond lobster. Replaced prior rating: 🦪 silver shellfish.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

History

Review history (1 earlier review cycle)
  • reviewed 2026-10-19T00:51:57.024Z sha 851bb69 :: needs changes before merge. :: [P3] Remove committed verification images from the landing diff | [P3] Extend the existing Storybook scenarios for the changed UI behavior

Reviewed October 18, 2026, 11:03 PM ET / October 19, 2026, 03:03 UTC (Revision 2).

…aracters

The error names column 18, the visible position of the stray x, after a
left-to-right mark, a soft hyphen and a word joiner (finding 1949).

@freeqaz-openai freeqaz-openai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Free's clanker here. I verified the PNGs are out of the landing diff and ran the exact-head JSON conformance file (13 passed). The invisible-mark correction is useful. I found one small regression in the Hangul exception, plus the two remaining publication steps below.

Count the other two visibly advancing Hangul fillers. In {"a": "p<FILLER>q", x}, either U+115F (choseong filler) or U+1160 (jungseong filler) makes this head report column 13. Current main reports 14. In sandboxed Chromium I imported this exact dom.mjs, applied the PR's .configuration-editor CSS, and measured the range of the offending x in text laid out with that computed font. Each filler advanced it by 12 px, just like the already-excepted U+3164 and U+FFA0. By contrast, an LRM or word joiner advanced it by zero, and the PR correctly reports 13 there. This is evidence about the editor font on this browser, not a claim that a display column equals a fixed pixel width or that all fonts render alike.

The narrow correction I checked was [\u115F\u1160\u3164\uFFA0] in the existing exception. Please add the first two to the current table of cases; both Segmenter and fallback paths discriminated the regression. No generalized text-width engine is needed.

Finish the existing UI proof, rather than redoing unrelated tests. Claw's previous review requested updating the existing invalid-configuration story and recovery walkthrough; this head still changes neither. The body links six raw PNGs in a historical commit, not the required native screenshots and short video. Please attach those on the corrected head; do not put the media files back in the diff. One fresh Claw review after the correction is enough.

…ON error column

U+115F and U+1160 advance the text like U+3164 and U+FFA0, so a stray x
after them is at column 14, as on main. The conformance cases cover all
four fillers with and without Intl.Segmenter (review of finding 1949).

@freeqaz-openai freeqaz-openai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Free's clanker here. The Hangul column correction I requested is fixed at 595569598. The head advanced while I was checking; this is the new version, not the earlier media-removal commit.

I matched both Git blobs and ran the owning file: all 13 tests passed. Restoring only the old two-filler exception made both the Segmenter and fallback tests fail at the intended assertion, column 13 instead of 14. This agrees with the editor measurement, without turning column reporting into a font-width engine. I also verified the invisible-characters Storybook scenario and that the screenshot and video files are out of the landing diff.

This clears my source change request. Please finish the native screenshot/video attachment described in Verification and receive current-head CI and ClawSweeper before landing. This approval does not bypass either.

@freeqaz-openai

Copy link
Copy Markdown
Collaborator

@clawsweeper re-review

Corrected source 595569598; the requested Storybook scenario and native screenshots and walkthrough are now in Verification. I downloaded all 12 attachments and matched their bytes; the walkthrough commit and review head have identical trees outside the evidence file, which is absent from the landing diff. Required CI is green; I separately verified the hosted 2,599-case conformance/baseline and 364-case browser results against the tested tree. Please review this revision.

@clawsweeper

clawsweeper Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
Exact review queued.

Re-review progress:

@freeqaz
freeqaz merged commit 4aa8296 into main Oct 19, 2026
48 of 49 checks passed
@freeqaz
freeqaz deleted the ux-fixes-123-tests branch October 19, 2026 03:06

This branch had an error being deployed

1 failed deployment
integration-qa-pr — 59556959 Deployed Oct 19, 2026 by freeqaz via QA advisory (OpenShell) #2442
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants