Skip to content

Fix/editor chrome numeric field border - #5

Merged
pdjdev merged 165 commits into
build/osxfrom
fix/editor-chrome-numeric-field-border
Oct 19, 2026
Merged

pdjdev merged 165 commits into
build/osxfrom
fix/editor-chrome-numeric-field-border

Conversation

@pdjdev

@pdjdev pdjdev commented Oct 19, 2026

Copy link
Copy Markdown
Owner

No description provided.

niksedk and others added 30 commits October 17, 2026 14:24
…detection)

Video > More > Sync subtitle to audio finds one offset for the whole
subtitle - and a frame rate mismatch, if any - by cross-correlating the
subtitle's shown/not-shown signal with a speech/silence signal made from
the waveform peaks, the way ffsubsync and alass do. The FFT correlation
covers every shift at once, so a feature film takes a second or two for
all eleven frame rate ratios between 23.976, 24, 25, 29.97 and 30.

The confidence shown is the prominence of the correlation peak above a
moving baseline (the raw correlation swells with how much is said in each
part of the film). On two sitcom episodes a complete in-sync subtitle
scores 73-100 %, half of it 65 %, its last third 28-61 %, and the other
episode's subtitle 0 %; below 25 % the dialog warns. A subtitle can also
be synced against another subtitle file that is already in sync.

The result is applied as one undo step, like Change frame rate. The
dialog analyzes on open when the waveform exists; without a waveform
only the subtitle reference is offered.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A heavy period and a short dash are both a solid blob, and the loose passes'
top-margin tolerance let a dash entry claim the period at the end of a line
(137 lines ending "word-" in a Russian Blu-ray sup). Polish dialogue dashes
went the other way and were read as ".".

GetMatch now works out where a small mark sits relative to its line's baseline
(only when at least three glyphs in the line are 1.5x taller, so a line of only
marks is left to the pixels):
- on the baseline: no dash/degree/caret candidates; a quote shape is a comma
  or low quote
- above it: no period/ellipsis/underscore candidates; a comma shape is an
  apostrophe ("we,ve" -> "we've")

The placement is part of the match cache key. On the sample sups only these
characters change: Russian PGS 156 x "-" -> "." and one „ -> ", Polish 165 x
"." -> "-", French 2 x "," -> "'"; English, Danish, Dutch, German, Italian,
Spanish, Swedish and Rus.sup are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ture-gaps-79e6b0

Video: Sync subtitle to audio (ffsubsync-style offset and frame rate detection)
Text boxes, combo boxes, number fields, list boxes, table views and trees
get the editor field color, the field border and rounded corners from one
app-wide style (UiTheme.ApplyFieldStyle), so they match the Show/Duration
fields and the editor-look windows. The combo box arrow uses the same
blue-gray. Classic and Pastel keep their own field colors.

Lists in an editor list frame drop their own border (the frame draws it),
and the ASSA styles editor uses the shared window styles for its combo
boxes and text boxes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ot-dash-baseline

nOCR: tell period from dash (and comma from apostrophe) by the baseline
In the thick outlined, rounded font of a Russian Blu-ray sup, the upright "Б"
is wider (aspect 117%) than every trained "Б" (143%+), so the aspect gate shut
all of them out while a small "в" entry got in on its scaled error budget; the
case fixer then made it "В" ("Вак", "Воже", "Веги"). Font training can't
reproduce the face (the trainer reads its heavy-font renders correctly, and the
installed rounded font has no Cyrillic), so the two new entries are cut from
real glyphs of that file, with discriminative lines against real "В" glyphs from
the same file so they don't claim them.

Russian - Track09_PGS.sup: 68 x "В" -> "Б", all correct (Вак -> Бак 35,
Будь, Бертон, Беги, Боже, ДОБРО, БЕЗБОЛЕЗНЕННОЕ, ...); every remaining "В"
word is a real one. Rus.sup output is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In the thick outlined font of a Russian Blu-ray sup, the italic "0" (30x42) fits
no trained italic "0" (best 17-22 wrong pixels), so small italic "в"/"а" entries
won on their scaled error budget and "2000" came out as "2ВВа". Two italic "0"
entries cut from real glyphs of that file, with discriminative lines against the
real italic "в", "о" and "а" from the same line.

