44 * Launches dist/codex-mobile-bridge.exe with isolated temp dirs and
55 * random ports, then validates:
66 * 1. HTTP GET /api/status returns 200 { status: 'ok' }
7- * 2. POST /api/pairing/generate returns { code, deviceId }
8- * 3. POST /api/pairing/verify with { code } returns { token }
9- * 4. state.db exists in BRIDGE_DATA_DIR (SQLite works)
10- * 5. service-crash.log has NO ABI / dlopen errors
7+ * 2. HTTP GET /index.html returns the Web/PWA shell
8+ * 3. POST /api/pairing/generate returns { code, deviceId }
9+ * 4. POST /api/pairing/verify with { code } returns { token }
10+ * 5. state.db exists in BRIDGE_DATA_DIR (SQLite works)
11+ * 6. service-crash.log has NO ABI / dlopen errors
1112 *
1213 * Exits 0 on pass, 1 on fail. No || true, no skipping checks.
1314 */
@@ -159,11 +160,25 @@ async function run() {
159160 }
160161 }
161162
163+ if ( pass ) {
164+ // CHECK 2: /index.html
165+ try {
166+ const r = await httpRequest ( 'GET' , '/index.html' ) ;
167+ if ( r . status !== 200 || ! r . raw . includes ( 'Codex Mobile Bridge' ) || ! r . raw . includes ( '/app.js' ) ) {
168+ pass = fail ( `/index.html returned ${ r . status } : ${ r . raw . slice ( 0 , 300 ) } ` ) ;
169+ } else {
170+ console . log ( ' CHECK PASS: /index.html -> Web/PWA shell' ) ;
171+ }
172+ } catch ( err ) {
173+ pass = fail ( `/index.html request failed: ${ err . message } ` ) ;
174+ }
175+ }
176+
162177 let pairingCode ;
163178 let pairingDeviceId ;
164179
165180 if ( pass ) {
166- // CHECK 2 : /api/pairing/generate
181+ // CHECK 3 : /api/pairing/generate
167182 try {
168183 const r = await httpRequest ( 'POST' , '/api/pairing/generate' , { } ) ;
169184 if ( r . status !== 200 || ! r . body || ! r . body . code || ! r . body . deviceId ) {
@@ -179,7 +194,7 @@ async function run() {
179194 }
180195
181196 if ( pass ) {
182- // CHECK 3 : /api/pairing/verify with { code }
197+ // CHECK 4 : /api/pairing/verify with { code }
183198 try {
184199 const r = await httpRequest ( 'POST' , '/api/pairing/verify' , { code : pairingCode } ) ;
185200 if ( r . status !== 200 || ! r . body || ! r . body . token ) {
@@ -197,7 +212,7 @@ async function run() {
197212 // Kill the exe now that HTTP checks are done
198213 killTree ( ) ;
199214
200- // CHECK 4 : state.db exists
215+ // CHECK 5 : state.db exists
201216 const dbPath = path . join ( dataDir , 'state.db' ) ;
202217 if ( ! fs . existsSync ( dbPath ) ) {
203218 pass = fail ( `state.db not found at ${ dbPath } — SQLite may have crashed` ) ;
@@ -206,7 +221,7 @@ async function run() {
206221 console . log ( ` CHECK PASS: state.db exists (${ dbSize } bytes)` ) ;
207222 }
208223
209- // CHECK 5 : crash log has NO fatal ABI errors
224+ // CHECK 6 : crash log has NO fatal ABI errors
210225 if ( fs . existsSync ( crashLog ) ) {
211226 const content = fs . readFileSync ( crashLog , 'utf-8' ) ;
212227 if ( / N O D E _ M O D U L E _ V E R S I O N / . test ( content ) ) {
0 commit comments