@akiojin/gwt 9.36.2 → 9.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md CHANGED
@@ -96,6 +96,51 @@ gwt
96
96
  `http://127.0.0.1:<port>/` のような URL を出力します。ネイティブアプリの起動中は、
97
97
  同じ URL を通常のブラウザでも開けます。
98
98
 
99
+ ### Headless / Browser-only モード
100
+
101
+ `gwt serve` (等価 alias: `gwt --headless`) は、ネイティブウィンドウを開かずに
102
+ 同じ UI を起動します。embedded HTTP / WebSocket サーバーだけが立ち上がり、
103
+ オペレーターは出力された URL を任意のブラウザで開いて操作します。
104
+
105
+ ```bash
106
+ gwt serve # 127.0.0.1、ランダムポート、ブラウザ自動起動
107
+ gwt serve --no-open # 同じ動作だがブラウザ自動起動を抑制 (CI / スクリプト用)
108
+ gwt serve --port 8787 # 固定ポート + ブラウザ自動起動
109
+ gwt serve --bind 0.0.0.0 --port 8787 # LAN (VPN 越し含む) へ公開 + ブラウザ自動起動
110
+ gwt --headless --port 8787 # `gwt serve --port 8787` と同じ
111
+ ```
112
+
113
+ 既定でシステムブラウザが自動起動します。CI / 自動化で server だけ立ち上げ
114
+ たい場合は `--no-open` を指定してください。`--open` は既存スクリプト互換性
115
+ 維持のため no-op flag として残しています。
116
+
117
+ 信頼境界は **LAN のみ** (VPN-extended LAN を含む) です。`gwt serve` には
118
+ TLS 終端、認証ゲート、レート制限は組み込まれていません。`--bind` で
119
+ 公開した IP に到達できる主体はすべて trusted と見なされ、ターミナル起動を
120
+ 含む全 UI 操作が可能になります。既定値は `127.0.0.1` で、ネイティブ GUI と
121
+ 同じローカルループバック信頼モデルを維持します。外部からアクセスする場合は、
122
+ ポートを公開インターネットに晒さず、VPN (Tailscale、WireGuard など) 越しで
123
+ LAN に入ってから接続してください。
124
+
125
+ プラットフォーム注記: Linux では `tao 0.35` が EventLoop 生成時に display
126
+ server (X11 / Wayland) を要求するので、v1 の `gwt serve` は GUI と同じ
127
+ `DISPLAY` 依存を引き継ぎます。macOS / Windows の headless 利用は追加設定
128
+ 不要ですが、Linux の pure-headless 環境 (DISPLAY 無し) では `Xvfb` /
129
+ `xvfb-run` を併用するか、SPEC-1942 follow-up の tao 切り離し対応を待って
130
+ ください。
131
+
132
+ すべての HTTP / WebSocket リクエストは `tracing::info!(target = "gwt_access",
133
+ ...)` で記録されるため、stderr と `~/.gwt/logs/<date>/` で「どこからアクセス
134
+ されているか」を即時に確認できます。`/healthz` は `debug!` に降格されており、
135
+ ヘルスチェックでログが埋まりません。
136
+
137
+ Lifecycle: `gwt serve` プロセスが agent / PTY の寿命を所有します。ブラウザの
138
+ タブを閉じても agent は **停止しません**。`Ctrl-C` / `SIGTERM` を受け取った
139
+ ときに、PTY のドレイン → サーバー停止の順で graceful shutdown を実行します。
140
+ GUI と headless は別の lock kind を使うので、同じ worktree で `gwt` と
141
+ `gwt serve` を同時に起動できます。起動時に共存 warning が stderr に出るので、
142
+ 意図しない並走は気付けます。
143
+
99
144
  CLI サブコマンドは `gwtd` で処理され、GUI は起動しません。
100
145
 
101
146
  ```bash
package/README.md CHANGED
@@ -98,6 +98,51 @@ directory. The app also starts a local HTTP/WebSocket server for the WebView
98
98
  surface and prints a URL such as `http://127.0.0.1:<port>/` to stderr. You can
99
99
  open that URL in a regular browser while the native app is running.
100
100
 