Russian - Track09_PGS.sup: exactly the four amounts change (2ВВа -> 2000,
22Ва -> 2200, 25Ва -> 2500, 28Ва -> 2800); Rus.sup is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…look-everywhere

One field look for text boxes, combo boxes and lists
…yrillic-be-ve

Cyrillic.nocr: read heavy rounded Б as Б, not В
…yrillic-italic-zero

Cyrillic.nocr: read heavy italic 0 as 0, not В/а
…ample

Three groups of misreads in a thick outlined Russian Blu-ray sup:

- Italic "ы" came out as "ъ/", "ъЇ", "ьЇ": the soft-sign half read as a hard
  sign and the bar as "Ї"/"/", so the ы composition (ь + dotless bar) never
  fired. It now also accepts "ъ"/"Ъ" and an "і"/"ї"/"Ї" reading of the bar
  (the same-height/same-top check still keeps a real dotted і out). Italic "ь"
  on its own read as "ъ" (волчъю, прелестъ): two italic "ь" entries cut from
  real glyphs, discriminated against heavy italic "ъ" renders and a real "в".
- The source text is ",.." (comma, period, period), read as "„." and ",,.":
  a "„" match now needs both parts to hang below the baseline, and a "comma"
  that doesn't hang and is about as wide as tall is a period.
- "*" were touching pairs, not "ж": entries cut from real glyphs for "кл"
  (italic + upright), "кж" and "АЯ" (проклят, также, ПАРОХОДНАЯ).

Sample sups vs main: Russian PGS - every "ъ/"/"ъЇ" is now "ы", 32 "ъ" -> "ь",
all 42 "„." -> ",..", all 7 "*" resolved, line-final ",": "." fixes; Rus.sup
1 "," -> "." (image shows a period); Polish 68 "," -> "." (line-final periods,
"15.00"); English, Danish, Dutch, French, German, Italian, Spanish, Swedish
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gs-yery-ellipsis-zhe

nOCR: heavy italic ы/ь, ",.." and touching letter pairs (Russian PGS)
- Color dialog finds the editor through a per-window ImageColorSource
  registry instead of depending on MainView and scanning the visual tree
- Selection mode starts focus on the frame (OK is disabled until a pick)
- Drop the extra pause; read the position after ShowDialogAsync pauses
- Grab the frame with ffmpeg in the background; picking waits for it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A relative input pattern with commas is treated as a list ("a.srt,b.srt"), so
"00800 - 22 - Subtitle (PGS), English, 1792 captions.sup" became three patterns
matching nothing: "No files found matching pattern(s)". Keep the entry whole when
it names an existing file; rooted paths were already kept whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y needs a gap

Four geometry checks from running Latin.nocr over 125 English Blu-ray/DVD sups:

- p/P: same shape; the case fixer now picks by the baseline - only "p" hangs
  below it ("oPPonent", "uP", "keeP"; mid-sentence "Power" -> "power").
- Expanded accented letters ("û" as "u" plus a separate "^") must have every
  part but the letter above the letter's top. Two bars side by side ("ll") or a
  bar and an apostrophe ("I'") fitted slanted "û"/"ù" entries ("aû", "ùm").
- "ì"/"Ì" must clearly beat "i"/"I": a round dot of an untrained font read as a
  grave all through English text ("thìs", "ìs", "wìll"). Only the grave i; "í",
  "Á", "Å" are everyday letters and keep their accents.
- "i", "j" and their accented forms need a gap or a neck between the dot/accent
  and the stem: a slanted italic "l" fitted italic "ì"/"Ì" ("shouìders"), a "t"
  read as "i" in Polish ("Wszysiko iylko" -> "Wszystko tylko"), "l" as "j" in
  Dutch ("Veej" -> "Veel"). A neck (rounded bold fonts whose stem corners reach
  into the gap) still counts, so those "i"s stay "i".

