Skip to content

Commit 49ffbec

Browse files
chore: add copilot instructions (#39)
1 parent 0f46950 commit 49ffbec

2 files changed

Lines changed: 240 additions & 84 deletions

File tree

.github/copilot-instructions.md

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
# WebUI — Copilot Instructions
2+
3+
You are working on **WebUI**, a high-performance server-side rendering framework written in Rust that operates without JavaScript runtimes. It separates static and dynamic content at build time into a binary protocol that enables fast rendering in any host language.
4+
5+
Read and internalize these instructions at the start of every session. They are non-negotiable.
6+
7+
---
8+
9+
## Context you must load first
10+
11+
Before suggesting or applying **any** change, read these files — they are the ground truth:
12+
13+
1. **`DESIGN.md`** — The living technical specification. Architecture, protocol schema, module contracts, and behavioral rules all live here. Treat every constraint in it as mandatory unless the user explicitly asks to change one.
14+
2. **`Cargo.toml`** (workspace root) — Workspace members, dependency versions, and release profile.
15+
3. **`clippy.toml`** — Lint policy (bans `unwrap`/`expect`, caps cognitive complexity at 20, limits function arguments to 5).
16+
4. **`deny.toml`** — Allowed licenses and advisory ignore-list.
17+
5. The specific crate(s) under `crates/` that are relevant to the task at hand.
18+
19+
---
20+
21+
## The one rule that gates everything
22+
23+
Before creating **any** commit, run:
24+
25+
```bash
26+
cargo xtask check
27+
```
28+
29+
This executes, in order: `fmt → clippy → deny → test → build`. Work is **not done** until this passes cleanly. If it fails, fix every reported issue before proceeding. No exceptions.
30+
31+
---
32+
33+
## Performance is the top priority
34+
35+
Every decision — API design, data structure choice, algorithm, error path — must be evaluated through a performance lens first. WebUI's value proposition is speed; nothing else matters if it is slow.
36+
37+
### Hard constraints
38+
39+
| Rule | Rationale |
40+
|------|-----------|
41+
| **No recursion** in core algorithms | Use iterative loops with an explicit stack. Recursion blows the call stack on deep templates and defeats branch prediction. |
42+
| **No regular expressions** in core logic | Deterministic scanners are faster and more predictable. |
43+
| **Minimal runtime computation** | Move work to build time (the `webui build` CLI step) whenever possible. |
44+
| **Protobuf binary serialization** via `prost` | Zero-copy decoding; JSON is for `webui inspect` debugging only. |
45+
| **Buffer consolidation** | Reuse buffers, pre-allocate, avoid unnecessary allocations. |
46+
47+
### Allocation discipline
48+
49+
- `Vec::with_capacity` / `String::with_capacity` when size is known or estimable.
50+
- `push_str` / `write!` into existing buffers — never `format!` in hot paths.
51+
- No unnecessary `.clone()` — pass `&str`, `&[T]`, or slices. Use `Cow<'_, str>` when a value is sometimes borrowed, sometimes owned.
52+
- Prefer explicit state machines and stack-based traversal over recursive AST walking.
53+
54+
### Measurement
55+
56+
- Identify hot paths first: parsing, expression evaluation, handler rendering, protocol serialization, state lookups.
57+
- Measure **before** changing anything: `cargo bench -p <crate>` in `--release` mode.
58+
- After the change, re-measure and report the delta (qualitatively if exact numbers aren't available).
59+
- The smallest safe change that improves CPU time, allocation count, or cache locality wins. Do not over-engineer.
60+
61+
---
62+
63+
## Rust architecture standards
64+
65+
### Error handling
66+
- Library crates (`webui-parser`, `webui-handler`, `webui-expressions`, `webui-state`, `webui-protocol`, `webui-ffi`) use **custom error enums** via `thiserror`.
67+
- Binary crates (`webui-cli`, `xtask`) may use `anyhow`.
68+
- **No `unwrap()` or `expect()`** in library code — `clippy.toml` enforces this.
69+
- Errors must be **actionable**: tell the caller what went wrong *and* what they can do about it.
70+
71+
### Public API surface
72+
- Expose the minimum necessary. Use `pub(crate)` for internal helpers.
73+
- New public functions, structs, traits, and error variants must be documented with `///` doc-comments.
74+
- Use `#[must_use]` on functions whose return value should not be silently discarded.
75+
76+
### Code organization
77+
- One concern per module. When a file approaches ~400 lines, split it.
78+
- Types are `PascalCase`, functions are `snake_case`, constants are `SCREAMING_SNAKE_CASE`.
79+
- `cargo fmt --all` is the sole formatting authority — never override or disable it.
80+
81+
### Dependencies
82+
- Keep them minimal. Prefer the standard library. Before adding a crate, justify why std doesn't suffice.
83+
- Every dependency must pass `cargo deny check` (license allowlist + security advisories).
84+
- Prefer well-maintained crates under MIT or Apache-2.0.
85+
86+
### Safety
87+
- No `unsafe` without a `// SAFETY:` comment explaining the invariant upheld.
88+
- Prefer zero-copy borrowing over cloning. Prefer slices over owned collections when lifetime allows.
89+
- Keep cognitive complexity under 20 per function (enforced by clippy). Refactor, don't suppress.
90+
91+
### Concurrency (when applicable)
92+
- State explicit `Send + Sync` bounds.
93+
- Prefer `tokio::sync::mpsc` channels over `Arc<Mutex<_>>`.
94+
- Use atomics when a mutex is overkill.
95+
96+
---
97+
98+
## Tests are mandatory
99+
100+
Every code change ships with tests. No exceptions.
101+
102+
| Scenario | Requirement |
103+
|----------|-------------|
104+
| New public API | At least one unit test per function/method. |
105+
| Bug fix | A regression test that **fails** without the fix. |
106+
| Performance change | Benchmark comparison (before/after). |
107+
| Refactor | Existing tests must continue to pass unchanged. |
108+
109+
- Unit tests live alongside code in `#[cfg(test)]` modules.
110+
- Integration tests go in each crate's `tests/` directory.
111+
- Run the **targeted** crate first (`cargo test -p <crate>`), then the full workspace (`cargo test --workspace`).
112+
- Never remove, weaken, or `#[ignore]` an existing test unless the user explicitly asks.
113+
114+
---
115+
116+
## DESIGN.md is the living specification
117+
118+
`DESIGN.md` is not documentation — it **is** the specification. Code implements what `DESIGN.md` describes.
119+
120+
- **Read it** before any architectural or API change.
121+
- **Update it** in the same commit whenever you add, remove, or modify a public API, protocol field, fragment type, error variant, or behavioral contract.
122+
- Keep its Rust code examples conceptually compilable and in sync with real code.
123+
- If `DESIGN.md` and the code disagree, that is a bug — fix both.
124+
125+
---
126+
127+
## Developer docs (`/docs`) stay current
128+
129+
The `docs/` directory is a VitePress site for external developers consuming WebUI.
130+
131+
- Any change to user-visible behavior, CLI usage, or public API **must** include a corresponding docs update in the same PR.
132+
- New features get a guide page (`docs/guide/`) or tutorial (`docs/tutorials/`).
133+
- Verify with `cd docs && pnpm build` when possible.
134+
135+
---
136+
137+
## Branch and commit discipline
138+
139+
- **Never commit to `main` directly.** Create a branch: `<user>/<short-description>` (e.g. `mmansour/optimize-handler-allocs`).
140+
- One logical change per commit. Write imperative messages: *"Add …"* not *"Added …"*.
141+
142+
---
143+
144+
## Commands reference
145+
146+
| What | Command |
147+
|------|---------|
148+
| **Full gate (run before every commit)** | `cargo xtask check` |
149+
| Format | `cargo xtask fmt` |
150+
| Lint | `cargo xtask clippy` |
151+
| License & advisory audit | `cargo xtask deny` |
152+
| Tests (workspace) | `cargo xtask test` |
153+
| Build (workspace) | `cargo xtask build` |
154+
| Test a single crate | `cargo test -p webui-parser` (or any crate name) |
155+
| Benchmark a crate | `cargo bench -p webui-protocol` (or any crate name) |
156+
| Build in release mode | `cargo build --release` |
157+
| Docs site | `cd docs && pnpm build` |
158+
159+
---
160+
161+
## FFI boundary (`webui-ffi`)
162+
163+
The FFI crate exposes WebUI to **any** host language (C, C#, Go, Ruby, Python, Node.js, etc.) via a C-compatible ABI. Treat it as the project's most sensitive surface.
164+
165+
- Every `pub extern "C" fn` must have a `# Safety` doc section explaining pointer validity, lifetime, and ownership expectations.
166+
- All `unsafe` blocks require a `// SAFETY:` comment. No exceptions.
167+
- Assume callers are in a different language with no Rust safety net — validate every input (null pointers, invalid UTF-8, out-of-range values) before dereferencing or converting.
168+
- Never panic across the FFI boundary. Catch all errors and return them as error codes or null pointers. A panic in FFI is undefined behavior.
169+
- C header generation is handled by `cbindgen` in `build.rs`. After changing any `#[no_mangle]` function signature, verify the generated header in `include/webui_ffi.h` is correct.
170+
- Keep the FFI surface minimal and stable — additions are easy, removals break every consumer.
171+
- Platform-specific code must be gated behind `#[cfg(target_os = "...")]` and every platform path must be tested or at least compile-checked.
172+
- Design for ABI stability: prefer opaque pointers and integer error codes over exposing Rust struct layouts.
173+
174+
---
175+
176+
## Protobuf schema evolution
177+
178+
The protocol is defined in `crates/webui-protocol/proto/webui.proto` and compiled by `prost` via `build.rs`. Schema changes cascade through the entire stack: **protocol → handler → FFI → CLI**.
179+
180+
- Never remove or renumber existing proto fields — mark them `reserved` instead.
181+
- Add new fields as optional with sensible defaults so older serialized data remains decodable.
182+
- After any `.proto` change, rebuild the full workspace (`cargo xtask build`) and run all tests — not just the protocol crate.
183+
- Update `DESIGN.md` protocol section in the same commit.
184+
185+
---
186+
187+
## Workspace dependency management
188+
189+
All third-party dependency versions are centralized in the root `Cargo.toml` under `[workspace.dependencies]`.
190+
191+
- **Never** add a dependency version directly in a crate-level `Cargo.toml`. Use `dep = { workspace = true }` instead.
192+
- Before adding any new dependency, check if the standard library or an existing workspace dependency covers the need.
193+
- New dependencies must pass `cargo deny check` (license allowlist + advisory audit).
194+
195+
---
196+
197+
## Release profile awareness
198+
199+
The workspace ships with an aggressive release profile (`Cargo.toml`):
200+
201+
```toml
202+
[profile.release]
203+
lto = true # Full link-time optimization
204+
codegen-units = 1 # Maximum optimization (slower compile)
205+
panic = "abort" # No unwinding — smaller binary, but panics terminate immediately
206+
strip = true # Strip debug symbols
207+
```
208+
209+
- **`panic = "abort"` means panics kill the process instantly** — reinforcing why `unwrap`/`expect` are banned in library code.
210+
- Always validate performance claims in `--release` mode. Debug builds are not representative.
211+
- Be aware that LTO + single codegen unit makes release builds slow. Use `cargo test` (debug) for iteration, `cargo build --release` for final validation.
212+
213+
---
214+
215+
## Shared test utilities (`webui-test-utils`)
216+
217+
The `webui-test-utils` crate provides common test helpers, builders, and fixtures.
218+
219+
- Before writing new test helpers, check if `webui-test-utils` already has what you need.
220+
- New shared test utilities belong in `webui-test-utils`, not duplicated across crates.
221+
- Add it as a `[dev-dependencies]` entry: `webui-test-utils = { path = "../webui-test-utils" }`.
222+
223+
---
224+
225+
## Acceptance checklist
226+
227+
Before finishing any task, confirm **all** of these:
228+
229+
- [ ] `cargo xtask check` passes.
230+
- [ ] Changes include or update tests.
231+
- [ ] `DESIGN.md` is updated if any contract changed.
232+
- [ ] `docs/` is updated if any user-facing behavior changed.
233+
- [ ] No new recursion or regex in core paths.
234+
- [ ] No new `unwrap`/`expect` in library code.
235+
- [ ] No unnecessary allocations introduced; buffers reused where possible.
236+
- [ ] FFI changes include `# Safety` docs and never panic across the boundary.
237+
- [ ] Proto schema changes are backward-compatible and cascade-tested.
238+
- [ ] New dependencies use `workspace = true` and pass `cargo deny check`.
239+
- [ ] Commit is on a feature branch, not `main`.
240+
- [ ] Commit message is imperative with Copilot co-author trailer.

.github/skills/rust-performance/SKILL.md

Lines changed: 0 additions & 84 deletions
This file was deleted.

0 commit comments

Comments
 (0)