101
+ ### Headless / Browser-only mode
102
+
103
+ `gwt serve` (equivalent alias: `gwt --headless`) launches the same UI without
104
+ opening a native window. The embedded HTTP / WebSocket server stays up and
105
+ the operator opens the printed URL in any browser instead.
106
+
107
+ ```bash
108
+ gwt serve # 127.0.0.1, random port, auto-open browser
109
+ gwt serve --no-open # same, but suppress the browser launch (CI / scripts)
110
+ gwt serve --port 8787 # fixed port + auto-open browser
111
+ gwt serve --bind 0.0.0.0 --port 8787 # share with the LAN (VPN-extended), auto-open browser
112
+ gwt --headless --port 8787 # same as `gwt serve --port 8787`
113
+ ```
114
+
115
+ The system browser is opened automatically by default. Pass `--no-open` for
116
+ CI / automation use cases that only need the server running. `--open` is kept
117
+ as a no-op flag for backward compatibility with existing scripts.
118
+
119
+ Trust boundary: **LAN only** (including VPN-extended LAN). `gwt serve` does
120
+ not ship TLS termination, an authentication gate, or rate limiting. Anyone
121
+ that can reach the bind address can drive the embedded UI, which includes
122
+ spawning terminals. The `--bind` flag is opt-in: the default `127.0.0.1`
123
+ keeps the same loopback-trust behaviour as the native GUI. For external
124
+ access, run the host behind a VPN (Tailscale, WireGuard, etc.) rather than
125
+ exposing the port to the public Internet.
126
+
127
+ Platform note: on Linux, `tao 0.35` still requires a display server (X11 or
128
+ Wayland) at EventLoop creation, so v1 of `gwt serve` inherits the GUI's
129
+ `DISPLAY` dependency. macOS and Windows headless installs need nothing
130
+ special; Linux operators in pure-headless environments (no DISPLAY) should
131
+ either use `Xvfb`/`xvfb-run` or wait for the tao-detach follow-up tracked
132
+ under SPEC-1942.
133
+
134
+ Every HTTP / WebSocket request is mirrored to `tracing::info!(target =
135
+ "gwt_access", ...)` so the operator can see *which* peer is connecting in
136
+ real time on stderr and in `~/.gwt/logs/<date>/`. `/healthz` is demoted to
137
+ `debug!` to avoid drowning the stream with health probes.
138
+
139
+ Lifecycle: the `gwt serve` process owns the agent / PTY lifetime. Closing a
140
+ browser tab does **not** stop running agents — only `Ctrl-C` / `SIGTERM`
141
+ asks the server to drain PTYs and exit gracefully. The GUI and a headless
142
+ session for the same worktree are isolated by separate lock kinds, so you
143
+ can run `gwt` and `gwt serve` together; a startup warning surfaces the
144
+ co-existence so it is intentional, not accidental.
145
+
101
146
  CLI subcommands run through `gwtd` without opening a GUI window:
102
147
 
103
148
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akiojin/gwt",
3
- "version": "9.36.2",
3
+ "version": "9.38.0",
4
4
  "description": "Desktop GUI for Git worktree management and coding agent launch",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,9 +12,9 @@
12
12
  "dev": "cargo run -p gwt --bin gwt",
13
13
  "build": "cargo build --release -p gwt --bin gwt --bin gwtd",
14
14
  "test": "cargo test -p gwt-core -p gwt --all-features",
