cleanup []

ober

dbacd80b0445145fff4c1d5d0c8b681cc28457ca

diff --git a/JERBOA-LANG.md b/JERBOA-LANG.md
index 426fc74..771b75d 100644
--- a/JERBOA-LANG.md
+++ b/JERBOA-LANG.md
@@ -82,12 +82,15 @@ Key points:
 
 Jerboa extends the Chez Scheme reader with Gerbil-inspired syntax.
 
-### Square Brackets → List Literals
+### Square Brackets — Plain Parentheses
+
+Square brackets are interchangeable with parentheses, exactly like Gerbil and
+stock Chez Scheme. Use them freely in bindings, match clauses, cond, etc.:
 
 ```scheme
-[1 2 3]           ;; → (list 1 2 3)
-[]                ;; → (list)
-[a [b c]]         ;; → (list a (list b c))
+(let ([x 1] [y 2]) (+ x y))
+(for/collect ([i (in-range 5)]) (* i i))
+(cond [(> x 0) "positive"] [else "non-positive"])
 ```
 
 ### Curly Braces → Method Dispatch
diff --git a/README.md b/README.md
index d30f4cd..47da40b 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@ scheme --libdirs lib --script your-file.ss
 └──────────────┬───────────────────────────────┘
 ┌──────────────▼───────────────────────────────┐
-│  Reader: [...] → (list ...), {...} → (~ ..)  │
+│  Reader: [...] = (...), {...} → (~ ..)       │
 │  :std/sort → (std sort) module paths         │
 ├──────────────────────────────────────────────┤
 │  Core Macros: def, defstruct, match, try     │
@@ -179,7 +179,7 @@ These modules use external C libraries via chez-* FFI shims. They remain functio
 - Full Gambit-to-Chez type mapping
 
 ### Reader (`(jerboa reader)`)
-- `[1 2 3]` → `(list 1 2 3)`
+- `[...]` = `(...)` — plain parentheses (same as Gerbil and Chez)
 - `{method obj}` → `(~ obj 'method)`
 - `keyword:` → keyword objects
 - `:std/sort` → `(std sort)` module paths
diff --git a/gerbil-like.md b/gerbil-like.md
index a522b46..7ffdfe2 100644
--- a/gerbil-like.md
+++ b/gerbil-like.md
@@ -49,20 +49,18 @@ No Gerbil expander. No gambit-compat.sls. No 1790 lines of `##` primitive shims.
 ### Layer 0: The Reader
 
 Handles:
-- `[1 2 3]` → list syntax
+- `[...]` → plain parentheses (interchangeable with `(...)`, same as Gerbil and Chez)
 - `{method obj}` → method dispatch
 - `keyword:` → keyword objects
 - `#!void`, `#!eof` → special values
 
-Instead of emitting `(@list ...)` and `(@method ...)` markers that the compiler interprets later, **expand them directly to Chez forms at read time**:
-
 ```scheme
-[1 2 3]       → (list 1 2 3)
-{method obj}  → (~ obj method)     ; ~ is the dispatch operator
-foo:          → (quote #:foo)      ; or a keyword record
+[x 1]         → (x 1)          ; brackets = parens, use freely in let/match/cond
+{method obj}  → (~ obj method) ; ~ is the dispatch operator
+foo:          → (quote #:foo)  ; or a keyword record
 ```
 
-This eliminates the compiler's need to pattern-match these. They're just Chez expressions by the time macros see them.
+Brackets are **not** list constructors — they are ordinary delimiters, matching Gerbil and stock Chez behavior.
 
 ### Layer 1: Syntax Macros
 
diff --git a/jerboa-native-rs/src/tls.rs b/jerboa-native-rs/src/tls.rs
index 7b5c413..70befb1 100644
--- a/jerboa-native-rs/src/tls.rs
+++ b/jerboa-native-rs/src/tls.rs
@@ -855,6 +855,90 @@ pub extern "C" fn jerboa_tls_connect_mtls(
     }
 }
 
