GitHub Copilot
218aabc8ca
Allow visible dashboard screenshots while unfocused
...
Relax screenshot request gating to depend on tab visibility only, so thumbnail updates continue when the dashboard tab is visible but the window is not focused.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 19:59:55 +00:00
GitHub Copilot
8762e2cc7d
Reduce idle screenshot churn with change-driven SSE
...
Emit dashboard activity updates only when terminal screen content actually changes, and tighten screenshot 304 fast-path behavior to avoid stale not-modified responses after newer activity.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 19:52:41 +00:00
GitHub Copilot
2de22d37da
Fix dashboard live refresh and UTF-8 hint rendering
...
Restore reliable live thumbnail updates in the single-flight queue and set UTF-8 charset metadata/headers so typeahead hint symbols render correctly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 19:42:09 +00:00
GitHub Copilot
157da5deb9
Increase SSE activity debounce to 500ms
...
Reduce per-route SSE activity event frequency by doubling the server-side debounce window from 250ms to 500ms.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 19:34:44 +00:00
GitHub Copilot
eb0465403e
Reduce dashboard screenshot churn with single-flight focus gating
...
Ensure only one screenshot request is in flight at a time, queue per-tile refreshes, and pause screenshot fetches while the dashboard is hidden or unfocused.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 19:33:22 +00:00
GitHub Copilot
0ca413f10c
webterm: restore Python-style dashboard search and add gzip
...
Restore dashboard typeahead behavior to match the Python version with floating results, keyboard navigation, tile highlighting, and Enter-to-open handling.
Add HTTP gzip compression middleware (while excluding WebSocket upgrades) to reduce SVG transfer size, and add a safe make push target that pushes current branch plus tags on HEAD.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 19:19:49 +00:00
GitHub Copilot
cb36beaf2e
build: add VERSION-based release workflow
...
Introduce VERSION as the app version source of truth and add make bump-patch to increment VERSION, commit, and create a matching vX.Y.Z tag.
Wire VERSION into build outputs by injecting it into webterm.Version for make build-go and Docker image builds, and include VERSION in Docker build context.
Also remove the visible dashboard container count subtitle while keeping count updates in browser console logs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 18:58:59 +00:00
GitHub Copilot
a49c4d8718
webterm: add docker watcher event logging
...
Add structured server-side logs for Docker watcher lifecycle, event stream connectivity/decoding failures, start/die event handling, and container add/remove actions.
This complements HTTP/WebSocket request logs with Docker-specific observability for debugging dynamic tile/session behavior.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 18:48:30 +00:00
GitHub Copilot
1cfced1052
webterm: fix screenshot tile bootstrap and add request logging
...
Fix screenshot generation for requested dashboard route keys by preserving non-empty route_key lookups when no session exists yet, allowing lazy session creation instead of returning 404.
Add server-side observability with HTTP request logs (method, URI, status, bytes, duration, remote address) and websocket connection lifecycle logs for connect/disconnect and unexpected read errors.
Update README title/positioning and expand feature bullets to document Ghostty WASM rendering and mobile/touch keyboard support.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 18:46:36 +00:00
GitHub Copilot
4110963c9f
Bump minor version to v1.3.0
...
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 18:32:34 +00:00
GitHub Copilot
c8040e5938
go: harden session cleanup path
...
Ensure SessionManager.CloseAll fully removes session and route mappings by reusing CloseSession for each tracked session ID.
Tighten coverage test assertions to verify CloseAll removes both sessions and route-key mappings, guarding against stale state regressions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 18:26:43 +00:00
GitHub Copilot
3d4dab2359
Finalize Go-only migration, runtime hardening, and CI/container optimization
...
This commit consolidates the full repository transition to a Go-first codebase and captures the follow-up performance/reliability work completed in the same stream.
Highlights:
- Remove Python implementation and test suites (, , , ) and retire Python-specific docs/instructions.
- Move and standardize static web assets under , updating Bun/TypeScript build paths and server static resolution logic.
- Rewrite developer workflow to Makefile-first Go targets (vet/test/race/coverage/fuzz/build) and align repository guidance/docs accordingly.
- Update Docker and CI/CD for leaner artifacts:
- switch to Alpine-based multi-stage build with stripped Go binary
- install only minimal runtime deps (, )
- tighten Docker build context via
- ensure workflows build/publish the target.
- Improve runtime correctness/latency and reduce duplication:
- explicit WebSocket outbound frame typing (text vs binary) instead of payload-byte heuristics
- SSE activity fan-out outside global lock and safer subscriber lifecycle
- shared session output/snapshot helpers to reduce duplicated logic
- restart-safe channel lifecycle for Docker watcher/stats start-stop-start flows
- faster screenshot cold-start path (poll-until-ready within timeout vs fixed sleep).
- Add/expand regression coverage for the above lifecycle and helper paths.
Validation run:
- bun run build
[32mBundled 3 modules in 10ms[0m
[34mterminal.js[33m 0.68 MB [2m(entry point)[0m (Bun typecheck + bundle)
- cd go && go vet ./...
cd go && go test ./...
ok github.com/rcarmo/webterm-go-port/cmd/webterm (cached)
ok github.com/rcarmo/webterm-go-port/internal/terminalstate (cached)
ok github.com/rcarmo/webterm-go-port/webterm (cached)
cd go && go test ./webterm -coverprofile=coverage.out && go tool cover -func=coverage.out
ok github.com/rcarmo/webterm-go-port/webterm (cached) coverage: 81.0% of statements
github.com/rcarmo/webterm-go-port/webterm/cli.go:14: RunCLI 51.6%
github.com/rcarmo/webterm-go-port/webterm/config.go:25: DefaultConfig 100.0%
github.com/rcarmo/webterm-go-port/webterm/config.go:29: LoadLandingYAML 82.6%
github.com/rcarmo/webterm-go-port/webterm/config.go:70: LoadComposeManifest 76.9%
github.com/rcarmo/webterm-go-port/webterm/config.go:114: extractLabel 92.3%
github.com/rcarmo/webterm-go-port/webterm/config.go:138: asString 80.0%
github.com/rcarmo/webterm-go-port/webterm/constants.go:27: EnvBool 50.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:30: Read 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:56: NewDockerExecSession 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:72: Open 90.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:99: Start 85.7%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:119: readLoop 83.3%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:143: handleOutput 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:153: createExec 75.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:183: startExecSocket 60.7%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:219: resizeExec 83.3%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:237: Close 90.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:250: Wait 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:257: SetTerminalSize 81.8%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:274: ForceRedraw 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:281: SendBytes 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:294: SendMeta 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:298: IsRunning 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:304: GetReplayBuffer 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:308: GetScreenSnapshot 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_exec_session.go:316: UpdateConnector 80.0%
github.com/rcarmo/webterm-go-port/webterm/docker_http.go:23: DockerSocketPath 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_http.go:37: newUnixHTTPClient 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_http.go:47: sharedUnixClient 91.7%
github.com/rcarmo/webterm-go-port/webterm/docker_http.go:64: unixJSONRequest 84.2%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:33: NewDockerStatsCollector 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:47: Available 72.7%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:64: Start 80.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:78: Stop 75.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:90: AddService 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:101: RemoveService 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:115: GetCPUHistory 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:124: pollLoop 95.2%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:160: discoverContainers 65.4%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:198: pollContainer 77.8%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:223: calculateCPUPercent 69.2%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:260: RenderSparklineSVG 89.3%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:299: max 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:306: toAnyMap 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:323: toStringMap 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:331: toAnySlice 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:340: toStringSlice 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:351: toUint 91.7%
github.com/rcarmo/webterm-go-port/webterm/docker_stats.go:376: toInt 85.7%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:34: NewDockerWatcher 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:54: hasWebtermLabel 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:60: isAutoLabel 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:67: getContainerCommand 80.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:76: getContainerTheme 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:81: getContainerName 42.9%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:93: containerToSlug 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:98: addContainer 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:119: removeContainer 100.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:143: listLabeledContainers 94.1%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:168: handleEvent 80.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:202: watchEvents 85.7%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:239: ScanExisting 60.0%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:249: Start 83.3%
github.com/rcarmo/webterm-go-port/webterm/docker_watcher.go:265: Stop 81.8%
github.com/rcarmo/webterm-go-port/webterm/identity.go:12: GenerateID 94.1%
github.com/rcarmo/webterm-go-port/webterm/normalize.go:13: FilterDASequences 83.3%
github.com/rcarmo/webterm-go-port/webterm/replay.go:14: NewReplayBuffer 66.7%
github.com/rcarmo/webterm-go-port/webterm/replay.go:21: Add 100.0%
github.com/rcarmo/webterm-go-port/webterm/replay.go:43: Bytes 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:95: OnData 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go💯 OnBinary 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:105: OnMeta 0.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:107: OnClose 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:112: NewLocalServer 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:163: findStaticPath 62.5%
github.com/rcarmo/webterm-go-port/webterm/server.go:184: markRouteActivity 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:207: enqueueWSFrame 77.8%
github.com/rcarmo/webterm-go-port/webterm/server.go:233: stopWSClient 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:246: wsSender 80.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:256: createTerminalSession 66.7%
github.com/rcarmo/webterm-go-port/webterm/server.go:278: clampInt 60.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:288: parseResizePayload 88.9%
github.com/rcarmo/webterm-go-port/webterm/server.go:303: handleWebSocket 81.1%
github.com/rcarmo/webterm-go-port/webterm/server.go:425: chooseRouteForScreenshot 50.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:440: screenshotTTL 66.7%
github.com/rcarmo/webterm-go-port/webterm/server.go:457: handleScreenshot 55.7%
github.com/rcarmo/webterm-go-port/webterm/server.go:541: handleCPUSparkline 94.4%
github.com/rcarmo/webterm-go-port/webterm/server.go:566: handleEvents 76.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:602: toIntFromQuery 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:609: dashboardTiles 81.8%
github.com/rcarmo/webterm-go-port/webterm/server.go:631: handleTiles 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:636: getWSURL 65.2%
github.com/rcarmo/webterm-go-port/webterm/server.go:671: handleRoot 56.8%
github.com/rcarmo/webterm-go-port/webterm/server.go:732: htmlEscape 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:736: htmlAttrEscape 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:740: handleHealth 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:744: setupDockerFeatures 40.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:791: shutdown 62.5%
github.com/rcarmo/webterm-go-port/webterm/server.go:814: Handler 100.0%
github.com/rcarmo/webterm-go-port/webterm/server.go:829: Run 77.8%
github.com/rcarmo/webterm-go-port/webterm/session.go:31: OnData 0.0%
github.com/rcarmo/webterm-go-port/webterm/session.go:32: OnBinary 0.0%
github.com/rcarmo/webterm-go-port/webterm/session.go:33: OnMeta 0.0%
github.com/rcarmo/webterm-go-port/webterm/session.go:34: OnClose 0.0%
github.com/rcarmo/webterm-go-port/webterm/session.go:36: dispatchSessionOutput 100.0%
github.com/rcarmo/webterm-go-port/webterm/session.go:47: snapshotFromTracker 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:20: NewSessionManager 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:34: SetSessionFactory 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:40: defaultSessionFactory 87.5%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:57: splitCommand 75.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:65: shlexSplit 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:69: AddApp 87.5%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:88: RemoveApp 87.5%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:101: Apps 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:107: AppBySlug 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:114: GetDefaultApp 80.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:123: NewSession 50.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:167: OnSessionEnd 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:176: CloseAll 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:189: CloseSession 87.5%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:201: GetSession 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:207: GetSessionByRouteKey 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:217: GetSessionIDByRouteKey 100.0%
github.com/rcarmo/webterm-go-port/webterm/session_manager.go:223: GetFirstRunningSession 85.7%
github.com/rcarmo/webterm-go-port/webterm/shellsplit.go:5: shlexSplitImpl 100.0%
github.com/rcarmo/webterm-go-port/webterm/slugify.go:13: Slugify 100.0%
github.com/rcarmo/webterm-go-port/webterm/svg_exporter.go:35: RenderTerminalSVG 92.6%
github.com/rcarmo/webterm-go-port/webterm/svg_exporter.go:113: colorToHex 87.5%
github.com/rcarmo/webterm-go-port/webterm/svg_exporter.go:139: isHex 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:37: NewTerminalSession 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:49: Open 86.7%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:90: Start 85.7%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:110: readLoop 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:132: handleOutput 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:142: Close 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:160: Wait 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:167: SetTerminalSize 80.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:190: ForceRedraw 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:198: SendBytes 88.9%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:211: SendMeta 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:215: IsRunning 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:221: GetReplayBuffer 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:225: GetScreenSnapshot 100.0%
github.com/rcarmo/webterm-go-port/webterm/terminal_session.go:233: UpdateConnector 80.0%
github.com/rcarmo/webterm-go-port/webterm/twoway.go:14: NewTwoWayMap 100.0%
github.com/rcarmo/webterm-go-port/webterm/twoway.go:21: Set 88.9%
github.com/rcarmo/webterm-go-port/webterm/twoway.go:36: DeleteKey 100.0%
github.com/rcarmo/webterm-go-port/webterm/twoway.go:45: Get 100.0%
github.com/rcarmo/webterm-go-port/webterm/twoway.go:52: GetKey 100.0%
github.com/rcarmo/webterm-go-port/webterm/twoway.go:59: Keys 100.0%
github.com/rcarmo/webterm-go-port/webterm/twoway.go:70: UnsafeForward 100.0%
total: (statements) 81.0%
- cd go && go test -race ./...
ok github.com/rcarmo/webterm-go-port/cmd/webterm (cached)
ok github.com/rcarmo/webterm-go-port/internal/terminalstate (cached)
ok github.com/rcarmo/webterm-go-port/webterm (cached)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 18:03:28 +00:00
GitHub Copilot
065de286fb
refactor: standardize Go layout with internal terminalstate
...
Audit findings: cmd/webterm and webterm package were acceptable, but terminalstate
was an internal implementation detail exposed as a public package.
Changes:
- Move go/terminalstate -> go/internal/terminalstate
- Update imports to github.com/rcarmo/webterm-go-port/internal/terminalstate
- Keep package name terminalstate unchanged
Resulting package layout:
- github.com/rcarmo/webterm-go-port/cmd/webterm
- github.com/rcarmo/webterm-go-port/internal/terminalstate
- github.com/rcarmo/webterm-go-port/webterm
Validation:
- go test ./...
- go test -race ./...
- go coverage check remains 80.9%
- make check
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 17:13:49 +00:00
GitHub Copilot
f597f8f99d
test: expand Go fuzzing and raise coverage above 80%
...
- Add comprehensive runtime tests for session, docker watcher/stats/http, and server helpers
- Add new fuzz targets: FuzzToIntFromQuery and FuzzHTMLHelpers
- Add cmd/webterm main entrypoint test
- Expand helper conversion and color-mode coverage tests
Validation:
- go test ./...
- go test -race ./...
- All 15 fuzz targets pass with short fuzz runs
- go test ./... -coverpkg=./... => 80.9% total statement coverage
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 17:06:52 +00:00
GitHub Copilot
674e62d983
refactor: upgrade go-te to v0.1.0, remove C1 normalization
...
go-te v0.1.0 fixes the ByteStream C1 bug (Latin-1 fallback for
invalid UTF-8 bytes), so NormalizeC1Controls is no longer needed.
Removed:
- NormalizeC1Controls function and its tests/fuzz target
- utf8Buffer field from TerminalSession and DockerExecSession
- C1BUG.md (fix shipped upstream)
The handleOutput pipeline now does: FilterDA → replay → tracker → connector
(was: FilterDA → NormalizeC1 → replay → tracker → connector)
All tests pass with -race. 13 fuzz targets remain.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 16:40:28 +00:00
GitHub Copilot
307a8cc312
docs: add go-te C1 ByteStream bug report (C1BUG.md)
...
ByteStream.Feed() in UTF-8 mode permanently stalls on raw C1
control bytes (0x80-0x9F). DecodeRune returns RuneError, the loop
breaks, and the bad byte stays in the buffer forever — blocking
all subsequent input and leaking memory.
Stream.handleGround() has correct C1 handlers but they are
unreachable through ByteStream. Includes reproduction case and
suggested fix (Latin-1 fallback for invalid UTF-8 bytes).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 16:32:50 +00:00
GitHub Copilot
52a96915f0
test: add 14 fuzz tests across Go packages
...
Fuzz targets covering all input-processing functions:
- terminalstate: FuzzTrackerFeed, FuzzTrackerFeedIncremental
- normalize: FuzzNormalizeC1Controls, FuzzFilterDASequences
- slugify: FuzzSlugify (with unit tests)
- identity: FuzzGenerateID (with unit tests)
- replay: FuzzReplayBuffer, FuzzReplayBufferRapid
- svg_exporter: FuzzColorToHex, FuzzIsHex, FuzzRenderTerminalSVG
- shellsplit: FuzzShlexSplit (with unit test)
- twoway: FuzzTwoWayMap (with unit test)
- config: FuzzExtractLabel
All 14 targets validated with -fuzztime=3s, no panics found.
All unit tests pass with -race.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 16:25:55 +00:00
GitHub Copilot
fd6c1c4e0d
feat: complete Go port with go-te terminal emulator
...
Full Go implementation under go/ replacing Python pyte with go-te:
- HTTP server with WebSocket protocol, SSE, screenshot SVG rendering
- PTY terminal sessions and Docker exec sessions
- Docker watcher (label-based container discovery + event stream)
- CPU stats collection with sparkline SVG rendering
- Session manager with TwoWayMap routing and replay buffers
- C1 normalization, DA filtering, identity generation, theme palettes
Audit fixes for 9 concurrency/correctness issues:
- HTTP transport leak: shared client pool for Docker socket calls
- WebSocket concurrent writes: all writes routed through send channel
- Closed channel panic: atomic.Bool guard on enqueueWSData
- GetFirstRunningSession: use UnsafeForward under SessionManager lock
- NewSession TOCTOU: re-check routeKey after re-acquiring lock
- waitErr data race: protect with mutex in both session types
- Replay buffer fragmentation: copy to new slice on eviction
- go-te dirty tracking: check screen.Dirty before incrementing counter
- Identity modulo bias: rejection sampling for uniform distribution
All Go tests pass (including -race). Python baseline unchanged (397 tests).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com >
2026-02-14 16:18:23 +00:00