English set (124 files, sample_missing_lines.sup excluded): unknown words
15.8% -> 9.0%. Language samples: Polish 281 + 61, Dutch 215, Italian 3 fixes;
Danish, German, Spanish, Swedish, English, Russian unchanged; French changes
only text that was already wrong. Same speed as main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-comma-file-names

seconv: don't split a file name with commas into patterns
VobSub colour isolation (on by default) hands the OCR engine an opaque
black-on-white bitmap. nOCR and BinaryOCR split letters on the transparency of
the original, so every subpicture became one blob read as "*": a VobSub .sub
came out as 715 of 720 lines "*", a DVD .sup as 97 of 97. PGS isolation already
skips these engines for the same reason; VobSub/DVD sup now does too, in seconv
and in Batch convert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…atin-geometry

nOCR (Latin): p/P by baseline, accent parts above the letter, i-family needs a gap
…-isolation-nocr

seconv/Batch convert: no VobSub colour isolation for nOCR and BinaryOCR
"0" and "O" are the same ring in most subtitle fonts and nOCR/BinaryOCR decide
each glyph alone. In the text they produce (ItalicTextMerger, shared by the app,
Batch convert and seconv):
- a run of digits and capital O's with at least one digit is a number
  ("5O", "1OO", "1O:3O", "1,OOO", "2O04");
- a lone "0" in a word of letters with no other digits is a letter ("0f", "t0",
  "g0t", "N0t", "0kay"; capital at a sentence start or in an all-caps word).
  Words with more zeros than letters stay ("З000" is 3000 with a misread 3).

English sups: 151 "O"-in-number cases in 47 files; Dutch/Polish/Italian samples
gain "Onze", "Ostatecznie", "2004", "3:00".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…igit-letter

OCR: settle 0/O from the neighbours ("5O" -> "50", "g0t" -> "got")
Two letters drawn touching ("av", "tt", "ay", "As", "wt") are one glyph that
fits no entry, so it came out as "*" or as a loose last-ditch guess ("h*e",
"beuer", "alwUs"). Cut it at one of the thinnest columns of its middle half,
trim both sides to their ink and match them strictly; one side may itself be
a touching pair. The pair wins over a last-ditch guess only if both halves fit
better than the guess. Halves must be letters (or both digits - an "M" cut in
two read as "b1"), and a "w" cut in two ("vv") stays "w".

English set: 262 words fixed, 6 lexicon-"worse" that are right ("Eww.",
"Aww.", "(DRAX"); unknown words 8.62% -> 8.57%, "*" 2607 -> 2336. Samples:
Spanish "o*sión" -> "ocasión" (64 lines), Danish "Ma*ell" -> "Maxwell",
Russian "наверту" -> "наверху", "Ляске" -> "Аляске".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…plit-touching

nOCR: read a glyph that matches nothing as two touching letters
The random line generator skips the neighbour check on glyphs of 10 px or less,
so lines on a dot ran along its anti-aliased rim. They fit at the trained size
but missed the rim at other sizes: a "." trained at 50 px read as "*" at 100 px
for ~70% of trainings (29 of 40 seeds), which made
TrainedDb_RecognizesTextAtTwiceTheTrainedSize flaky. For glyphs under 150 px
area the trainer now keeps only the lines that also fit the glyph rendered at
1.5x and 2x (falls back to all lines if too few survive).

Also thread an optional Random through line generation
(NOcrTrainerSettings.RandomSeed, GenerateLineSegments overload) so tests can
train deterministically; the default stays Random.Shared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The case fixer kept an accented capital when the glyph was taller than the
average capital + 3 px - but the grave on a lowercase "ì" also reaches that
high, so Italian came out as "cosÌ", "lÌ", "piÙ", "perÒ". With the line's
baseline known, compare the height above it to the cap height instead: an
accent on a capital stands well above it (> 1.18x), one on a lowercase letter
about reaches it. A cedilla hangs below, so for "Ç"/"ç" the body tells: x-high
or cap-high. Without a baseline the old rule applies as before.