+/// mTLS connect using in-memory cert/key data (no file paths).
+/// Avoids /proc/self/fd/ which Android SELinux may block.
+/// Returns handle ID (>0) on success, 0 on error.
+#[no_mangle]
+pub extern "C" fn jerboa_tls_connect_mtls_mem(
+    host: *const u8,
+    host_len: usize,
+    port: u16,
+    cert_pem: *const u8,
+    cert_pem_len: usize,
+    key_pem: *const u8,
+    key_pem_len: usize,
+) -> u64 {
+    match std::panic::catch_unwind(|| {
+        if host.is_null() || cert_pem.is_null() || key_pem.is_null() {
+            set_last_error("null argument".to_string());
+            return 0;
+        }
+        let host_str = unsafe {
+            match std::str::from_utf8(std::slice::from_raw_parts(host, host_len)) {
+                Ok(s) => s.to_string(),
+                Err(_) => { set_last_error("invalid UTF-8 hostname".to_string()); return 0; }
+            }
+        };
+        let cert_data = unsafe { std::slice::from_raw_parts(cert_pem, cert_pem_len) };
+        let key_data = unsafe { std::slice::from_raw_parts(key_pem, key_pem_len) };
+
+        // Parse client certs from PEM bytes
+        let client_certs: Vec<CertificateDer<'static>> =
+            rustls_pemfile::certs(&mut std::io::BufReader::new(cert_data))
+                .filter_map(|r| r.ok())
+                .collect();
+        if client_certs.is_empty() {
+            set_last_error("no client certificates found in PEM data".to_string());
+            return 0;
+        }
+
+        // Parse client private key from PEM bytes
+        let client_key = match rustls_pemfile::private_key(&mut std::io::BufReader::new(key_data)) {
+            Ok(Some(k)) => k,
+            Ok(None) => { set_last_error("no client private key found in PEM data".to_string()); return 0; }
+            Err(e) => { set_last_error(format!("read client key PEM: {}", e)); return 0; }
+        };
+
+        let config = match ClientConfig::builder()
+            .dangerous()
+            .with_custom_certificate_verifier(Arc::new(PinVerifier {
+                expected_sha256: None,
+            }))
+            .with_client_auth_cert(client_certs, PrivateKeyDer::from(client_key))
+        {
+            Ok(c) => c,
+            Err(e) => { set_last_error(format!("client config: {}", e)); return 0; }
+        };
+
+        let server_name = match ServerName::try_from(host_str.clone()) {
+            Ok(sn) => sn,
+            Err(e) => { set_last_error(format!("invalid server name: {}", e)); return 0; }
+        };
+
+        let conn = match ClientConnection::new(Arc::new(config), server_name) {
+            Ok(c) => c,
+            Err(e) => { set_last_error(format!("TLS client init: {}", e)); return 0; }
+        };
+
+        let addr = format!("{}:{}", host_str, port);
+        let tcp = match TcpStream::connect(&addr) {
+            Ok(s) => s,
+            Err(e) => { set_last_error(format!("TCP connect {}: {}", addr, e)); return 0; }
+        };
+
+        let stream = StreamOwned::new(conn, tcp);
+        let handle = next_handle();
+        conns().lock().unwrap().insert(handle, TlsConn::Client(stream));
+        handle
+    }) {
+        Ok(h) => h,
+        Err(_) => {
+            set_last_error("panic in tls_connect_mtls_mem".to_string());
+            0
+        }
+    }
+}
+
 // ============================================================
 // Read / Write / Close
 // ============================================================
diff --git a/lib/jerboa/reader.sls b/lib/jerboa/reader.sls
index 55a36b7..556056f 100644
--- a/lib/jerboa/reader.sls
+++ b/lib/jerboa/reader.sls
@@ -170,11 +170,10 @@
          (reader-next! rs)
          (annotate rs (read-list rs #\) (+ depth 1)) loc))
 
-        ;; Square brackets → (list ...)
+        ;; Square brackets — plain parentheses (same as Gerbil and Chez)
         ((char=? ch #\[)
          (reader-next! rs)
-         (let ((items (read-list rs #\] (+ depth 1))))
-           (annotate rs (cons 'list items) loc)))
+         (annotate rs (read-list rs #\] (+ depth 1)) loc))
 
         ;; Curly braces → (~ obj method args...)
         ((char=? ch #\{)