15
- "test:frontend-bundle": "node --check crates/gwt/web/app.js && node --check crates/gwt/web/branch-cleanup-modal.js && node --check crates/gwt/web/migration-modal.js && node --check crates/gwt/web/project-clone-modal.js && node --check crates/gwt/web/board-surface.js && node --check crates/gwt/web/workspace-kanban-surface.js && node --check crates/gwt/web/theme-manager.js && node --check crates/gwt/web/theme-toggle.js && node --check crates/gwt/web/hotkey.js && node --check crates/gwt/web/operator-shell.js && node --check crates/gwt/web/focus-trap.js && node --check crates/gwt/web/window-docking.js && node --check crates/gwt/web/update-cta.js && node --check crates/gwt/web/terminal-context-menu.js && node --check crates/gwt/web/window-geometry-sync.js && node --check crates/gwt/web/custom-agent-env-editor.js && node --check crates/gwt/web/socket-receive-dispatcher.js && node --check crates/gwt/web/interaction-guard.js && node --check crates/gwt/web/viewport-persist-throttle.js && node --check crates/gwt/web/viewport-sync.js && node --check crates/gwt/web/project-tabs-renderer.js && node --check crates/gwt/web/clone-modal-focus-guard.js && node --check crates/gwt/web/ui-trace-profiler.js && node --check crates/gwt/web/ui-trace-wiring.js",
16
- "test:frontend-smoke": "node --test crates/gwt/web/__tests__/branch-cleanup.smoke.test.mjs crates/gwt/web/__tests__/migration-modal.smoke.test.mjs crates/gwt/web/__tests__/project-clone-modal.smoke.test.mjs crates/gwt/web/__tests__/open-project-split-button.smoke.test.mjs",
17
- "test:frontend-unit": "node --test crates/gwt/web/__tests__/contrast.test.mjs crates/gwt/web/__tests__/theme-manager.test.mjs crates/gwt/web/__tests__/theme-segmented.test.mjs crates/gwt/web/__tests__/hotkey.test.mjs crates/gwt/web/__tests__/index-settings-panel.test.mjs crates/gwt/web/__tests__/index-status-controller.test.mjs crates/gwt/web/__tests__/operator-chrome-structure.test.mjs crates/gwt/web/__tests__/operator-shell-runtime.test.mjs crates/gwt/web/__tests__/operator-shell-hover-reveal.test.mjs crates/gwt/web/__tests__/board-surface.test.mjs crates/gwt/web/__tests__/focus-trap.test.mjs crates/gwt/web/__tests__/kanban-structure.test.mjs crates/gwt/web/__tests__/kanban-dnd.test.mjs crates/gwt/web/__tests__/kanban-drawer.test.mjs crates/gwt/web/__tests__/workspace-kanban-surface.test.mjs crates/gwt/web/__tests__/update-button.test.mjs crates/gwt/web/__tests__/window-docking.test.mjs crates/gwt/web/__tests__/terminal-context-menu.test.mjs crates/gwt/web/__tests__/terminal-viewport-reflow.test.mjs crates/gwt/web/__tests__/window-geometry-sync.test.mjs crates/gwt/web/__tests__/custom-agent-env-editor.test.mjs crates/gwt/web/__tests__/settings-system-tab.test.mjs crates/gwt/web/__tests__/socket-receive-dispatcher.test.mjs crates/gwt/web/__tests__/ui-trace-profiler.test.mjs crates/gwt/web/__tests__/ui-trace-wiring.test.mjs crates/gwt/web/__tests__/interaction-guard.test.mjs crates/gwt/web/__tests__/wizard-interaction-guard-wiring.test.mjs crates/gwt/web/__tests__/viewport-persist-throttle.test.mjs crates/gwt/web/__tests__/viewport-sync.test.mjs crates/gwt/web/__tests__/project-tabs-renderer.test.mjs crates/gwt/web/__tests__/project-tab-style.test.mjs crates/gwt/web/__tests__/playwright-embedded-routes.test.mjs crates/gwt/web/__tests__/viewport-persist-wiring.test.mjs crates/gwt/web/__tests__/system-settings-interaction-guard-wiring.test.mjs crates/gwt/web/__tests__/clone-modal-focus-guard.test.mjs crates/gwt/web/__tests__/clone-modal-focus-guard-wiring.test.mjs crates/gwt/web/__tests__/recent-row-style.test.mjs",
15
+ "test:frontend-bundle": "node --check crates/gwt/web/app.js && node --check crates/gwt/web/branch-cleanup-modal.js && node --check crates/gwt/web/migration-modal.js && node --check crates/gwt/web/project-clone-modal.js && node --check crates/gwt/web/board-surface.js && node --check crates/gwt/web/workspace-kanban-surface.js && node --check crates/gwt/web/theme-manager.js && node --check crates/gwt/web/theme-toggle.js && node --check crates/gwt/web/hotkey.js && node --check crates/gwt/web/operator-shell.js && node --check crates/gwt/web/focus-trap.js && node --check crates/gwt/web/window-docking.js && node --check crates/gwt/web/update-cta.js && node --check crates/gwt/web/terminal-context-menu.js && node --check crates/gwt/web/terminal-wheel-scroll.js && node --check crates/gwt/web/window-geometry-sync.js && node --check crates/gwt/web/custom-agent-env-editor.js && node --check crates/gwt/web/socket-receive-dispatcher.js && node --check crates/gwt/web/interaction-guard.js && node --check crates/gwt/web/viewport-persist-throttle.js && node --check crates/gwt/web/viewport-sync.js && node --check crates/gwt/web/project-tabs-renderer.js && node --check crates/gwt/web/clone-modal-focus-guard.js && node --check crates/gwt/web/ui-trace-profiler.js && node --check crates/gwt/web/ui-trace-wiring.js && node --check crates/gwt/web/close-project-tab-confirm-modal.js",
16
+ "test:frontend-smoke": "node --test crates/gwt/web/__tests__/branch-cleanup.smoke.test.mjs crates/gwt/web/__tests__/migration-modal.smoke.test.mjs crates/gwt/web/__tests__/project-clone-modal.smoke.test.mjs crates/gwt/web/__tests__/open-project-split-button.smoke.test.mjs crates/gwt/web/__tests__/close-project-tab.smoke.test.mjs",
17
+ "test:frontend-unit": "node --test crates/gwt/web/__tests__/contrast.test.mjs crates/gwt/web/__tests__/theme-manager.test.mjs crates/gwt/web/__tests__/theme-segmented.test.mjs crates/gwt/web/__tests__/hotkey.test.mjs crates/gwt/web/__tests__/index-settings-panel.test.mjs crates/gwt/web/__tests__/index-status-controller.test.mjs crates/gwt/web/__tests__/operator-chrome-structure.test.mjs crates/gwt/web/__tests__/operator-shell-runtime.test.mjs crates/gwt/web/__tests__/operator-shell-hover-reveal.test.mjs crates/gwt/web/__tests__/board-surface.test.mjs crates/gwt/web/__tests__/focus-trap.test.mjs crates/gwt/web/__tests__/kanban-structure.test.mjs crates/gwt/web/__tests__/kanban-dnd.test.mjs crates/gwt/web/__tests__/kanban-drawer.test.mjs crates/gwt/web/__tests__/workspace-kanban-surface.test.mjs crates/gwt/web/__tests__/update-button.test.mjs crates/gwt/web/__tests__/window-docking.test.mjs crates/gwt/web/__tests__/terminal-context-menu.test.mjs crates/gwt/web/__tests__/terminal-wheel-scroll.test.mjs crates/gwt/web/__tests__/terminal-viewport-reflow.test.mjs crates/gwt/web/__tests__/window-geometry-sync.test.mjs crates/gwt/web/__tests__/custom-agent-env-editor.test.mjs crates/gwt/web/__tests__/settings-system-tab.test.mjs crates/gwt/web/__tests__/settings-agent-backends-tab.test.mjs crates/gwt/web/__tests__/launch-wizard-backend-picker.test.mjs crates/gwt/web/__tests__/socket-receive-dispatcher.test.mjs crates/gwt/web/__tests__/ui-trace-profiler.test.mjs crates/gwt/web/__tests__/ui-trace-wiring.test.mjs crates/gwt/web/__tests__/interaction-guard.test.mjs crates/gwt/web/__tests__/wizard-interaction-guard-wiring.test.mjs crates/gwt/web/__tests__/viewport-persist-throttle.test.mjs crates/gwt/web/__tests__/viewport-sync.test.mjs crates/gwt/web/__tests__/project-tabs-renderer.test.mjs crates/gwt/web/__tests__/project-tab-style.test.mjs crates/gwt/web/__tests__/playwright-embedded-routes.test.mjs crates/gwt/web/__tests__/viewport-persist-wiring.test.mjs crates/gwt/web/__tests__/system-settings-interaction-guard-wiring.test.mjs crates/gwt/web/__tests__/clone-modal-focus-guard.test.mjs crates/gwt/web/__tests__/clone-modal-focus-guard-wiring.test.mjs crates/gwt/web/__tests__/recent-row-style.test.mjs",
18
18
  "test:visual": "playwright test --config crates/gwt/playwright/playwright.config.ts",