Italian samples: 101 "Ì" -> "ì", 42 "Ù" -> "ù", 34 "Ò" -> "ò" in one file, 33 in
another; the other two unchanged. English unchanged apart from 8 "Ì" -> "ì" in
an already-wrong word; Dutch/French only "Í" -> "í" in lines already garbled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mall-glyph-cross-size

nOCR train: fix flaky cross-size match of small glyphs (dot)
…ccent-case

nOCR: case of accented letters from the height above the baseline
…sition

A curly apostrophe is a raised comma, but the comma entries sit at the
baseline and there is no curly apostrophe entry, so the top-margin gate kept
every candidate off it: "don*t", "Let*s", "You*ll". A small mark that matched
nothing is now tried against the comma and apostrophe shapes without their
trained position; where it sits then decides what it is (raised comma ->
apostrophe, as before).

English set: 58 words fixed, none worse ("don't", "Let's", "you've", trailing
"Master,"). Polish: 11 "*" -> correct commas. Other samples unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
niksedk and others added 28 commits October 19, 2026 06:43
SE 4 compared the file's write time at save time and asked "File on disk
modified, overwrite?" before writing. SE 5 only asked on window activation
whether to reload, and a Ctrl+S afterwards silently overwrote whatever the
other program had written (SubtitleEdit#16216).

Save now compares the file against the stamp SE took when it last read or
wrote it and asks before overwriting. The auto-save timer never shows a
dialog, so it skips that round with a status bar line instead.

Answering "No" to the reload prompt used to move the stamp to the outside
version, which would have hidden the change from the save check. The
declined change is now remembered separately: it is not asked about again
until the file changes once more, while the stamp stays at SE's own version.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
"Reverse RTL start/end" (the default mode) moves the punctuation of every
line from the end to the start, and "Fix via Unicode" wraps every line in
RTL control characters. Both are meant for Hebrew/Arabic subtitles in
players without bidi support; on English text they just scramble it. A user
who left the box ticked got ".Hello world" in 26 English files.

The batch function (and the matching seconv operations) now leave a subtitle
alone when none of its lines contain a right-to-left letter. The whole
subtitle is checked, not just the first lines, so an RTL subtitle that opens
with Latin credits is still processed. "Remove Unicode control chars" is
harmless on Latin text and still runs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Fixes SubtitleEdit#16215: adding 20 words meant 20 rounds of "New rule", each from a
context menu, and the new rule at the end of a 500-rule category was
selected but out of view.

- New "Add rules..." window (toolbar, context menus, Ctrl+Shift+N): type
  find/replace, Enter adds the pair and returns to "Find what", OK adds
  the list to the category (after the selected rule, or at its end).
  Type and whole word stick between rules and start as the neighbour's.
  Double-click a row to correct it, Delete removes it, Cancel asks before
  discarding an entered list.
- Toolbar "New rule" button, so a rule no longer needs a right-click.
- New and inserted rules scroll into view (NavigateToRule).
- F2 edits the selected rule / renames the category; Ctrl shortcuts also
  accept Cmd on macOS; the context menus show the gestures.
- Help page and headless tests.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rogram

Since SubtitleEdit#15828 the open file is reloaded on window activation when SE has
no unsaved changes, and the user is asked when it has. SubtitleEdit#16216 wants to be
asked every time, so Settings > General gets a three-way choice:

- Reload if nothing is unsaved, otherwise ask (the default, as before)
- Always ask - the question says "Reload it?" when nothing would be lost
- Do nothing - the subtitle is left alone; saving over the outside change
  still asks

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Per SMPTE 334-2 a caption distribution packet may carry a time code
section (id 0x71 + 4 bytes) between the cdp header and the cc_data
section (0x72). The parser read cc_data at the fixed offset 10, so such
packets threw in GetAllCcData and the whole MCC file loaded empty (and
embedded nothing in remux) without any error.

- Smpte291M(byte[]): when time_code_present is set and 0x71 follows the
  header, store the four time code bytes in CaptionDistributionPacketTimeCode
  and continue at index 15; footer/service-info arithmetic now uses a
  running index.
- Tolerate a cc_data section that is not at the expected offset by
  scanning forward to 0x72 instead of reading garbage.
- GetBytes: emit the time code section when present, and skip the
  service info section when the parsed packet has none (previously a
  NullReferenceException), so parsed packets round-trip byte for byte.
- Tests: MCC line from the fixture with an inserted time code section
  yields the same cc_data; flag-only packets still parse; writer
  round-trips with and without the section and keeps the flag off for
  packets it generates itself.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…le-replace-shortcuts-window-89851c

Multiple replace: "Add rules" window for entering a list of rules
…Edit#16219)

The typing auto-wrap (SubtitleEdit#16087) rewrapped any single line longer than the
profile limit on the first typed character, so a line that was already
too long when it landed in the edit box - a freshly opened file, or a
profile that lowered the limit - got broken as soon as it was edited.
The reporter saw that as SE5 breaking lines on open / profile switch.

Measure the tag-stripped length in the tunnel pass, before the TextBox
inserts the input, and only wrap when the line was within the limit
before the keystroke and over it afterwards. Already-long lines stay as
they are until the user breaks them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The convention scan (InitialFocusConventionTests) flags focus set from an
Activated handler, which re-focuses on every Alt+Tab back into the window.
Use UiUtil.FocusOnFirstActivation like the other dialogs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Broadcast Scenarist/MacCaption files carry the time of day, usually from
01:00:00:00, while the video they are remuxed into starts at zero - so the
captions landed an hour past the end of the video and never showed (SubtitleEdit#16220).

The Remux video dialog gets a "Caption offset" field, shown when the subtitle
files become closed captions in the video (.mpg, or .mp4 with CEA-608 in
video). It is taken off every caption time; captions that would come before
the video are dropped. It is suggested automatically when the first caption
of the first file lies at or past the end of the video and starts at a whole
hour: 01:00:00:00 gives 1 h, 00:59:58:00 gives nothing. A value the user
types is kept.

libse: ClosedCaptionBytes.Shift(milliseconds) moves CEA-608 slots and
CEA-708 triplets, ClosedCaptionBytes.GetFirstTimeCode(file) reads the first
timecode of an .scc/.mcc, SccBytePairs.Shift does the slots. Tests embed the
01:00:00;01 scc_16038_pop_on.scc fixture into the 6 s H.264 sample with a
1 h offset and read the captions back near the start.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…uard-file-changed-outside

Ask before saving over a subtitle file changed outside Subtitle Edit
…hanged-outside-setting

Setting for what to do when the subtitle file is changed by another program
…clean-0d01d3

MCC/SMPTE 291M: parse CDP packets with an optional time code section
…-layout-zoom-16213

Keep imported layout sizes and waveform zoom after a settings import
…or-updates-settings-gear

Check for updates: settings gear for startup check and release channel
…nctuation-errors-c8a7bb

Batch convert: skip "Fix right-to-left" on subtitles without RTL text
…reak-newlines-1e63db

Auto-wrap while typing: leave pre-existing long lines alone (SubtitleEdit#16219)
…caption-offset

Remux video: caption time offset for broadcast .scc/.mcc files
…tleEdit#16233)

The redesigned windows (EditorChrome) carried a fixed blue-tinted dark
palette (#1E1F24 / #24262C / accent #4C6EF5) next to the neutral gray
main window built from the dark background color setting (#212121), and
their buttons used a different blue than the grid selection.

The palette is now derived: the dark surfaces step from the user's dark
background color (neutral gray by default, a tinted base keeps its
tint), the light surfaces from the Light/Classic/Pastel window color,
text and icon grays from the base lightness so contrast holds, and the
accent is the theme's SystemAccentColor (Pastel's violet, the OS accent
on Windows), with a readable on-accent text color. Brushes re-read the
settings on the next read and are refreshed from SetCurrentTheme and on
OS light/dark switches, so open windows repaint after Settings OK/Apply.

The ASSA draw canvas accent follows the same color.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…leedit-themes-fb2aad

Editor chrome palette follows theme settings and system accent (SubtitleEdit#16233)
)

The Qwen3 ASR CPP engine had a fixed model list and no way to use a model the
user already has. It now implements the custom-model interface: "Add custom
model..." accepts a qwen3-asr.cpp '.gguf' file and any extra '.gguf' in the
models folder is listed in the dropdown, like whisper.cpp custom models.

Several unrelated projects publish "Qwen3-ASR GGUF" files and only the
qwen3-asr.cpp layout (audio encoder + LLM in one file, architecture "qwen3-asr")
works with the shipped binary; llama.cpp (LLM + mmproj), transcribe.cpp and
CapsWriter-Offline (ONNX encoder + decoder-only GGUF) use different layouts and
the engine just crashes on them. A new GgufHeader reader in libuilogic parses the
header without touching tensor data, and Qwen3AsrCppModelValidator rejects the
foreign layouts up front with a message naming compatible downloads.

Also: the custom-model file picker filter and help text now come from the engine
instead of being hardcoded to whisper.cpp '.bin', and Download does nothing for a
custom model without URLs instead of throwing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…leedit-issue-16232-f96eed

Speech to text: custom GGUF models for Qwen3 ASR CPP (SubtitleEdit#16232)
Pin support-files release audiocpp-indextts25-2026-10-19, built from
upstream 0xShug0/audio.cpp 507495611b22dc4590e0e5609e05e8096384e33f
(tag v0.9.2-drama3-base-small) with the same nine families as 2026-10-16b.

A seeded KugelAudio request on an M4 (Metal) was byte-identical between
the 2026-10-16b build, the new build and upstream's own prebuilt binary.

Also refresh the stale "upstream ships Windows prebuilts only" comments:
upstream has shipped prebuilt archives for every platform since v0.9.0,
but we keep our own composite build because upstream's Windows CPU and
Vulkan builds are tuned to the CI runner they land on (v0.9.1/v0.9.2
carry AVX-512 code) and its portable variants have no AVX2.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A new configurable waveform toolbar item, "Rule profile": a sliders icon and a
slim borderless drop-down of the profiles from Settings > Rules, styled like the
audio-track picker. Choosing one applies it exactly like the Choose profile
shortcut does, and the picker follows profile changes made in Settings or in
the Choose profile dialog.

Applying a profile now also refreshes the grid's CPS / line-length colouring
and the waveform's minimum gap, which the Choose profile dialog left showing
the previous profile's values until a row was edited.

The item is hidden by default (Configure toolbar items... in the waveform
"More" menu), so an upgrade does not change an already tuned toolbar.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…cpp-update-a734b0

Bump audio.cpp runtime to v0.9.2-drama3-base-small (2026-10-19)
…rm-toolbar-profile-select-9c50d4

Waveform toolbar: compact rule-profile picker (SubtitleEdit#16236)
Bump the version in Se.cs and English.json (regenerated, picks up the
new strings from SubtitleEdit#16182, SubtitleEdit#16192, SubtitleEdit#16225, SubtitleEdit#16227, SubtitleEdit#16228, SubtitleEdit#16231, SubtitleEdit#16235
and SubtitleEdit#16238) and add the change-log section for everything merged since
the v5.4.0-beta1 tag (PRs SubtitleEdit#16178-SubtitleEdit#16238).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ta-release-4cd8d2

Prepare v5.4.0-beta2 release
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T14:31:10.039051Z fd02ff1 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pdjdev
pdjdev merged commit 71508a9 into build/osx Oct 19, 2026
1 check passed
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.

8 participants