Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .claude/rules/cross-platform.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,22 @@ When the gated code uses no platform-specific API and only *running* it is platf

When gated code changes, update the comment that explains why the gate is needed. A stale explanation can lead someone to widen or copy an unnecessary gate.

## Verify before landing

Windows is not in CI, so the person (or agent) writing platform-specific code is the only line of defense. `cargo check` and `cargo clippy` do not link, so you can type-check the Windows build from any OS without an MSVC toolchain:

```bash
rustup target add x86_64-pc-windows-msvc # once
cargo clippy -p <crate> --all-targets --target x86_64-pc-windows-msvc -- -D warnings
```

`--all-targets` matters: the breakage is usually in tests (bd-j0pgiips, bd-lhi82470). This catches `std::os::unix` misuse (E0433/E0599) and, under `-D warnings`, cfg-gated dead code. Run it for every crate you touched; run the same command without `--target` for the host platform.

Caveats:

- Crates whose build scripts compile C for the target (e.g. `ring`, `v8`) may not cross-check from unix. If a crate you touched can't cross-check, say so in the PR so a Windows user can run the native check: `cargo clippy -p <crate> --all-targets -- -D warnings`.
- Cross-checking proves compilation only. Runtime behavior (file locking, line endings, process signals) still needs a Windows run — flag tests that exercise those for manual verification.

## File paths

- Use `std::path::Path`/`PathBuf`, never hardcode `/` or `\` separators
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ The changelog is rendered in the About section of the hub-client UI.
- **CRITICAL**: If you'll be writing tests, read the special instructions on file claude-notes/instructions/testing.md
- **CRITICAL**: For hub-client changes, passing tests alone is NOT sufficient. You must also verify that `npm run build:all` (from `hub-client/`) succeeds before claiming work is done. The production build (`tsc -b && vite build`) is stricter than `tsc --noEmit` and `vitest` — it uses project references mode and catches errors the other tools miss.
- **CRITICAL**: For any CLI- or user-visible feature, passing tests alone is NOT sufficient. See **End-to-end verification before declaring success** below.
- **Windows**: Some crates must be manually excluded from tests. See claude-notes/instructions/windows-dev.md for details.
- **Windows**: Windows is not in CI. When your change uses platform-specific APIs (`std::os::unix`/`std::os::windows`), adds `#[cfg(...)]` gates, or touches test helpers, cross-check before landing: `cargo clippy -p <crate> --all-targets --target x86_64-pc-windows-msvc -- -D warnings` (works from any OS; no linking). See `.claude/rules/cross-platform.md` and claude-notes/instructions/windows-dev.md.

## End-to-end verification before declaring success

Expand Down
13 changes: 13 additions & 0 deletions claude-notes/instructions/windows-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,16 @@ significantly.
## CI

Windows is not currently in the CI matrix. All Windows testing is manual.

Until a Windows leg exists, the pre-landing gate is a cross-check, which works
from any OS because `cargo check`/`cargo clippy` do not link:

```bash
rustup target add x86_64-pc-windows-msvc # once
cargo clippy -p <crate> --all-targets --target x86_64-pc-windows-msvc -- -D warnings
```

Run it for every crate you touch when your change uses `std::os::unix` /
`std::os::windows`, adds `#[cfg(...)]` gates, or touches test helpers. The full
rules and patterns are in `.claude/rules/cross-platform.md`; failure history:
bd-j0pgiips, bd-lhi82470, bd-5tdzaf3t.
20 changes: 18 additions & 2 deletions crates/quarto-mcp-launcher/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,10 +504,26 @@ mod tests {
);
}

/// Building a non-UTF-8 `OsString` is platform-specific, so the
/// fixture is a `cfg` pair and the test itself stays portable
/// (`.claude/rules/cross-platform.md`; bd-j0pgiips).
#[cfg(unix)]
fn non_utf8_os_string() -> std::ffi::OsString {
use std::os::unix::ffi::OsStringExt;
std::ffi::OsString::from_vec(vec![0xff, 0xfe])
}

/// A lone surrogate is ill-formed UTF-16, so `to_str()` returns
/// `None` for it just as it does for non-UTF-8 bytes on unix.
#[cfg(windows)]
fn non_utf8_os_string() -> std::ffi::OsString {
use std::os::windows::ffi::OsStringExt;
std::ffi::OsString::from_wide(&[0xD800])
}

#[test]
fn q2_path_injection_skips_non_utf8_exe_paths() {
use std::os::unix::ffi::OsStringExt;
let weird = std::ffi::OsString::from_vec(vec![0xff, 0xfe]);
let weird = non_utf8_os_string();
assert_eq!(q2_path_for_child(None, Some(PathBuf::from(weird))), None);
}
}
Loading