test / unit + widget + golden + a11y (push) Failing after 31s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 1m7s
Seven small consultant findings, one commit:
1. TreeSitterLib stores last dlopen error + path in static fields
instead of swallowing them. Callers that observe a null instance
can now read the diagnostic.
2. Drop the Cmsghdr alias in libc.dart — back-compat shim with no
callers; CLAUDE.md forbids those in a solo repo.
3. Drop EditorController._events field + the unused_field
suppression. The constructor still subscribes via `events.on<...>`
for _eventSub; the field itself was speculative retention.
4. Replace inline hex / errno literals in native_pty.dart with
PosixErrno.{eintr,ebadf,epipe} and new libc.{pollin, pollAnyErr,
sighup, sigkill, sigwinch}. PosixErrno gains eintr.
5. ExtensionManager records activate/deactivate exceptions in a
`_failed` map exposed as `failedExtensions` + `didFail(id)`.
Listeners are notified on entry/exit; cleared on a clean
activate. UI surfaces the degraded state instead of pretending
everything is fine.
6. file_tree_view imports FileEntry via the clide.dart barrel
instead of `package:clide/src/files/listing.dart` directly — the
leak the consultant flagged (barrel already re-exports it).
7. test_app branch in main.dart wrapped in `if (kDebugMode)` so
release tree-shaker elides the test harness from shipping
binaries. Source import stays; tree-shake handles the rest.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`forkpty` calls `fork()` underneath. `fork()` in a multithreaded
process is unsafe: only the calling thread survives in the child,
but libc locks held by other threads remain "locked forever." With
the multi-threaded Dart VM as parent, ~5% of spawns deadlocked in
the child before `execve` (forensic probe: child stuck in S state
with comm=`DartWorker`, master fd never sees POLLIN).
`posix_spawn` uses `vfork` on glibc/musl/macOS, keeping the parent
suspended until execve completes — no Dart code runs in the child.
Pty pair built via the POSIX-standard `posix_openpt` / `grantpt` /
`unlockpt` / `ptsname` sequence. Probed: zero hangs in 300
sequential spawns vs ~5% before.
Behavior change: missing executable / missing workingDirectory now
surface as a `PtyException` thrown by `NativePty.start` rather than
a diagnostic written from the child to the slave PTY. Cleaner error
path for callers.
Side benefit: drops the `libutil.so.1` dynamic-library dependency.
PTY now resolves entirely against libc via `DynamicLibrary.process()`.
Splits the library-level `@Tags(['forkpty'])` on session_test.dart
into a per-test tag, so the now-runnable-under-flutter-test cases
contribute to coverage. `dart_test.yaml` declares the tag so the
exclude-tags filters honor it. Drops the `retry: 2` workaround from
the formerly-flaky registry test.
D-5 amended. Trims session-introduced CHANGELOG entries that were
over-verbose for the Keep-a-Changelog format.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Complete three overdue cleanups discovered during macOS health check:
D-56 daemon dissolution: delete bin/clide.dart, DaemonServer,
and orphaned tests (test/cli/, subprocess_test, in_process_test).
Update stale "clide --daemon" references in i18n catalogs, error
messages, editor_commands, CI scripts, and decision records.
ptyc retirement: delete ptyc/ source tree, PtySession, scm_rights.
Remove from Toolchain resolution, ToolCheck gate, backend
serialization, testmode harness, Makefile, CI, and sandbox
entitlements. PTY spawning uses NativePty (Dart FFI forkpty) since
the terminal was absorbed in-tree. D-5 amended.
Golden tests: wire the existing but never-applied clideGoldenConfig
via flutter_test_config.dart. Disable CI goldens (Skia anti-aliasing
differs between macOS/Linux even with Ahem). Keep platform-keyed
goldens only — goldens/linux/ and goldens/macos/ each run on their
own OS.
Test suite: 826 pass, 0 fail on macOS (was 829 pass, 11 fail).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
test / unit + widget + golden + a11y (push) Failing after 35s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
test / dart doc (lib API) (push) Failing after 1m0s
Clears the 19 misc lint hits left after the test_app print sweep
+ libc.dart suppression. By rule:
- `withOpacity(α)` → `withValues(alpha: α)` (deprecated_member_use)
in `painter.dart:187` and `terminal_view.dart:318`.
- `Pointer.elementAt(n)` → `Pointer + n` (deprecated_member_use)
in `native_pty.dart:306` and `session.dart:187`.
- Brace single-statement for/if bodies in `native_pty.dart`
(×3) and `decisions_view.dart` (curly_braces_in_flow_control_
structures).
- `IsolateClient` and `InProcessClient` constructors switched to
`super.log` / `super.events` parameters (use_super_parameters);
associated unused imports of `kernel/src/log.dart` and
`kernel/src/events/bus.dart` removed in the same files.
- `InProcessClient._dispatcher` field + getter/setter pair folded
into a single mutable public `dispatcher` field
(unnecessary_getters_setters).
- `_buildDispatcher` local in `lib/main.dart` renamed to
`buildDispatcher` (no_leading_underscores_for_local_identifiers).
- `_onTapDown(_)` in `terminal_view.dart` typed as
`TapDownDetails _` (strict_top_level_inference).
- `operator []=(...)` in `circular_buffer.dart` given an explicit
`void` return type (strict_top_level_inference).
- `CustomKeyboardListener` and `TerminalGestureDetector` callsites
reordered so `child:` lands last (sort_child_properties_last).
- `CustomTextEdit` constructor declared `const`
(prefer_const_constructors_in_immutables).
- `LinkedHashMap<K, V>()` in `paragraph_cache.dart` collapsed to a
`<K, V>{}` literal (prefer_collection_literals); the now-unused
`dart:collection` import dropped.
Project analyze: 19 → 0 issues. `make test` stays green; coverage
unchanged at 52.72%.
Co-Authored-By: Claude <noreply@anthropic.com>
Mechanical `dart format` sweep across files that drifted from the
formatter's output (mostly trailing-comma and line-wrap differences
from a Dart SDK / formatter version bump). No semantic changes.
Caught because the pre-push gate now actually fires.
Co-Authored-By: Claude <noreply@anthropic.com>
NativePty.close() now awaits the reader-isolate spawn, kills the
child first to drive EOF on the master fd, awaits the isolate's
EOF acknowledgement, and only then closes the fd. Previously the
fd-close racing with the polling isolate left a window where the
fd number could be reused and the isolate would briefly target the
wrong file.
Both NativePty and PtySession now surface reader-isolate spawn
errors via the output stream's addError instead of silently
swallowing them.
PtySession.spawn closes the master fd on any post-receive failure,
closes parentSock in finally (was leaking on every spawn), and
kills the ptyc process if recvFd fails.
PtySession._recvFdAsync uses try/finally to close the ReceivePort
and kill the spawn isolate even when Isolate.spawn itself throws.
Co-Authored-By: Claude <noreply@anthropic.com>
forkpty failures throw PtyException with the captured errno
(previously a generic StateError). The spawned child's chdir/execve
failures write a diagnostic line to its slave PTY before _exit, so
the parent's reader sees "exec failed: <path>" instead of an
indistinguishable EOF.
NativePty.write and PtySession.write loop on short writes and throw
PtyException on hard errors (with errno). NativePty.resize sets
_dead on EBADF so subsequent calls short-circuit cleanly.
Co-Authored-By: Claude <noreply@anthropic.com>
Platform-dispatched constants where Linux and macOS diverge:
TIOCSWINSZ, O_NONBLOCK, MsghdrDarwin struct (4-byte msg_iovlen
and msg_controllen vs Linux's 8-byte size_t fields), and split
recvmsg into Linux/Darwin typed variants so scm_rights uses the
correct struct per platform.
Also: app settings dir uses ~/Library/Application Support on
macOS, removed hardcoded TERMINFO from pane spawn env, removed
debug print from native_pty resize.
Co-Authored-By: Claude <noreply@anthropic.com>
test / unit + widget + golden + a11y (push) Failing after 27s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
tmux running inside a PTY without a traditional terminal client
defaults to a huge window size (2000+ cols, 10000 rows). Pass
explicit -x and -y flags matching the TerminalView dimensions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
test / unit + widget + golden + a11y (push) Failing after 29s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
Split escape sequences caused rendering artifacts (visible % prompt
mark, garbled lines between commands). Two fixes from the legacy
Python implementation:
1. Read buffer increased from 4096 to 65536 bytes. Larger reads mean
fewer chunk boundaries that can split multi-byte escape sequences.
2. Output writes throttled to ~60fps via a 16ms Timer. Multiple PTY
reads within one frame window are batched into a single
terminal.write() call, so the xterm parser sees complete sequences
instead of fragments that render as garbage between frames.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
test / unit + widget + golden + a11y (push) Failing after 28s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
Rapid resize during window drag sends many SIGWINCH signals causing
the shell to redraw repeatedly, corrupting xterm's render. Debounce
to 150ms so only the final size is sent.
NativePty.resize now explicitly sends SIGWINCH (signal 28) after
TIOCSWINSZ, matching the legacy Python implementation.
Removed 8px padding from ClidePtyView to eliminate potential
dimension mismatch between widget size and PTY cols/rows.
Default window size increased to 1600x900.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
test / unit + widget + golden + a11y (push) Failing after 28s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
execve doesn't search PATH — bare names like 'tmux' or 'claude' fail
silently. Resolve via the environment's PATH in Dart before passing
to the child. This matches ptyc's old execvp behavior.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
test / unit + widget + golden + a11y (push) Failing after 3m13s
test / integration_test (xvfb) (push) Has been skipped
test / bundle smoke (xvfb 5s) (push) Has been skipped
test / daemon subprocess + web WASM smoke (push) Has been skipped
NativePty calls forkpty() directly — no helper binary, no socketpair,
no SCM_RIGHTS. The master fd stays in-process. Reader isolate uses
poll() for clean shutdown.
Based on the pty-spike proof-of-concept. Platform-aware: macOS uses
libSystem (DynamicLibrary.process), Linux needs libutil.so.1.
TIOCSWINSZ platform-detected.
PaneRegistry updated to use NativePty. registerPaneCommands no longer
needs a Toolchain parameter. All ptyc references removed from the
daemon layer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>