Repository navigation
fix: full app review — editor, menu bar, settings, domain, web/CLI, docs and screenshots - #251
Merged
Merged
Conversation
… restore behavior
…xt off the keystroke path
…ocks The grid emulator now fills erased, inserted and scrolled-in cells with the current SGR background (bce), so TUI color bars and theme backgrounds reach the right margin. The routing scan no longer stops at a CSI interrupted by a control byte. Line mode keeps a line after a carriage return until something is drawn or erased there, so script's \r\r\n output survives. Cursor up/down moves between emitted lines, so log-update style redraws keep only the final frame. Erases keep SGR and OSC escapes, and backspace removes a glyph instead of escape bytes. TerminalScreen.plainText() had no production caller and moves to the tests; the routing table in ARCHITECTURE.md now documents the repeated ED 2 trigger.
Decoded images now take their point size from the file's DPI, so a 144-DPI Retina screenshot lays out at half its pixel size and exports 1:1 at @2x instead of being upsampled. Image reads go through BoundedFileReader (non-blocking open, descriptor type and stability checks) instead of a separate FileHandle loop. The pixel budget is a single ImageDecodePolicy function that the import tests now exercise directly; the unused decodedByteCost helper and the duplicate validateImageDimensions are removed.
… / => assignments
Scanner accepted a 0x prefix and leading whitespace that the length check counted, so 0x1E1E1E decoded as a nearly transparent color. RGBAColor and HexColor now use the same ASCII-only parser.
Recipe import decodes the style strictly, so a string font size or an unknown background kind fails with its JSON path instead of silently falling back to a default. Presets and preferences keep the tolerant decoder.
…xt and LineSplitter.plainLines
- Read --stdin in bounded chunks and report oversized stdin or files as inputTooLarge instead of "could not read". - Refuse an --out image (not only sidecars) that would overwrite the source, a background image, or a watermark logo. - Batch discovery runs before the output folder is created and skips the output folder, manifest, and skipped report, so re-runs do not render earlier artifacts; render failures keep their typed reason. - --edit rejects theme and output options the handoff cannot carry, carries --terminal-width as a columns hint, and fails on empty sources. - --copy with --out writes the file first and copies that raster; clipboard-only copies reject a non-PNG --format and report png. - Locate fonts and the enclosing app through the dyld executable path, not argv[0]. - Usage errors exit 2 and print usage; runtime errors exit 1 with only their message. A second positional is an unexpected argument. - --alt-text requires a Markdown or HTML sidecar; help text for --profile and terminal-capture matches the parser.
…cribed - Network quiet now counts in-flight fetch/XHR from document start and waits for an idle window with no new resources, instead of returning about 0.4 s after load. - The sign-in window hosts popups in their own windows, answers HTTP Basic/Digest/NTLM challenges with a credential sheet, and shows the page host and whether it is fully secure. - Production URL capture uses the tested URLRenderer.configured mapping. - HTML mode hides capture options that HTML rendering ignores. - The capture caption no longer claims nothing is sent to a server. - Image-backed social cards export with the same opaque matte as snapshots, in raster and PDF. - Raster-backed PDFs (Web Snapshot, comparison boards) use point-sized pages. - Export all sizes encodes off the main actor, honors the export format, names files from the real capture size, and never overwrites. - Toolbar tooltips and labels are localized; "%lld slides" has an English plural. - The unreachable disabled-disclosure branch is removed.
Menu bar - Return focus to the previous app after a panel action or the history consent alert, so the next paste lands there. - Relaunch to Apply passes the old process id, so the single-instance guard no longer quits both instances; terminated processes are ignored. - Refresh the panel's hotkey chip on every open and name what the hotkey runs. - Announce capture HUD results to VoiceOver (failures with high priority). - File > Copy Image closes the editor under "Close the editor after copying". - Services renders with the Export scale, color profile, and destination size. - Close the panel before running a capture so a modal alert keeps Escape. - Anchor the helper's panel on the icon; label the in-process status item. - Show the newest captures in the panel; say when history is off; use the pinned-capture warning for Clear All. - Localize the Recents title, diagnostics panel, Services and automation errors; report a failed diagnostics export. - View > Theme shows a checkmark and custom themes; Check for Updates is validated against Sparkle and also offered in Settings > About. - Remove the unreachable Web Snapshot recovery action, the unused editor shortcut name, and the production-only test wrapper; compile memory-journey hooks in Debug only. Settings - Route captions, tooltips, panels, and import errors through the String Catalog, including domain summaries and messages. - Report why a license activation failed with a specific message. - Show the real launch-at-login status after a change, with an approval link. - Add corner radius, shadow depth, and window title to the Style pane with value readouts and the persisted slider ranges; share one background control; fix the Brand Kit, Library, Help, and Reset copy. - Disable URL-only Input controls on builds without URL capture; confirm before clearing web data. - Offer the sudo fallback only for permission failures; pick the shell from the chosen startup file. - Keep a seat release running when the user leaves the About pane, with progress; show restore and pending-purchase results on the App Store build. - Make the free-placement handle adjustable from the keyboard and VoiceOver; announce disclosure state; label the Style sections. - Follow the system accent for focus rings and selected pills; drop stale and unused catalog entries; use consistent Spanish terms. Architecture - Add WindowPlacement for every window controller and fit the Comparison Board window to small displays. - Add one save-panel writer with a single atomic write policy. - Share one image-share route and inject feedback into ShareManager. - Add one image-copy helper that always reads clipboard privacy app-wide. - Remove `.shared` default arguments; tests build isolated settings. - Resolve the editor's window from viewDidMoveToWindow instead of polling. - Route activation through AppActivation using cooperative activation. - Use the batch-export folder picker for the documentation export.
…026-10 # Conflicts: # Vitrine/State/WindowState.swift # docs/ARCHITECTURE.md
…026-10 # Conflicts: # Vitrine/App/EditorWindowController.swift # Vitrine/Resources/Localizable.xcstrings
…e failure message
…a hotkey come forward
…ontrolled WebKit lane
…out of HighlightManager
…tings Auto-copy, save-to-file, close-after-copy, and clipboard concealment move out of ExportSettings into a new OutputBehavior store. The app-wide AppSettings creates the only instance; editor sessions reference it instead of seeding their own, so a window can no longer read a stale default. Make Default and EditorPreferencesSnapshot keep carrying only the per-capture output (scale, format, color profile, rich clipboard, text sidecar). All four image-copy paths (toolbar, File > Copy Image, menu-bar recents, recents gallery presets) go through RenderedImageCopy, which takes the config, the per-capture output, and the app-wide behavior. Persisted keys and values are unchanged, and a regression test covers an editor session copying with the app-wide conceal and close-after-copy preferences.
johnny4young
commented
Oct 6, 2026
johnny4young
left a comment
Owner
Author
There was a problem hiding this comment.
Review: full app review (editor, menu bar, settings, domain, web/CLI, docs, screenshots)
Size: 274 files, about +10.4k/−4.3k lines, 52 commits including worktree merges. I prioritized the parts with real logic or contract risk over copy, screenshots and the string catalog.
Verdict: ready. I found no blocking defects. There are four non-blocking inline notes, and #254 builds on this branch and should merge right after it.
Reviewed in depth (no defects found)
- CLI:
- Bounded stdin (
readBoundedStandardInputstops at limit+1). inputTooLarge, andunexpectedArgumentfor an extra positional.- With both
--copyand--out, the file is written first and the same raster is reused for the clipboard, so a failed write no longer replaces what the user had copied. --copyrejects a non-PNG--formatwhen there is no--out.--alt-textnow requires a sidecar.--editrejects output and theme options, refuses empty input, and passes the terminal width throughEditorHandoff.Payload, with thecolumnshint range-checked on both sides.- Batch discovery skips the output folder and report files and runs before the output folder is created.
_NSGetExecutablePathreplacesargv[0].
- Bounded stdin (
- Domain:
RGBAColor.hexComponentstakes ASCII-only hex and rejects0x/fullwidth digits.- SecretScanner: the new bearer, URL-credential and PGP rules. The URL-credential look-behind keeps scanning linear.
- LanguageDetector: JSON and Rust detection, and SQL now requires a statement verb plus a clause keyword.
- StyleSnapshot strict decoding is opt-in through
userInfo, so presets stay tolerant.
- Terminal:
- Erases and inserts now fill with the pen's background color (
bce), and padding to the right margin happens only when that color is set. ED 0from the origin snapshots the alt screen.isPopulatedignores colored blanks.- Scanner
continueon an aborted CSI:scanCSIalways advances (C0 abort returnscursor >= start), so the loop cannot spin.
- Erases and inserts now fill with the pen's background color (
- Images:
readBoundedImageDatanow goes throughBoundedFileReader, which adds FIFO and descriptor checks.ImageDecodePolicystill checks the frame count before the per-frame loop.
- Settings:
OutputBehaviorpersists under the same keys, so there's no preference migration or data loss, and editor sessions share the app-wide instance.resetToDefaultsresets the shared instance only from its owner.
- Web:
NetworkQuietTrackerlogic. The injected fetch/XHR counter clamps at 0, and a probe failure counts as busy.- HTTP auth sheet: password methods only, cancelled after 3 failures.
- Popup lifecycle, including re-entrant
windowWillClosethroughclosePopups(), which is safe becausepopupsis cleared first.
- Licensing:
LicenseActivationResultmapping. Deactivation now lives inEntitlements, so switching panes no longer drops its result. - Python QA scripts:
ruff check scripts qapasses. - CI: all 8 checks are green on
b3d7d8e: Linux static, Build & test and UI on Sequoia and Tahoe, WebKit integration on both, and GitGuardian.
Non-blocking notes (inline)
- 🟡
incompatibleOptionsnow exits 2 with the full usage text, even for conflicts found at run time against the filesystem (output overwriting an input, and #254's report conflicts). - 🟡 KVO observations for sign-in popups outlive closed popups.
- 🟡
.persistenceFailedalso covers "stored but not verified as PRO". - ℹ️ DPI-aware point size makes high-DPI foreground images lay out smaller. That's intended, but it's a visible change to call out in release notes.
Process notes
- At this size, a second human pass over the editor and undo changes (
EditorCommandResponder,EditorView*,AnnotationToolbar) is advisable. They're hard to verify statically, and I relied on the UI and screenshot-tour lanes for them. - Future review rounds would be easier to bisect as several focused PRs, which is the pattern #255–#259 already follow.
Generated by Claude Code
An output or sidecar that would replace an input or image resource is found against the filesystem, not in the command line, so it now raises CLIError.outputConflict (exit 1, message only) instead of incompatibleOptions (exit 2 with the usage text). The claim check folds case like the default macOS volume, so NOTES.md cannot replace notes.md; on a case-sensitive volume this fails closed.
Subtitle KVO observations for sign-in popups lived in one controller-wide array that was only cleared when the main sign-in window closed, so every closed popup left its observations (and the closures retaining its web view) alive. Each popup now owns its observations, invalidated when that popup closes.
This was referenced Oct 7, 2026
…ecipe themes - Compute the DPI-aware point size from the decoded, budget-bounded bitmap so a downsampled foreground image is never laid out larger than its pixels. - Reuse an earlier re-keyed copy when a recipe theme collides with a different local theme, so reapplying the recipe no longer adds a new copy each time. - Split asciinema casts only on CR, LF, and CRLF so events carrying a raw U+2028, U+2029, or NEL are not cut into invalid JSON fragments.
johnny4young
added a commit
that referenced
this pull request
Oct 13, 2026
…ocs and screenshots (#251)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A full review of the app (functionality, UI/UX, accessibility, localization, architecture, docs, and published screenshots), with every confirmed finding fixed in one branch. The CHANGELOG
[Unreleased]section has the user-facing summary.Editor
SettingsDefaults; secret scan reports "No secrets found" / "N lines redacted" and can rescan; labeled title fields and buttons; the scope note wording is fixed.BackgroundControlsandValueSliderreplace three copies across the inspector, Settings and the social card.Menu bar, quick capture, recents
Settings
Domain and rendering
\r\r\n, cursor-up redraws and escape bytes in erases.0x; language detection recognizes JSON and Rust and stops reading prose as SQL.:=/=>assignments. The URL rule's scheme is anchored, so a 1 MB dotted line scans in 0.3 s instead of 3.7 s.Web Snapshot, social card, CLI
--editrejects options it cannot carry and carries the terminal width;--copywrites the file first; the executable path no longer relies onargv[0]; usage errors exit 2.Architecture
WindowPlacementhelper for all windows (the comparison board window now fits small screens), one atomic save-panel writer, one activation path, injected stores instead of= .shareddefaults, and production uses the testedURLRenderer.configuredmapping.Docs and screenshots
editor.png,settings.png,menu-bar.png,annotated.png(the secret line is truly redacted; the blur covers an ordinary line) andog-card.png. A Debug-only--brand-accentlaunch hook keeps tour screenshots on the brand accent whatever the Mac's accent setting is.Found while verifying
NSApp.activate()is refused while another app stays active, which left windows opened from Terminal (render --edit), a hotkey, Services or Shortcuts behind it. Activation keeps the forcing call in one place, pinned by a test.ESC[H ESC[Jbefore exiting (current lazygit).fetchand a positive control.Completed after review
ExportSettingsinto one sharedOutputBehavior; editor sessions reference it instead of holding stale copies, and the four image-copy paths share one helper.CustomThemeRendererand the theme chrome lookups moved out ofHighlightManager.swift.docs/HELP.md.Verification
make lintpasses.make test: 1964 app tests plus the domain, rendering and repository suites, all passing.make test-web-capture(diagnostic host): 13/13 controlled WebKit tests, including the new network-quiet scenario.cd site && npm test: 58/58.Review follow-ups (2026-10-06)
Reviewed in depth with no defects found:
--copy+--outordering,--edithandoff;OutputBehavior(same defaults keys, so no preference loss);ruff check scripts qapasses.Applied:
11c97c5fix(cli): report output conflicts as runtime failures and fold case.CLIError.outputConflict(exit 1, message only) instead ofincompatibleOptions(exit 2 plus the full usage text).NOTES.mdcannot replacenotes.mdon case-insensitive APFS. On a case-sensitive volume this fails closed.982c47cfix(web): release sign-in popup observations with their popup. Each popup now owns its subtitle KVO observations; they are invalidated when that popup closes. Before, they were held in a controller-wide array until the main sign-in window closed, so they kept firing for popups that no longer existed.Not applied (follow-up): distinguishing
!persistedfrompersisted && !isProin the license activation message. It needs a new user-facing string with its Spanish translation. Both cases already fail closed (no PRO without verified state); only the wording differs.Validation of the new commits:
swiftc -parseandswift format lint --stricton every changed file (Swift 6.0.3 on Linux), andscripts/check-repository-hygiene.sh.Release note: foreground images now honor their DPI, so 144-DPI screenshots lay out at half their previous on-canvas size. This is already in the CHANGELOG.
Merge order: this PR first, then fix(cli): protect batch artifacts and skipped inputs during preflight #254 (retarget to
main; it already contains this head). fix(site): patch build-toolchain advisories in the website lockfile #260 (site build advisories) is independent.Release-aware first-use follow-up (2026-10-07)
The documentation update extends this existing PR without replacing its earlier review fixes (11c97c5 and 982c47c).
Exact source head: 4871ddb
Parent before this follow-up: 982c47c
Tested tree: 5e1d8e4fc58cfb00dff0614fe52c9df5e33b3266
Main base: bb8fea0
Fresh Linux validation: full site image generation, Astro check/build, HTML validation, and 63/63 tests pass with zero skips; git diff --check, hygiene, changelog/version checks, and portable lint prerequisites pass. Existing local dependencies were reused, with no manifest/lockfile changes. Native make format/lint/build were attempted but require unavailable xcrun/Xcode/XcodeGen. The archive sub-check explicitly skips without ditto/unzip. Exact-head hosted CI subsequently completed successfully; see the evidence below.
Released v1.2.3 source contracts and mock shell examples were checked during preparation. Actual signed-release clipboard capture and browser/native first-use interaction have not been executed here; those remain a separate native acceptance limitation. No real clipboard/user-content capture was performed. This follow-up changes no production Swift, licensing, installer, dependencies, workflow gates, or release state.
Reviewer focus: inspect both languages and usable copied shell examples; confirm the free/released/current-source/PRO boundaries; retain existing installer recovery guidance. No merge, release, deployment, or force-push.
Exact-head qualification (2026-10-07)
Verified unchanged head
4871ddb2f1d2f79213a23afa010e13f3031630b3, tree5e1d8e4fc58cfb00dff0614fe52c9df5e33b3266, against mainbb8fea04d62c82194b8a05cb353d13b3336984bf.CI run 37553818314 completed successfully: all five jobs passed. Controlled WebKit capture also passed.
The local Linux formatter/build limitations above remain historical facts; current-source native compilation and testing are now qualified by this exact-head CI. Actual signed v1.2.3 first-use clipboard interaction and rendered browser acceptance of the new copy remain unperformed. This is not a claim that the published release was exercised, nor a combined qualification with other PRs. The PR remains open, conflict-free and ready for human review; no merge/release/deployment occurred.