19
19
  "test:release-assets": "node scripts/test_release_assets.cjs",
20
20
  "test:release-flow": "bash scripts/check-release-flow.sh",
package/wix/main.wxs CHANGED
@@ -43,11 +43,19 @@
43
43
  <Fragment>
44
44
  <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
45
45
  <Component Id="GwtExecutableComponent">
46
- <File Id="GwtExecutable" Source="!(bindpath.gwt)gwt.exe" KeyPath="yes" />
46
+ <!--
47
+ SPEC-1942 2026-05-20 Amendment Bug B: WiX v4 defaults the installed
48
+ File Name to the literal Source string when Name is omitted, so the
49
+ bindpath binder variable leaks into the on-disk file name (observed
50
+ in v9.37.0 as `!(bindpath.gwt)gwt.exe`). Pin the Name explicitly so
51
+ the installed file is always `gwt.exe` regardless of how bindpath
52
+ resolves at build time.
53
+ -->
54
+ <File Id="GwtExecutable" Source="!(bindpath.gwt)gwt.exe" Name="gwt.exe" KeyPath="yes" />
47
55
  <Environment Id="GwtUserPath" Name="PATH" Value="[INSTALLFOLDER]" Action="set" Part="last" />
48
56
  </Component>
49
57
  <Component Id="GwtdExecutableComponent">
50
- <File Id="GwtdExecutable" Source="!(bindpath.gwt)gwtd.exe" KeyPath="yes" />
58
+ <File Id="GwtdExecutable" Source="!(bindpath.gwt)gwtd.exe" Name="gwtd.exe" KeyPath="yes" />
51
59
  </Component>
52
60
  </ComponentGroup>
53
61