Editors, terminals, build systems, package managers, linters, formatters and test runners.
685 instructions from 30 repositories. Last updated 2026-05-08.
Tests should follow consistent structure and provide high-signal coverage.
Apply these rules: 1) Put tests in dedicated files
*_tests.rs (or *_test.rs) files, not inline #[cfg(test)] mod tests { ... } blocks.#[path = "..."] mod tests;.Example pattern:
// in source file
#[cfg(test)]
#[path = "my_module_tests.rs"]
mod tests;
2) Keep tests concise and behavior-focused
3) Consolidate related checks into regression-style tests
// regression for #10139).4) Assert complete, observable sequences
5) Ensure cross-platform coverage when you condition tests
These practices improve maintainability, reduce test brittleness, and ensure coverage remains accurate as behavior evolves.
When behavior depends on platform features, build features, feature flags, or user-provided configuration, keep it explicitly scoped and validated.
Apply this checklist:
#[cfg(...)] so non-target platforms don’t even compile unix/fs-only imports.local_fs is off, return a safe default (e.g., None/empty map) without referencing unavailable functionality.Example pattern (cfg + validated parsing):
// Build gating: don't compile unix-only code on Windows.
#[cfg(unix)]
mod local_api;
// Validation: enforce invariants at parse time.
fn parse_positive_usize_query_param(url: &Url, name: &str) -> Result<Option<usize>> {
let Some(raw) = url.query_pairs().find(|(k, _)| k == name).map(|(_, v)| v) else {
return Ok(None);
};
let value = raw.parse::<usize>()?;
ensure!(value > 0, "`{name}` must be greater than 0");
Ok(Some(value))
}
These practices prevent cross-platform build breaks, mis-scoped feature behavior, and silent misconfiguration—while keeping configuration-driven behavior predictable and maintainable.
When review finds repeated or “very similar” logic patterns, don’t leave copy-paste growth—refactor into a shared helper, and follow local file conventions so future edits don’t diverge.
Apply these rules: 1) DRY similar control-flow blocks
Example pattern (from the style of the suggested refactors):
// 1 helper used by multiple match arms
fn apply_harness_change<A, V>(
state: &mut OrchestrationEditState,
memory: &mut PerHarnessModelMemory,
handles: &OrchestrationPickerHandles<A>,
new_harness_type: &str,
fallback_base_model_id: impl FnOnce(&mut ViewContext<V>) -> Option<String>,
ctx: &mut ViewContext<V>,
) {
// ... shared harness-switch logic ...
// ... update picker/model selections ...
ctx.notify();
}
// called from different arms
apply_harness_change(
&mut self.state.orch,
&mut self.saved_model_per_harness,
&self.handles.pickers,
harness_type,
|ctx| block_model.base_model(ctx).map(|id| id.to_string()),
ctx,
);
2) Avoid duplication for readability a) Don’t call the same query method in both sides of an if/else—compute once before branching when it’s the same value. b) If match arms differ only by a small behavior, consider grouping them (or a shared function) rather than duplicating the surrounding scaffolding.
3) Keep file conventions consistent
#[cfg(test)] blocks at the bottom of the file).These changes should be “small refactors that prevent future drift”: they improve consistency without altering behavior.
When data is optional/unknown, handle it intentionally and explicitly—either skip the feature (return None) or fall back to a safe default—never via implicit drop or placeholder sentinel values.
Standards:
1) Use Option (or “unset” fields) to represent missingness. Don’t encode “missing user” as an empty string; use Option<String> (or clear the field) instead.
2) For optional features: return None when the input is absent or invalid (e.g., empty/unparseable config) so you don’t inject placeholder context.
3) For UX that must keep working: when an identifier can’t be resolved (unknown profile/name), fall back to a defined default rather than aborting.
4) Enforce invariants in types: if None should never occur, remove Option from parameters/fields and make it impossible to construct invalid states.
5) Be explicit in branching: enumerate all enum/location/type cases so non-local/null/unknown cases don’t get silently mishandled.
Example pattern (skip-or-fallback):
fn resolve_profile(agent_profile_name: Option<&str>, default_profile: &str) -> Option<&str> {
match agent_profile_name {
None => Some(default_profile),
Some(name) if is_known_profile(name) => Some(name),
Some(_unknown) => {
// Unknown should still resolve to something usable.
Some(default_profile)
}
}
}
fn load_optional_context(path: &Path) -> Option<String> {
let content = path.read_to_string().ok()?; // absent/IO error => None
if content.trim().is_empty() {
return None; // invalid/empty config => None (don’t inject placeholders)
}
Some(content)
}
When adding or modifying code, ensure comments/doc comments are written to explain meaning and rationale—not just what the code does or where it’s mutated.
Apply this checklist:
#[cfg] helpers) between a doc comment and the item it documents; structure code so the comment clearly binds to the intended symbol.Example (clarifying non-canonical state intent):
/// Current known statuses as reported to clients.
/// Not the canonical source of truth; once canonical indexing state is wired in,
/// this transitional cache should be removed.
codebase_index_statuses_by_repo: HashMap<String, RemoteCodebaseIndexStatus>,
Use naming that matches the code’s actual semantics and data contracts—avoid misleading terms and generic parameter names.
Apply these rules:
value; name the expected type/encoding.Example (pattern):
// Misleading: suggests truly removing state when we actually restore.
fn unset_warp_default(&mut self, ctx: &mut ModelContext<Self>) {
self.restore_macos_terminal_as_default(ctx)
}
// Contract-revealing parameter names.
pub fn format_git_branch_command(encoded_branch: &str) -> String {
// encoded_branch is a GitBranchOnClickValue-encoded string
format!("git checkout {encoded_branch}")
}
// Domain-accurate API naming.
pub fn scroll_to_matching_header(&mut self, header: &str) { /* ... */ }
// Clear terminology via an enum when behavior is two-state.
enum FullGridClearBehavior { ClearToTemplate, ScrollIntoScrollback }
When implementing algorithms for pairing/alignment, matching/routing, search, or event fan-out, require a clearly stated invariant and explicit boundary/edge-case behavior, then back it with targeted tests.
Practical checklist: 1) Define the mapping/invariant precisely
2) Make boundary behavior unambiguous
3) Use data structures that support required operations directly
4) Test the invariants at the boundaries
Mini example (alignment invariant style):
// Within each hunk: D deletions followed by A additions.
// Invariant: row indices correspond across panes.
let pairs = d.min(a);
for i in 0..pairs {
left_row(i) = deleted[i];
right_row(i) = added[i];
}
// Excess
for i in pairs..d {
left_row(i) = deleted[i];
right_row(i) = blank();
}
for i in pairs..a {
left_row(i) = blank();
right_row(i) = added[i];
}
Adopting this standard prevents “almost correct” algorithms that break only at boundaries (chunk edges, quota-trigger thresholds, prefix boundary rules, uneven hunk sizes) and makes future maintenance safer because invariants are explicit and testable.
APIs that cross module boundaries, wire formats, or event streams should be designed so callers can’t accidentally construct invalid requests or rely on unstable semantics.
Apply these rules: 1) Prefer request objects/enums over ambiguous parameters
(Option<T>, Option<U>) when only certain combinations are valid.ReportShutdownRequest) or split into distinct methods.Example:
async fn report_shutdown(&self, req: ReportShutdownRequest) -> Result<()> {
// handle only valid states; unreachable invalid combinations
}
// vs:
// async fn report_shutdown(&self, error_category: Option<String>, error_message: Option<String>) -> Result<()>;
2) Use named fields (and owned inputs) for client interfaces
struct parameters with named fields so arguments can’t be swapped.String) over &str for async/client boundaries unless there’s a strong lifetime reason.Example:
pub struct InitializeRequest {
pub user_id: String,
pub user_email: String,
pub crash_reporting_enabled: bool,
}
pub async fn initialize(&self, auth_token: Option<String>, req: InitializeRequest) -> Result<()>;
3) Evolve event/wire contracts compatibly
4) Be cautious with serialization changes
5) Keep public API surfaces intentional
These practices reduce misuse at the boundary, make intent obvious at call sites, and prevent subtle regressions when contracts evolve.
When handling auth secrets, user directory/path-based configuration, or shell-generated code, treat any value that could reveal identity/organization or execute code as sensitive and untrusted by default.
Apply these rules:
1) Define trust boundaries explicitly
2) Escape/serialize as data, never as code
3) Redact sensitive logs and diagnostics
4) Don’t “silently weaken” authorization scopes
Example patterns
A) Redacted warning message (path-key privacy)
fn warn_directory_override(key: &str, theme: &str) {
let redacted = redacted_key_id(key); // stable short id; never reversible without a local salt
log::warn!(
"directory_overrides[hash={}] : unknown theme '{}' — skipping this entry until corrected",
redacted,
theme
);
}
B) Inert secret/command snippets in untrusted flows
Enforcement checklist / tests
Implement failure handling so recovery is (1) bounded, (2) never hangs indefinitely, and (3) has explicit validation + deterministic fallback.
Apply this when adding retries, polling for readiness, or supporting boundary-specific execution paths:
// Pattern: on known limit failure, retry with bounded cost by adjusting quota.
match err {
ExceededMaxFileLimit => {
// Retry only what’s needed at shallow depth; avoid consuming the global quota again.
entry.build_tree(max_depth = 1, remaining_file_quota = None)?;
}
other => return Err(other.into()),
}
let ready = tokio::time::timeout(Duration::from_secs(30), wait_for_ready()).await;
match ready {
Ok(Ok(())) => {}
Ok(Err(e)) => return Err(e),
Err(_) => return Err(anyhow::anyhow!("Timed out waiting for follow-up session readiness")),
}
Explicit validation and fallback: for boundary-specific spawning (WSL/MSYS2/remote/local) validate required arguments up front and ensure unsupported paths fail predictably (graceful unsupported-shell fallback) rather than relying on implied behavior.
Any cached value must have an explicit, testable “when does it become stale?” policy, plus a fallback path when updates may be missed.
Apply this as a checklist: 1) State the cache scope & dependencies: What inputs does this cached data depend on? (e.g., harness selection + auth secrets, repo path + embedding config, shared snapshot version, identity key/authorization) 2) Enumerate invalidation triggers (at minimum):
Example pattern (Rust-style pseudocode):
enum CacheState<T> { Fresh(T), Stale { reason: String } }
fn should_invalidate(reason_from_inputs: Option<&str>, integrity_ok: bool) -> bool {
!integrity_ok || reason_from_inputs.is_some()
}
async fn get_with_invalidation(cache_key: Key) -> Result<Value> {
let entry = load_cache(cache_key)?;
if should_invalidate(entry.integrity_ok == false, entry.dep_version_changed) {
invalidate(cache_key);
return fetch_from_source(cache_key).await;
}
// If push might have been missed or we’re not confident it’s current:
if entry.age > TTL || entry.last_update_suspicious {
return fetch_and_replace(cache_key).await;
}
Ok(entry.value)
}
Result: fewer “mysteriously stale” UIs, safer authorization handling, and consistent behavior across both local and remote/daemon-backed caches.
When code performs expensive IO/compute or reacts to frequent events, (1) gate side effects to meaningful state changes, (2) bound or chunk large inputs/outputs before allocation or heavy processing, and (3) cache/share to avoid repeated recomputation and deep clones.
Apply this standard:
Example patterns (adapt as needed):
// 1) Gate side effects on meaningful state changes.
let is_dark = theme.inferred_color_scheme() == ColorScheme::LightOnDark;
let should_notify = {
let mut model = self.model.lock();
let changed = model.is_dark_mode() != is_dark;
model.update_colors(colors);
model.set_color_scheme(is_dark);
changed && model.is_term_mode_set(TermMode::DARK_LIGHT_NOTIFICATIONS)
};
if should_notify {
self.write_to_pty(format!("\x1b[?997;{}n", if is_dark { 1 } else { 2 }).into_bytes(), ctx);
}
// 2) Chunk large writes for constrained transports.
const CHUNK_SIZE: usize = 4096;
for (i, chunk) in bootstrap_bytes.chunks(CHUNK_SIZE).enumerate() {
// spawn/send with a small delay if needed to avoid buffer drops
send_chunk_with_delay(chunk, i * 50, ctx);
}
// 3) Stat-first size cap before reading full payloads.
let meta = std::fs::metadata(&path_str)?;
if meta.len() > MAX_IMAGE_SIZE_BYTES_FOR_CLI_AGENT {
show_toast(format!("{} is too large", filename), ctx);
continue;
}
// 4) Prefix-only sniffing.
let prefix = read_prefix(&path, MIME_SNIFF_BYTES)?;
let mime = infer_mime_type(&path, &prefix);
// 5) Compute caps/guards.
let entity_diff = if content_is_small_enough && !is_large_or_unrenderable {
compute_entity_diff(&content)
} else {
None
};
Result: fewer wasted computations, less memory churn, and fewer correctness/performance issues caused by oversized payloads or high-frequency event handling.
Define and implement explicit, user- and operator-facing error semantics for async/protocol code: handle recoverable/expected mismatches without panicking, make failure outcomes observable, and ensure recovery/retry behavior is bounded and well-specified.
Apply this standard
panic!/unhandled!(). Prefer return/ignore with log::warn! (including the offending parameters) and continue.Concrete examples
('n', Some(b'?')) => {
match next_param_or(0) {
996 => handler.report_color_scheme(writer),
other => {
log::warn!("Unhandled CSI ? Ps n query: {other}");
// graceful no-op
}
}
}
// On Ok(None) / Err, wait a little before re-opening the listener.
self.restart_backoff = self.restart_backoff.next();
warpui::async::sleep(self.restart_backoff).await;
self.start_dormant_claude_wake_listener(conversation_id, ctx);
Checklist: For any change touching error handling, confirm you can answer (a) what happens on failure, (b) whether it retries/reconciles, (c) how the user/client learns about it, and (d) where the error reason is captured (log/telemetry).
Adopt a “docs must be executable-accurate” standard: treat technical docs/specs/changelogs as part of the product contract, and ensure they exactly match current behavior, supported formats, and rendering constraints.
Apply this checklist before merge:
[#1234](https://...); prefer Unicode emojis over :sparkles: style shortcodes if the renderer can’t resolve them).Example (configuration doc precision):
# Flat YAML map: action_name -> key_trigger
# action_name contains ':' so it must be quoted
"workspace:toggle_ai_assistant": ctrl-s
"editor_view:delete_all_left": cmd-shift-A
"workspace:toggle_command_palette": none
Example (changelog rendering):
[#9275](https://github.com/warpdotdev/warp/pull/9275).✨ instead of :sparkles: when shortcode rendering isn’t available.When you cache UI/model state, make the cache key and lifecycle unambiguous:
Example (pattern):
// 1) Cache lookup should use the cache’s expected raw key.
let candidate = pathbuf; // raw
if let Some(hit) = detected_repos_cache.get(&candidate) {
// 2) Normalize only when constructing the stable group key/label.
let group_key = ProjectGroupKey::Root(normalize_project_group_path(hit.path.clone()));
return group_key;
}
// 3) Persist per-entity state; don’t use a transient default.
self.mouse_states
.entry(conversation_id)
.or_default(); // ensures the handle exists and is reused
// 4) Remove on deletion.
self.mouse_states.remove(&conversation_id);
Apply this checklist anytime you see HashMap-backed state, memoized computations, or “lookup + derived key” flows—most cache bugs here come from key normalization order, missing persistence, or missing refresh/invalidation paths.
When implementing networking/event-streaming and bidirectional sync, make event delivery correctness explicit: who owns the subscription, who owns cursor advancement, and whether an event should be echoed back.
Apply these rules: 1) Differentiate event origin (server-originated vs user-originated) before emitting a change back over the network, to prevent feedback loops. 2) Open SSE only for eligible consumers: exclude passive/shared/remote-run views that don’t actually receive inbox delivery in this process. 3) Define cursor ownership: only the component that “owns” the inbox should advance/persist cursors; avoid dormant subscribers that advance the server cursor, which can cause later replays to return nothing. 4) Trigger on the right event classes: don’t filter wake/delivery down to a narrow subset (e.g., only message events) if lifecycle/peer events should wake the process.
Minimal pattern:
// 1) Origin-aware echo prevention
match event {
BufferEvent::ContentChanged { delta, origin } => {
if origin == EventOrigin::Server {
// Don't push back to the server; it's already accounted for.
return;
}
// Push only user-originated changes.
send_edit_to_server(delta);
}
}
// 2) Eligibility predicate for SSE
fn is_eligible(conversation_id: AIConversationId, ctx: &AppContext) -> bool {
let has_consumer = driver_or_view_has_live_consumer(conversation_id, ctx);
let is_not_passive_remote_view = !is_shared_or_remote_child_view(conversation_id, ctx);
has_consumer && is_not_passive_remote_view
}
// 3) Cursor ownership: only the SSE owner updates cursor state
if this_process_owns_inbox(conversation_id) {
persist_cursor_sqlite(conversation_id, max_seq);
persist_cursor_server(conversation_id, max_seq);
}
This prevents the common networking failures implied by the discussions: echo loops in bidirectional sync, SSEs opened for the wrong role, missed wakeups from overly narrow filters, and cursor collision that causes replay gaps after dormancy.
All CI/CD automation should be deterministic, machine-independent, and enforced via failing gates—never relying on “latest tag,” unstated baselines, or author-local tooling.
Apply these rules: 1) Release automation must compute baselines programmatically
stable_00/01/02) explicitly in the baseline-selection logic.2) Standards should be enforced by CI-run checks
-D warnings).3) Test environments must be reproducible
Example (baseline selection + CI gate sketch):
// Pseudocode for deterministic “previous cut” lookup
fn previous_cut(tag: &str, all_tags: &[&str]) -> Option<&str> {
let channel = parse_channel(tag);
// Filter to same channel, then sort by the release-cut identifier
// (not by the most recent full tag string).
let mut cuts = release_cuts_for_channel(channel, all_tags);
// Find the cut immediately preceding the one containing `tag`
cuts.find_preceding_cut(tag)
}
// CI (presubmit) should fail on lint violations
// cargo dylint --lib appearance_theme_in_tab_path -- -D warnings
Net effect: release artifacts are correct, rules are enforced automatically, and CI results match across machines.
Adopt a consistent rule: anything coming from persistence, other platforms/accounts, terminal escape sequences, or secret-managed inputs must be validated/normalized and handled with collision-safe, non-injectable, non-leaky logic.
Apply this as standards:
themes_dir(). Preserve “foreign” absolute paths (don’t attempt partial cross-platform legacy inference).../parent traversal behavior and add Windows-specific coverage where paths/roots differ.0o600) on Unix.Example patterns (condensed):
// 1) Shell quoting helper
fn shell_single_quote(value: &str) -> String {
format!("'{}'", value.replace("'", "'\\''"))
}
// 2) Secret env insertion with collision safety
fn build_secret_env_vars(secrets: &HashMap<String, ManagedSecretValue>) -> HashMap<OsString, OsString> {
let mut env_vars = HashMap::new();
for (secret_key, secret) in secrets {
// typed secrets: if any env var is already set non-empty, skip that secret entirely
// (and never override existing process env)
for (env_name, env_value) in typed_secret_entries(secret) {
if std::env::var(env_name).is_ok_and(|v| !v.is_empty()) {
continue; // collision: skip
}
env_vars.insert(OsString::from(env_name), OsString::from(env_value));
}
}
env_vars
}
Ensure async/stateful flows are race-free by avoiding overlapping work for the same logical key and by handling events that arrive before the relevant state is ready.
Practical rules:
path, session_id, conversation_id) can be triggered concurrently, allow only one in-flight async task per key. Queue subsequent updates and apply them sequentially after the current task completes.Example (per-key queue to prevent stale overwrites):
// pseudo-pattern
if let Some(queued) = pending_updates.get_mut(&key) {
queued.push(update);
return;
}
pending_updates.insert(key.clone(), Vec::new());
let rules = current_rules.clone();
spawn(async move {
process_update(update, rules, key.clone()).await
}, move |me, result, ctx| {
me.apply(result);
me.drain_pending_updates(&key, ctx); // sequentially process queued updates
});
When implementing matching/diff logic (especially for code/entities), define and test the algorithmic invariants you rely on, and avoid fragile heuristics.
Apply:
Example (structural hash rename-invariant):
fn compute_body_hash_invariant(content: &str, start: usize, end: usize, body_bytes: &[u8]) -> u64 {
// Mask the entity name span so renames don’t change the structural hash.
let mut bytes = body_bytes.to_vec();
// Replace non-whitespace characters in [start, end) with spaces (conceptually).
for b in &mut bytes {
if *b != b' ' && *b != b'\n' && *b != b'\t' { *b = b' '; }
}
let mut hasher = std::collections::hash_map::DefaultHasher::new();
bytes.hash(&mut hasher);
hasher.finish()
}
Outcome: fewer misclassified diffs (renames vs modifications vs moves), deterministic behavior, and safer results under edge cases and degraded indexing.
Build-time behavior that depends on versions, paths, or external metadata should be configured explicitly and reproducibly—never implicitly via network calls or brittle patching.
Apply these rules:
1) Avoid mutable network state during Nix builds/evaluation. If a value (e.g., release/version info) can change, don’t fetch it at build time; instead, pass it as an explicit declared input (or keep it unset and let Nix own upgrades).
2) Prefer configuration knobs (env vars / explicit inputs) over cross-repo string hacks. If another repo needs different paths/behavior for your build, that repo should read an env var and fall back to its current relative defaults.
3) Make pinned external dependencies update-visible. Use explicit flake inputs (even with flake = false) so updates go through the normal flake.lock workflow instead of hidden fetchFromGitHub inside expressions.
Example pattern (replace brittle substituteInPlace with upstream env-var overrides):
// build.rs in warpdotdev/warp-proto-apis (proposed)
use std::path::PathBuf;
fn main() {
let proto_path = std::env::var("WARP_PROTO_APIS_DIR").ok()
.map(PathBuf::from)
.unwrap_or_else(|| {
// fallback to existing behavior
let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
manifest_dir.parent().unwrap().parent().unwrap().to_path_buf()
});
println!("cargo:rerun-if-env-changed=WARP_PROTO_APIS_DIR");
// use proto_path...
}
Then in your Nix expression, pass the override:
substituteInPlace "${./path/to/derivation}" {
# ...
}
# and ensure the derivation sets the env var, e.g. via buildPhase:
# export WARP_PROTO_APIS_DIR=${warpProtoApis}/apis/multi_agent/v1
Outcome: fewer surprising build failures, clearer upgrade semantics, and safer, testable configuration changes across repos.
When log behavior depends on configuration (e.g., WARP_CHANNEL) or when scripts auto-select an environment/tool (e.g., which Xcode app to use), make the behavior explicit and observable:
elif for each supported channel/value).Example pattern (channel-aware log file selection):
if [ "$WARP_CHANNEL" = "local" ]; then
LOG_FILE=~/Library/Logs/warp_local.log
elif [ "$WARP_CHANNEL" = "oss" ]; then
LOG_FILE=~/Library/Logs/warp_oss.log
else
echo "Warning: unrecognized WARP_CHANNEL='$WARP_CHANNEL'" >&2
LOG_FILE=~/Library/Logs/warp.log
fi
echo "Using log file: $LOG_FILE"
When authoring CI/CD workflows, make configuration choices that (1) match the actual capabilities required by downstream steps and (2) use conservative, contributor-safe defaults for automated cleanup.
git blame, changelog generation, diffing across tags/commits), ensure the checkout includes sufficient history (commonly full history via fetch-depth: 0) and don’t remove it without verifying the dependency.Example (git history):
- uses: actions/checkout@v4
with:
ref: ${{ needs.analyze.outputs.analyzed_sha }}
fetch-depth: 0 # required for git blame/history-based steps
Example (conservative stale closure):
const LABEL = 'needs-info';
const BUSINESS_DAYS = 10; // ~1–2 weeks; adjust only with a strong reason
When an API operation can be “partially successful” (or yields an empty but non-error outcome), encode that distinction explicitly in the response/protocol so callers can take correct next actions.
Apply this standard:
Success with an empty result to represent distinct conditions like “requested line range is beyond EOF”.missing_ranges: [...] / failed_ranges: [...]) instead of forcing an all-or-nothing Failure or misusing an existing field with different semantics (e.g., treating “range missing” as “file missing”).state enums and failure categories; prefer bulk initialization/status RPCs over repeated per-entity polling when clients need initial state.Example pattern (server response shape):
// Instead of: ReadFilesResult::Success { files: vec![] }
// Use something like:
ReadFilesResult::Success {
files: vec![/* successfully read files */],
missing_ranges: vec![
MissingRange { path: "a.txt", line_range: (1891, 2090) }
],
}
// Or, if per-file success is granular:
ReadFilesResult::Success {
per_file: vec![
PerFileResult::Ok { path: "a.txt", segments: vec![...] },
PerFileResult::MissingRange { path: "b.txt", requested: (1891, 2090), eof: 1237 },
]
}
This keeps the API truthful, prevents misleading UI states, and lets agent/client logic “course-correct” without breaking the ability to return other successfully retrieved items.
Treat configuration as a stable, privacy-safe contract: it must load without breaking the whole file, resolve safely at apply-time, use platform-correct paths, and (for significant changes) be shipped behind feature flags with explicitly defined non-lossy toggle behavior.
Apply these rules when you change or add configuration, settings, or config-driven behavior:
1) Prefer Settings persistence over ephemeral UI
2) Feature-flag major behavior changes
3) Make config parsing fail-soft; validate at apply-time
Option<String> for free-form references at the schema layer, then resolve into canonical internal types during application.4) Resolve paths centrally and pass resolved values
~/.warp*/.5) Treat sensitive config data as local-only; redact diagnostics
6) Keep bundled/agent-exposed skills aligned with the schema
working_directory), update the bundled skill so it explains defaults and supports the override parameter with correct example structure.Example pattern (fail-soft + apply-time resolution + safe warning):
// Schema layer: never fails load on unknown values
#[derive(Deserialize)]
struct Entry { theme_ref: Option<String> }
// Apply-time resolution (per-entry fallback)
fn apply_entry(entry: Entry) {
if let Some(raw) = entry.theme_ref {
match resolve_theme_ref(&raw) {
Some(theme) => set_effective_theme(theme),
None => {
let id = redacted_key_id(&raw); // or for the config key
log::warn!("config[hash={}] unknown theme '{}'; skipping entry", id, raw);
// fall through to next resolution layer
}
}
}
}
Use this standard as a checklist during reviews for anything under the “Configurations” umbrella: settings schema changes, feature-flag rollout wiring, config-driven rendering/application, path handling, and privacy/sync behavior.
Use canonical, source-verified naming for identifiers and for artifact locations. Avoid guesses, stale references, or incidental structure (like username folders).
Apply:
Example (action naming rule):
workspace:show_keybinding_settings) rather than a similarly named page action.cmd-k / workspace:toggle_keybindings_page if source verification shows the canonical editor shortcut/action is different.Example (path naming rule):
specs/<linear-ticket-id>/....specs/<username>/<linear-ticket-id>/... or any structure that doesn’t match the ticket-id convention.When working with nullable/optional values or external/runtime-provided fields, never assume presence or a specific concrete type/spelling. Instead: (1) explicitly treat inputs as optional, (2) provide deterministic fallbacks (often empty string/None/previous-state), (3) avoid dereferencing missing values, and (4) add tests for both “value present” and “value absent / alternate field present” cases.
Apply this especially to:
"") rather than constructing partial commands/paths.Example (runtime field fallback):
fn nu_home_path(env: &HashMap<String, String>) -> String {
// Prefer $nu.home-path when exposed; fall back to $nu.home-dir, then finally $HOME.
env.get("nu.home-path")
.or_else(|| env.get("nu.home-dir"))
.or_else(|| env.get("HOME"))
.cloned()
.unwrap_or_else(|| "".to_string())
}
Checklist for PRs:
When writing shell scripts that run privileged operations, never call sudo directly or execute such commands silently. Centralize privilege escalation in a helper that (1) prints the exact command being run, (2) prompts for confirmation by default, and (3) provides an explicit, documented non-interactive escape hatch for CI (e.g., an env var like WARP_BOOTSTRAP_YES=1 or auto-skip when stdin isn’t a TTY).
Example (bash):
#!/usr/bin/env bash
set -euo pipefail
warp_sudo() {
local cmd=("$@")
echo "About to run as sudo: ${cmd[*]}"
if [[ "${WARP_BOOTSTRAP_YES:-false}" == "true" ]] || [[ ! -t 0 ]]; then
sudo "${cmd[@]}"
return
fi
read -r -p "Proceed? [y/N] " ans
case "${ans}" in
y|Y) sudo "${cmd[@]}" ;;
*) echo "Aborted."; return 1 ;;
esac
}
# Use the helper instead of direct sudo:
# warp_sudo brew install jq
# warp_sudo apt-get update
Apply this standard anywhere your scripts install system-wide packages, modify system configuration, or otherwise require super-user privileges.
For any PR that affects the build/release pipeline (scripts, manifests like package.json, or release tooling), require:
1) Pipeline must be green before requesting/continuing review
2) Release automation must be complete and consistent
3) Local quality gates must mirror CI (or be clearly split)
pnpm lint behave differently from what CI runs.Example script structure (align local with CI, while still allowing fast runs):
{
"scripts": {
"lint:fast": "pnpm biome check && pnpm lint:jison",
"lint:fast:fix": "pnpm biome check --write",
"lint:slow": "pnpm lint:fast && cross-env NODE_OPTIONS=--max_old_space_size=16384 eslint --cache --cache-strategy content .",
"lint": "pnpm lint:slow",
"lint:fix": "pnpm lint:fast:fix && cross-env NODE_OPTIONS=--max_old_space_size=8192 eslint --cache --cache-strategy content --fix . && tsx scripts/fixCSpell.ts"
}
}
Also update any CI workflow or automation that calls the old script names so CI and local stay in sync.
Practical checklist before merge:
pnpm lint (and other gated commands) reflect what CI enforces, or the split is explicit and workflow references are updated.Adopt consistent, explicit identifier naming across diagrams and TypeScript APIs.
Rules 1) Diagram ids/syntax keywords
-beta to the syntax/keyword the parser accepts.Mini or extra suffixes like Language unless the codebase has a single established pattern).2) TypeScript naming style
DiagramStylesProvider).interface for object shapes when possible.3) Type-only files
.d.ts for internal project types..type.ts (e.g., gantt.type.ts).4) Exported fields/props
width/height over w/h) to improve readability for downstream users.5) Stability/compatibility for naming formats
Example
// diagram detector keyword
const detector: DiagramDetector = (txt) => /^\s*contextMap-beta/.test(txt);
// stable diagram config key naming: one established pattern
export interface MermaidConfig {
contextMap?: MiniContextMapLanguageDiagramConfig; // avoid “Mini…Language…” unless consistent everywhere
}
// type-only file convention
// packages/mermaid/src/diagrams/gantt/gantt.type.ts
export type DiagramStylesProvider = (options?: Record<string, unknown>) => string;
// explicit fields
export interface NodeMetaData {
width?: string;
height?: string;
}
Use the language parser/grammar (e.g., Langium/Jison) for diagram syntax instead of hand-rolled regex parsing. Regex is allowed only for small, well-bounded token-level helpers when (a) it precisely matches the intended grammar slice (e.g., remove only outer quotes), (b) it doesn’t destructively change user content or semantics, and (c) it preserves source positions/ranges by avoiding pre-processing that removes/reflows lines before parsing.
Apply these rules:
.langium / grammar layer.%% ... comments and directives in the parser so AST line/range data stays accurate.Example: wrapper-quote removal must be outer-only (not global):
function stripOuterQuotes(s: string): string {
const t = s.trim();
if ((t.startsWith('"') && t.endsWith('"')) || (t.startsWith("'") && t.endsWith("'"))) {
// remove only the outer quotes
return t.slice(1, -1);
}
return t;
}
When you must match with regex (e.g., token-level extraction), keep it narrowly scoped and back it with tests for edge cases (escaped quotes, whitespace variations, delimiter presence, comments).
Ensure changeset PRs produce correct and minimal release automation output.
Apply these rules before submitting:
major: reserved for breaking changes.patch: bug fixes / no user-facing behavior change.minor: non-breaking new functionality/improvements that affect users.chore) when major/minor/patch is expected.Example (correct semver selection + scoped header):
---
'mermaid': patch
---
fix: Correct diagram rendering regression
Example (split multi-package change into separate files):
@mermaid-js/examplesmermaid
with each file containing only its relevant release-note text and semver decision.When implementing or extending functionality, ensure tests (primarily unit tests for non-renderer code) cover the full supported behavior surface—not just a subset.
Apply this as:
Example pattern (unit-test style):
const supportedTags = ['em','strong','sup','a','ul','li'];
describe('timeline label HTML support', () => {
supportedTags.forEach((tag) => {
it(`renders timeline label with <${tag}>`, () => {
const input = `Label with <${tag}>text</${tag}>`;
const output = renderTimelineLabel(input); // your unit-level function
expect(output).toContainTag(tag); // adapt to your assertion style
});
});
});
This standard prevents partial coverage (only testing <br>/<strong>) and ensures consistent test expectations across the codebase.
When you change an exported/non-trivial API (or add new function parameters), update JSDoc so it is complete and directly helpful:
{type} and a short description of what the parameter controls.@deprecated and point to the replacement using a link (e.g., {@link NewSymbol}), not just plain text.Example (parameter documentation)
/**
* @param {any} node
* @param {number} [width] - Max/target label width used for wrapping calculations.
* @param {boolean} [addBackground=false] - Whether to apply the label background styling.
* @returns {Promise<SVGForeignObjectElement>}
*/
async function addHtmlLabel(node, width, addBackground = false) {
// ...
}
Example (deprecation documentation)
/**
* @deprecated Use {@link getBoundaries} instead
*/
export const getBoundarys = getBoundaries;
When rendering/layout is affected by configuration or theming, avoid magic numbers and ad-hoc config handling. Instead:
"false" the same as false).themeVariables (or CSS vars like --mermaid-font-family) rather than hard-coding constants that break with different fonts/sizes.Example pattern:
// config.js
export function getEffectiveFlowchartHtmlLabels(siteConfig) {
// Correctly coerce string booleans
const v = siteConfig?.flowchart?.htmlLabels;
return v === true || v === 'true';
}
And for theme-derived styling:
// instead of spacing = 60; or font-family: ${options.fontFamily};
const spacing = themeVariables?.noteSpacing ?? 60; // or derive from other theme vars
const fontFamily = 'var(--mermaid-font-family), trebuchet ms, verdana, arial, sans-serif';
When writing tests, ensure they (1) match the scenario name and input data, (2) exercise behavior through the appropriate layer (prefer public/high-level APIs so defaults/precedence are covered), (3) use the project’s DOM test helpers/fixtures and avoid unnecessary mocks/polyfills, and (4) assert specific outcomes (including exact error messages) rather than broad behaviors.
Apply it like this:
jsdomIt can provide a real DOM, prefer it over spies/mocked D3/cytoscape.Example (DOM test with fixture + specific assertions):
import { expect } from 'vitest';
import { jsdomIt } from '../test-utils/jsdomIt';
import { select } from 'd3-selection';
import { addSVGa11yTitleDescription } from './a11y';
jsdomIt('does not insert title tag', ({ svg }) => {
const svgSelection = select<SVGSVGElement, never>(svg);
addSVGa11yTitleDescription(svgSelection, 'chart-title', undefined, 'givenId');
const titleNode = svg.querySelector('title');
expect(titleNode).toBeNull();
});
Example (error message assertion):
await expect(renderSomething(badInput)).rejects.toThrow(
'Expected exact error message here'
);
This combination prevents “false green” tests, improves coverage, reduces brittle mocks, and makes regressions easier to diagnose.
All documentation examples/configs must be compatible with the docs build/render pipeline and current Mermaid configuration conventions.
Apply this checklist when touching documentation:
themeVariables) over deprecated %%{init: ...}%% in examples.(v<MERMAID_RELEASE_VERSION>+) (or the project’s equivalent placeholder) when the behavior is version-dependent.mermaid-example, include one block—don’t add multiple identical code fences.Example (correct: frontmatter + single mermaid-example + version tag):
```mermaid-example
---
title: ELK layout example
config:
layout: elk
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
**Example (avoid):**
- Using `%%{init: ...}%%` when examples have been migrated to YAML/frontmatter.
- Copy-pasting the same `mermaid-example` block twice (final docs will render duplicates).
---
## Config must be consistent
<!-- source: mermaid-js/mermaid | topic: Configurations | language: TypeScript | updated: 2026-01-08 -->
Ensure every rendering/utility path uses the correct configuration *namespace* and that config values are passed explicitly (not implicitly via global getters or captured/stale variables).
Practical rules:
- **Match config paths end-to-end**: if tests set `config.flowchart.htmlLabels`, the code that affects label sizing must read the same path (and the same key name).
- **Don’t pull config inside internal helpers**: prefer passing `config`/needed flags as parameters so helpers are deterministic and easy to test.
- **Avoid caching/stale config snapshots**: don’t compute `const conf = getConfig().<section>` once if it can be initialized later; fetch/use config at the correct lifecycle or keep the prior approach.
- **Use diagram-specific defaults**: when computing defaults for a diagram/module, read from its own config section (e.g., block defaults from `config.block`, not `config.flowchart`).
Example pattern (config injection):
```ts
// Bad: internal utility reaches out to global config
import { getConfig } from '../config.js';
function preprocessMarkdown(markdown: string) {
const markdownAutoWrap = getConfig().markdownAutoWrap;
// ...
}
// Good: pass only what you need
function preprocessMarkdown(markdown: string, markdownAutoWrap: boolean) {
// ...
}
// Call site
const { markdownAutoWrap } = getConfig();
preprocessMarkdown(markdown, markdownAutoWrap);
Null/undefined safety should prevent crashes and preserve correct semantics. Don’t hide missing required inputs with optional chaining or weak fallbacks.
Standards
themeVariables) is expected to exist, check it and emit a warning/error when it’s missing instead of silently continuing.null sentinels: If downstream code expects a color/string/number/boolean, provide a real default of that type—avoid ?? null unless the API explicitly supports null.value || true (it always becomes true). Compute booleans with correct precedence.null vs undefined: Use ?? when you only want to treat null/undefined as “missing”, and add explicit branches when precedence matters.Example pattern
function getThemeValue<T>(theme: any, key: string, fallback: T): T {
if (!theme) {
console.warn(`Missing themeVariables; using fallback for ${key}`);
return fallback;
}
const value = theme[key];
if (value === undefined || value === null) {
console.warn(`Missing theme value ${key}; using fallback`);
return fallback;
}
return value as T;
}
const quadrant1Fill = getThemeValue(themeVariables, 'quadrant1Fill', '#000000');
// Boolean example: avoid `anything || true`
const useHtmlLabels = node.useHtmlLabels ?? evaluate(config.htmlLabels ?? undefined) ?? true;
Applying these rules makes UI/config failures easier to diagnose, avoids runtime surprises from invalid sentinel values, and keeps boolean/null semantics correct.
When handling possibly-null/undefined/empty inputs, be explicit about nullability and keep code aligned with the promised types/semantics.
Practical rules:
??) over falsy checks (||) when false (or 0) is a valid value that must not be treated as “missing”.undefined when the function claims string).number | string) via a shared parser or an explicit typeof check.null defaults; add/propagate types so nullability doesn’t collapse inference.Example pattern:
function getStylesFromDbInfo(dbInfoItem) {
return dbInfoItem?.styles ?? ''; // always a string
}
function useHtmlLabels(node, config) {
// preserves false when it matters; only falls back on null/undefined
return node.useHtmlLabels ?? config.flowchart.htmlLabels;
}
function getTasks(rawTasks, dateRange) {
if (dateRange === '') return rawTasks; // early return on empty input
// parse defensively
const [startStr, endStr] = dateRange.split(',');
// only use pieces if present
}
This reduces null/reference bugs and prevents subtle behavior changes caused by incorrect falsy-vs-nullish handling or mismatched return contracts.
When changing a user-facing interface (API/config/grammar or externally consumed resources), treat it as a versioned contract:
1) Classify change severity and reflect it in release artifacts
2) Isolate breaking changes from releases you can’t roll back
3) Explicitly version external interface/resource URLs
Example patterns:
htmlLabels config value whenever possible‘my-feature’: minor
—
feat: Deprecate flowchart.htmlLabels in favor of root-level htmlLabels
- Staged syntax release (don’t mix breaking syntax):
```text
Release N: ship only `@{ ... }` syntax (no additional simplified grammar)
Release N+1: add simplified syntax under separate ticket/version
// Prefer an URL that includes a major version segment
fetch('https://cdn.example.com/mermaid@3/icons/icons.json')
Apply this standard to ensure clients get predictable behavior, deprecations are actionable (not vague), and breakage risk is contained through semantic change classification and explicit versioning.
When performance matters, structure code to avoid unnecessary work: (1) keep cheap fast-paths first for short-circuiting, (2) cache expensive global lookups (like config) instead of repeatedly calling them, (3) reuse costly parser/services/stateful objects, (4) lazy-load heavy dependencies only when required, and (5) remove redundant rendering/computation that increases output size.
Practical rules:
// Fast path: user/node override avoids config evaluation
const useHtmlLabels = node.useHtmlLabels || getEffectiveHtmlLabels(getConfig());
getConfig() once per function scope.
const config = getConfig();
const titleColor = config.themeVariables.titleColor;
if (needsMathML && hasKatex(text)) {
const katex = await import('katex');
// ...use katex
}
These changes reduce CPU time, allocations, and network/module load, improving both runtime responsiveness and load time.
Optimize performance-sensitive code by eliminating unnecessary work:
// Prefer cheap value first to avoid extra computation
const useHtmlLabels = node.useHtmlLabels || getEffectiveHtmlLabels(getConfig());
forEach/map/render loops.
const config = getConfig();
data.nodes.forEach((item) => {
// use cached config
});
// Idea: shared label transform + optional lazy import of heavy lib
export async function renderMathLabels(input) {
const { katex } = await import('katex');
return katex.renderToString(/*...*/);
}
Apply a consistent, tool-friendly coding style to reduce formatting churn and improve readability.
Rules
sometimes vs a + ‘ ‘` other times). Prefer a single consistent pattern.=== / !== everywhere (avoid ==).Example (test string readability + stable diffs)
it('should parse bidirectional arrow', async () => {
const str = `sequenceDiagram\nAlice-><Bob:Hello Bob, how are you?`;
await mermaidAPI.parse(str);
const messages = diagram.db.getMessages();
expect(messages).toHaveLength(1);
});
Example (avoid magic numbers)
const TODAY_LINE_WIDTH = 30;
line.attr('y2', conf.titleTopMargin + TODAY_LINE_WIDTH);
Use this checklist when preparing commits: if a change is purely formatting, isolate it (or revert it) and keep PR intent behavior-focused.
Ensure logs are actionable: always include relevant context identifiers (e.g., full connection name, user or request id) and log any returned errors so failures are visible and debuggable. Mask or redact sensitive fields when necessary and choose an appropriate log level (info for status changes, warn/error for failures).
How to apply:
Code examples (pattern to follow):
// include full connection name and log error if err := conn.Connect(ctx, connFlags); err != nil { // show identifying context and the error log.Printf(“error connecting to %q (status=%q): %v”, conn.GetName(), conn.GetStatus(), err) return fmt.Errorf(“cannot connect to %q when status is %q: %w”, conn.GetName(), conn.GetStatus(), err) }
// always log helper errors and goroutine results err := setNoReleaseCheck(ctx, clientData, false) if err != nil { log.Printf(“failed updating client no-release-check for client=%q: %v”, clientData.ClientID, err) return err }
go func() { if err := releasechecker.CheckNewRelease(false); err != nil { log.Printf(“background release check failed: %v”, err) } }()
Notes:
When updating code, prioritize maintainability and readability by removing duplicated blocks, eliminating magic numbers, and keeping formatting/imports tooling-friendly.
Apply these rules:
Example (extract repeated wrap/shrink into one function):
const MAX_AVAILABLE_WIDTH = pieWidth - MARGIN;
const START_FONT_SIZE = 25;
const MIN_FONT_SIZE = 8;
function renderWrappedTitle(svg: any, titleText: string) {
let fontSize = START_FONT_SIZE;
let wrapped = wrapLabel(titleText, MAX_AVAILABLE_WIDTH, {
fontSize,
fontFamily: 'Arial',
fontWeight: 400,
joinWith: '<br/>',
});
// measure once per fontSize change
let tempTitle = svg.append('text')
.attr('x', pieWidth / 2)
.attr('y', 30)
.attr('class', 'pieTitleText')
.style('text-anchor', 'middle')
.style('white-space', 'pre-line')
.style('font-size', fontSize + 'px');
while (tempTitle.node()?.getBBox().width > MAX_AVAILABLE_WIDTH && fontSize > MIN_FONT_SIZE) {
tempTitle.remove();
fontSize -= 1;
wrapped = wrapLabel(titleText, MAX_AVAILABLE_WIDTH, {
fontSize,
fontFamily: 'Arial',
fontWeight: 400,
joinWith: '<br/>',
});
tempTitle = svg.append('text')
.attr('x', pieWidth / 2)
.attr('y', 30)
.attr('class', 'pieTitleText')
.style('text-anchor', 'middle')
.style('white-space', 'pre-line')
.style('font-size', `${fontSize}px`);
}
const lines = wrapped.split('<br/>');
lines.forEach((line, idx) => {
tempTitle.append('tspan')
.attr('x', pieWidth / 2)
.attr('dy', idx === 0 ? 0 : '1.2em')
.text(line);
});
return tempTitle;
}
Following this standard reduces duplicated maintenance work, makes “why” obvious (constants), and keeps code easier to review and debug.
When updating documentation, examples, or config-related code:
1) Follow the source of truth for generated artifacts
2) Use the supported frontmatter format for diagram configuration
--- block) to set config/theme.%%{init: ...}%% in tests/examples.Example (frontmatter-style):
---
title: Timeline example
theme: forest
config:
logLevel: debug
---
timeline
title Timeline Title
3) Prefer storing diagram sources in .mmd (or Markdown) for better developer ergonomics
index.ts for metadata, and put each diagram in a corresponding *.mmd file for IDE syntax highlighting/plugins.4) Avoid brittle Markdown “massaging”
dedent() instead of regex-based whitespace stripping (to prevent breaking lists and indented code blocks).Require API types and public interfaces to express clear, enforceable contracts: guarantee invariants, normalize variant shapes, and make compatibility choices explicit.
Why: Clear types prevent subtle bugs, make callers’ expectations explicit, and make evolving an API safer (clients can rely on invariants or intentionally opt into legacy shapes).
How to apply (practical rules):
Prefer precise return types that guarantee required fields instead of vague or permissive types. If a function promises to return a node with a specific model FQN, express that in the signature.
Example:
function findNodeByModelFqn
When two fields are conceptually paired, represent them as a single array of paired objects so their relationship and lengths are guaranteed: // instead of separate includePaths?: URI[] and includePathsAsStrings?: ProjectFolder[] includePaths?: Array<{ uri: URI, folder: ProjectFolder }>
Normalize variant/union shapes using discriminants and common base types; provide parsing/mapping helpers that convert legacy or multiple AST/kinds into a single canonical representation. When you must keep legacy shapes, add an explicit flag or an optional legacy field rather than implicit differences: type DynamicBranchCollectionBase = { branchId: string; astPath: string; kind: ‘parallel’ | ‘alternate’; paths: DynamicBranchPath[] } interface DynamicParallelBranch extends DynamicBranchCollectionBase { kind: ‘parallel’; isLegacyParallel?: boolean }
Use small helpers to map input kinds to the normalized model: function getBranchKind(astKind: string): ‘parallel’ | ‘alternate’ { return astKind === ‘alternate’ || astKind === ‘alt’ ? ‘alternate’ : ‘parallel’ }
Be explicit about semantic decisions that affect consumers (e.g., whether nested parallels are allowed or should be flattened). Either enforce the rule in the parser/validator or document/parameterize the behavior so callers/layout code can handle it deterministically.
Checklist for PR authors:
Applying these rules will make API boundaries explicit, reduce accidental breakage, and make evolution more controlled and predictable.
When changing or adding code prefer existing helpers, language-idiomatic constructs, and small well-maintained libraries to keep code DRY, readable, and consistent.
Why: Reusing helpers reduces duplication and bugs; using idiomatic patterns (entries, map, pipe) removes boilerplate and conditional checks; consistent literal formats improve readability; standard libraries avoid ad-hoc implementations for common tasks (e.g., color scales).
How to apply (checklist):
for...in plus manual checks
for (const [id, styles] of entries(parsedGlobalRules.styles)) { /* … */ }
// or
globalRules.styles = pipe(
entries(parsedGlobalRules.styles),
map(([id, style]) => ({ id, style })),
indexBy(prop(‘id’))
)Guidance for code reviews:
References: discussions 0, 1, 2, 3.
Write tests that are both type-safe and narrowly focused on supported behavior. Use small, typed test helpers or fixtures to eliminate repeated casts and noisy “as any”/”as T” in tests, and ensure test cases reflect the product’s validation rules (don’t test unsupported scenarios).
Why: Cleaner, safer tests are easier to read and maintain; helpers reduce boilerplate and prevent hiding type problems with casts. Keeping tests aligned with validation prevents brittle or misleading coverage.
How to apply:
Example helper (from discussion):
function testFindNodeByElementFqn(
nodes: Array<{ id: string; data: { modelFqn?: string | null } }>,
modelFqn: string
) {
return findNodeByElementFqn(nodes as any, modelFqn as any)
}
Use it to remove casts in many tests and keep the test intent clear.
Example simplified rank test (only supported sibling case):
it('parses element view rank rules for siblings', async ({ expect }) => {
const { parse, services } = createTestServices()
const langiumDocument = await parse(`
specification { element block }
model {
block root {
block childA {}
block childB {}
}
}
views {
view index {
include *
{rank=same; root childA childB}
}
}
`)
const doc = services.likec4.ModelParser.parse(langiumDocument)
const ranks = doc.c4Views[0]!.rules.filter(rule => 'rank' in rule)
expect(ranks).toHaveLength(1)
})
Checklist for PRs/tests:
When handling failures, classify them as recoverable vs unrecoverable, then apply a consistent rule: log with enough context, continue only for recoverable side-effects, and fail fast with explicit (prefer custom) errors for invalid/unknown inputs or internal invariants.
Apply it like this:
Example pattern (recoverable side-effect):
try {
registerDiagramIconPacks(config.icons);
} catch (error) {
log.error(
'Failed to register icon packs, continuing with diagram render:',
error,
);
// continue rendering
}
Example pattern (unrecoverable invalid input):
class InvalidStyleError extends Error {
constructor(message: string) {
super(message);
this.name = 'InvalidStyleError';
}
}
function parseRadius(value: string): number {
if (!/^\d+$/.test(value)) {
throw new InvalidStyleError(`radius value '${value}' must be a number`);
}
return parseInt(value, 10);
}
Example pattern (consistent propagation with suppression):
try {
await diag.renderer.draw(text, id, version, diag);
} catch (e) {
if (config.suppressErrorRendering) {
removeTempElements();
} else {
errorRenderer.draw(text, id, version);
}
throw e;
}
Maintain clean and well-documented CI configurations by removing dead code and properly documenting temporary changes. Avoid leaving commented-out code in CI files - either remove unused configurations entirely or add proper TODO comments with context when temporarily disabling features.
When removing unused configurations, delete them completely rather than commenting them out. For temporary disabling due to issues, add TODO comments with explanations and follow-up plans.
Example:
# Good - Clean removal
node_version:
- 20
- 22
- 24
# Good - Temporary disable with context
# TODO(v23): remove node 20 - EOL April 2026
# TODO: Re-enable Windows builds after fixing Gradle issue (assigned to @xiongemi)
# - os: windows-latest
# node_version: 22
# Bad - Unexplained commented code
# - 23
This practice keeps CI configurations maintainable, reduces confusion for team members, and ensures temporary changes don’t become permanent oversights.
Components should not make external API calls for data that can be pre-generated at build time. Instead of fetching dynamic data during component rendering, inject pre-computed values as props to improve performance and reduce external dependencies.
When you have data that changes infrequently (like GitHub star counts, version numbers, or configuration data), fetch it during the build process and pass it into components rather than making runtime API calls.
Example of what to avoid:
// ❌ Don't do this - runtime API call in component
useEffect(() => {
const getStarCount = async () => {
const response = await fetch('https://api.github.com/repos/nrwl/nx');
const data = await response.json();
setStarCount(data.stargazers_count);
};
getStarCount();
}, []);
Example of preferred approach:
// ✅ Do this - pass pre-generated data as props
interface HeaderProps {
starCount: number; // Fetched at build time
}
export function Header({ starCount }: HeaderProps) {
return <span>{formatStarCount(starCount)}</span>;
}
This approach reduces client-side API calls, improves initial page load performance, and makes components more predictable and testable.
Always validate configuration values at runtime and provide clear, actionable error messages when invalid combinations are detected. This prevents runtime failures and guides users toward correct configuration.
Key validation practices:
Example from environment variable validation:
if (
!args.outputStyle &&
process.env.NX_DEFAULT_OUTPUT_STYLE &&
choices.includes(process.env.NX_DEFAULT_OUTPUT_STYLE as OutputStyle)
) {
args.outputStyle = process.env.NX_DEFAULT_OUTPUT_STYLE;
}
Example from configuration combination validation:
if (usesVersionPlaceholder && hasSkipVersionActions) {
throw new Error(
`Release group "${groupName}" configures "skipVersionActions" but its docker version scheme contains the "{versionActionsVersion}" placeholder which cannot be resolved without version actions. Remove "skipVersionActions" or remove the placeholder from the scheme.`
);
}
This approach catches configuration errors early, provides clear guidance for resolution, and prevents confusing runtime failures that are difficult to debug.
When updating diagram parsers (Jison/Langium/Chevrotain), treat lexer/tokenization precedence as a compatibility contract: ensure changes don’t break existing inputs and that intended tokens are unambiguously chosen.
Apply these rules:
1) Assume the first/earliest matching token wins (Langium/Chevrotain behavior). Avoid overlapping regex/patterns that allow one token to “shadow” others. If overlap is unavoidable, control it explicitly (tighten patterns, reorder tokens, or use a custom matcher that refuses matches that should belong to other token types).
2) Never change the meaning of a previously-supported character/string without explicitly preserving the old interpretation (or providing a migration plan). If a symbol like - previously parsed as a generic/node string, keep that option working while adding the new operator token.
3) If you remove/replace lexer terminals to resolve conflicts, confirm that downstream validation preserves the same semantics the feature provided (don’t silently drop behavior).
4) Add regression tests for prior real-world diagrams/labels that previously worked—especially cases involving punctuation, quotes, and ambiguous terminals.
Example (conceptual fix for “shadowing”):
In code review, ask: “What token now matches this substring, and does that substring still parse the same way as before? Which token wins, and why?”
Documentation should prioritize user needs and experience over technical convenience. This means using appropriate link types (guides over API docs for user-facing content), organizing content to avoid overwhelming newcomers, providing necessary context, and ensuring links work correctly with tooling.
Key practices:
/docs/technologies/testingtools/vitest/guides/migrating-from-nx-vite instead of API docsExample of user-centric approach:
<!-- Instead of leading with technical details -->
# Build Your Own Nx Plugin: Integrating Biome in 20 Minutes
<!-- Lead with user benefits -->
# Using Biome with Nx: Fast Linting and Formatting
Learn how to integrate Biome for faster linting. You don't need a plugin to get started, but creating one will make your workflow smoother.
This approach ensures documentation serves users effectively rather than just being technically accurate.
Ensure all runtime and project configuration is explicit, type-safe, and machine-independent.
Motivation
Rules (actionable)
const preferredPort = env.PORT ? parseInt(env.PORT, 10) : 5173
export const LikeC4ProjectJsonConfigSchema = z.object({ // … experimental: LikeC4ExperimentalSchema.optional() })
import Icon from './path/to/icon.svg?inline' or /@fs/path/to/icon.svg?inline after computing correct project-relative path.Checks to run
Why this helps
Centralize OS-specific configuration and modifier mappings in a dedicated config/adapter module and document global declaration files. Motivation: key modifiers (Cmd/Meta/Alt/Option), global shortcuts, and shared types behave differently across platforms; putting the logic in one place avoids inconsistent handling, duplicate OS checks, and brittle startup code.
Rules and how to apply:
Code examples (patterns to follow):
Platform mapping helper (conceptual) const isMac = process.platform === “darwin”; export function mapLogicalModifier(mod: ‘Cmd’ | ‘Meta’ | ‘Option’) { if (mod === ‘Cmd’) return isMac ? ‘Meta’ : ‘Alt’; if (mod === ‘Option’) return isMac ? ‘Alt’ : ‘Alt’; return ‘Meta’; // fallback }
Use mapping in prettyPrintKeybind: function prettyPrintKeybind(keyDescription: string): string { const keyPress = parseKeyDescription(keyDescription); const mappedMods = { Cmd: mapLogicalModifier(‘Cmd’), Option: mapLogicalModifier(‘Option’), // respect explicit Meta/Alt in keyPress.mods if present }; // build display string using mappedMods and platform symbols }
OS-aware global shortcut registration: if (isMac) { reregisterGlobalShortcut(‘Cmd+F4’); } else if (process.platform === ‘linux’ || process.platform === ‘win32’) { reregisterGlobalShortcut(‘Alt+F4’); }
Practical checklist for PRs:
This ensures consistent cross-platform behavior, easier testing and maintenance, and a single place to update OS-specific settings.
Ensure that version declarations in configuration files accurately reflect the versions actually being used in runtime environments. Configuration drift occurs when declared versions diverge from deployed versions, leading to inconsistent environments and potential deployment issues.
When updating configuration files, verify that the specified versions match what’s currently deployed or intended for deployment. Avoid situations where configuration declares one version while the system runs another.
Example from mise.toml:
# Bad: Config says node 24, but runtime uses 20.19
node = "24" # Actually running 20.19
# Good: Config matches runtime
node = "20.19" # Matches actual deployed version
Before committing configuration changes, validate that:
When designing concurrent systems, ensure data ownership is explicit and clear at thread boundaries. Avoid passing references across threads or using indirect access patterns that obscure ownership responsibilities.
In multithreaded code, data must be owned by the thread that uses it, not borrowed from another thread. This prevents race conditions and makes the code’s concurrency model explicit.
Example of problematic pattern:
// BAD: Trying to pass &mut self to a thread
fn start_collection(&mut self) -> Result<(), Error> {
std::thread::spawn(|| {
self.collection_loop(); // Error: can't pass references across threads
});
}
Example of correct pattern:
// GOOD: Clone Arc references for thread ownership
fn start_collection(&mut self) -> Result<(), Error> {
let should_collect = Arc::clone(&self.should_collect);
let system = Arc::clone(&self.system);
std::thread::spawn(move || {
Self::collection_loop(should_collect, system); // Owned data
});
}
Additionally, avoid indirect data access that obscures ownership. Instead of retrieving data through unrelated objects, pass required data directly to maintain clear responsibility chains and prevent confusion about data sources in concurrent contexts.
Configuration changes and examples should be documented with clear formatting, proper context, and helpful references to aid developer understanding.
When documenting configuration changes:
Example of clear configuration documentation:
// nx.json
{
"plugins": [
{
"plugin": "@nx/dotnet",
"options": {
- "inferredTargets": {
- "build": "build",
- "test": {
- "targetName": "test:dotnet",
- "cache": false
- }
- }
+ "build": {
+ "targetName": "build"
+ },
+ "test": {
+ "targetName": "test:dotnet"
+ }
}
}
]
}
This approach helps developers quickly understand what configuration files are being modified, what specific changes are needed, and where to find additional information about configuration options.
Ensure documentation uses consistent structural elements and proper metadata to optimize user experience and content discoverability. Use platform-native components (like aside instead of callout for Astro docs), include appropriate sidebar labels, and leverage weight/filter properties to control search result prominence.
Key practices:
Example frontmatter:
---
title: 'affected:graph - CLI command'
sidebar:
label: Introduction
weight: .1
filter: "type:References"
---
This approach prevents deprecated or less relevant content from dominating search results while ensuring users can navigate documentation intuitively.
Before implementing new functionality, check if similar utilities or patterns already exist in the codebase. Reuse existing code rather than duplicating logic, and organize shared types and constants in centralized locations to prevent circular dependencies and maintain consistency.
Key practices:
isPrerelease utility in packages/nx/src/command-line/release/utils/shared.ts, let’s not duplicate the logic”)Example of good practice:
// Instead of creating multiple similar selectors
export function getMigrationType(ctx: AutomaticMigrationState, migrationId: string) {
return ctx.nxConsoleMetadata?.completedMigrations?.[migrationId]?.type;
}
// Then use it in components with comparison
const isSuccessful = getMigrationType(ctx, id) === 'successful';
const isFailed = getMigrationType(ctx, id) === 'failed';
This approach reduces code duplication, improves maintainability, and ensures consistent behavior across the codebase.
Variable and parameter names should be explicit about their purpose and consistent with established naming patterns in the codebase. Avoid ambiguous or generic names that could be confusing in context.
Make names explicit and descriptive:
versionActionsVersion instead of version when the context involves multiple version conceptstasksExecutionId or executionId instead of generic taskId when referring to execution identifiersgetAtomizedTaskEnvVars instead of getOutputEnvVars when the function has a specific scopeFollow established naming conventions:
releaseTagPatternStrictPreId not releaseTagPatternStrictPreid)is_golden not isGolden when other properties use underscores)Example:
// Avoid: Generic and potentially confusing
const taskId = hashArray([...process.argv, Date.now().toString()]);
const version = getVersion();
// Prefer: Explicit and descriptive
const tasksExecutionId = hashArray([...process.argv, Date.now().toString()]);
const versionActionsVersion = getVersionActionsVersion();
Prefer modern JavaScript nullish coalescing (??) and optional chaining (?.) operators over verbose conditional logic for handling null and undefined values. These operators provide cleaner, more readable code while maintaining null safety.
Use nullish coalescing to provide fallback values:
// Instead of complex conditional logic
let newVersion: string;
if (targetVersionData.newVersion === null) {
newVersion = this.releaseGraph.cachedCurrentVersions.get(dep.target) || currentDependencyVersion;
} else {
newVersion = targetVersionData.newVersion || currentDependencyVersion;
}
// Use nullish coalescing
const newVersion =
targetVersionData.newVersion ??
this.releaseGraph.cachedCurrentVersions.get(dep.target) ??
currentDependencyVersion;
Use optional chaining for safe property access:
// Safe property access
projectVersionData?.newVersion
// Ensure operators stay together (not split across lines)
delete rootVersionWithoutGlobalOptions.generatorOptions?.someProperty;
Add defensive checks even when values “shouldn’t” be null, and verify types before operations when parameters can be multiple types:
// Protect against unexpected nulls
const preId = prerelease(version)?.[0];
if (typeof preId === 'string') {
return preId;
}
// Type check before processing
function concurrency(str: string | number) {
const parallel = typeof str === 'number' ? str : parseInt(str);
}
Ensure components explicitly initialize reactive state, manage input/keybinding lifecycle, and decide whether children should subscribe to live atoms or use a stable snapshot.
Why: Discussions repeatedly show bugs from missing MobX setup, duplicated or double-registered keybindings, accidental live updates that change UI unexpectedly, and inconsistent key handling logic. This guideline makes component behavior predictable and prevents leaks, duplicate handlers, and surprising re-renders.
How to apply (practical checklist):
Initialize MobX observables in class components. In the constructor call mobx.makeObservable(this, { /* annotations */ }). Example: constructor(props) { super(props); mobx.makeObservable(this, { someState: mobx.observable, someAction: mobx.action }); }
Guard per-instance keybinding registration and always clean up. Use a per-instance domain name and a boolean observable to avoid double registration. Unregister the domain on unmount. Example pattern: keybindsRegistered = mobx.observable.box(false);
componentDidMount() {
if (!this.keybindsRegistered.get()) {
mobx.action(() => this.keybindsRegistered.set(true))();
const domain = datepicker-${this.uuid}-${part};
GlobalModel.keybindManager.registerKeybinding(“control”, domain, “generic:selectLeft”, () => { /…/; return true; });
// register other keys
}
}
componentWillUnmount() {
GlobalModel.keybindManager.unregisterDomain(datepicker-${this.uuid});
mobx.action(() => this.keybindsRegistered.set(false))();
}
Use centralized key-check utilities for consistent cross-platform modifier handling instead of ad-hoc e.code and getModifierState checks. Example: if (GlobalModel.checkKeyPressed(e, GlobalModel.KeyPressModifierControl + “:g”)) { /* … */ }
When using props with reactive frameworks (Preact/MobX quirks), if direct access triggers warnings, copy props into component fields/observables in the constructor to stabilize access. Example: this.props_ = props; // or makeObservable-backed copy if needed
Prefer reuse of components/resources (keybinding modules, shared UI pieces) rather than duplicating logic across similar views. Extract shared keybinding registration or UI into a reusable component or hook.
Benefits: predictable lifecycle, fewer memory leaks or double-registrations, clearer intent about subscription semantics, consistent key handling, and easier reuse of UI and logic across components.
Ensure API documentation examples use types, interfaces, and imports that actually exist in the documented versions. Verify that code examples can be successfully imported and executed before publishing documentation.
When documenting API lifecycle information (deprecation timelines, future removals), validate these claims with maintainers rather than making assumptions. Avoid stating definitive future plans unless they are confirmed by the development team.
Example of problematic documentation:
// Bad: Importing a type that doesn't exist in @nx/devkit@22+
import {
CreateNodes, // This type was removed!
CreateNodesV2,
} from '@nx/devkit';
Example of corrected documentation:
// Good: Only import types that exist in the target version
import {
CreateNodesV2,
CreateNodesContextV2,
} from '@nx/devkit';
Before documenting deprecation timelines, confirm with maintainers:
This prevents developers from following outdated or incorrect API guidance and ensures documentation remains a reliable reference.
Use distinct variable names that reflect their types to avoid confusion and make code intent clearer. Avoid reusing the same variable name for different types within the same scope or related functions.
This prevents confusion when tracking values as they pass through functions and makes the code more maintainable. When variables of different types serve similar purposes, use descriptive suffixes or prefixes that indicate the type.
Example from the codebase:
// Bad: Same name for different types
let executable: bool = file.is_executable();
let executable: FileExecutableFlag = FileExecutableFlag::from(executable);
// Good: Type-specific names
let executable: bool = file.is_executable();
let exec_bit: ExecBit = ExecBit::from(executable);
Other examples:
handle instead of val for same_file::Handle objectsremote_branch instead of ambiguous origin for branch parametersremote_url and push_url when both are URLs but serve different purposesThis practice is especially important in functions that transform data between types or when working with similar concepts at different abstraction levels.
When working with optional values, prefer safe extraction methods that provide defaults rather than methods that can panic. Use unwrap_or(), unwrap_or_default(), or unwrap_or_else() instead of unwrap() to handle None cases gracefully.
This pattern prevents runtime panics and makes code more robust by explicitly handling the absence of values. It’s particularly important when dealing with configuration values, map lookups, or any operation that might not return a result.
Examples of good patterns:
// Instead of potentially panicking
let executable = file.executable.unwrap();
// Use safe defaults
let executable = file.executable.unwrap_or(false);
// For common defaults
let config = maybe_read_to_string(&path)?.unwrap_or_default();
// For map lookups
let parent = old_to_new.get(p.id()).unwrap_or(&p);
This approach makes the code’s behavior predictable and prevents unexpected crashes when optional values are absent, while clearly documenting the intended fallback behavior.
Always handle nullable values explicitly and defensively to prevent runtime null/undefined errors and to make intent clear.
Why: Nulls and undefined values cause intermittent runtime exceptions and unclear state transitions. Being explicit—both when clearing values and when checking inputs—reduces bugs and documents intent.
Rules to follow:
Examples (based on discussion snippets): 1) Defensive parsing and explicit null to clear state
try { const decodedCmd = atob(cmd.data.cmd64); rtInfo[“shell:lastcmd”] = decodedCmd; } catch (e) { console.error(“Error decoding cmd64:”, e); // null used intentionally to clear the key rtInfo[“shell:lastcmd”] = null; }
2) Combine guards and use optional chaining for nullable collections
if (ww?.workspaceId === workspaceId) { if (workspaceList?.length > 1) { // switch workspace } else { // delete workspace } }
Apply these consistently: prefer explicit null to indicate cleared/absent values, guard all external inputs and collections with optional chaining or null checks, and structure conditionals to make null-handling intent obvious.
Any diagram text/config that can originate from users (node labels, tooltips, markdown, theme/style tokens, and link targets) must be treated as untrusted. Apply context-appropriate escaping/sanitization and avoid security-by-regex.
Practical rules:
.html(...), sanitize the string (e.g., DOMPurify/rehype-sanitize) and/or ensure all metacharacters are escaped. If you only need plain text, prefer .text(...).url(...) in SVG/CSS, use CSS.escape() (or equivalent) instead of manual replace chains.javascript: in any “click”/link rendering path. Add tests that ensure unsafe schemes are rejected/neutralized.Example patterns:
tooltipEl.text(userProvidedTitle); // avoid .html for untrusted strings
const safeToken = CSS.escape(untrustedToken);
const css = `url(${safeToken})`;
function isValidHexColor(s: string) {
return /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.test(s);
}
if (theme.primaryColor && !isValidHexColor(theme.primaryColor)) throw new Error('Invalid color');
Configuration files should maintain consistency in patterns, use correct paths and values, and follow established conventions across the codebase. This includes proper output paths, consistent dependency versioning patterns, and appropriate dependency categorization.
Key areas to verify:
dist/lib instead of {projectRoot}/src/lib)^ for similar packages, apply it consistently)dependencies vs devDependencies)Example from package.json:
{
"dependencies": {
"@module-federation/enhanced": "^0.17.0", // Keep caret for consistency
"@module-federation/sdk": "^0.17.0"
},
"devDependencies": {
"@nx/cypress": "workspace:*" // Move dev-only deps here
}
}
Design command-line interfaces with consistent flag semantics and leverage framework features for validation. Avoid ambiguous syntax that can be interpreted multiple ways, use explicit conflict declarations instead of manual validation, and ensure flag combinations have clear, predictable behavior.
Key principles:
conflicts_with instead of manual validation: #[arg(long, conflicts_with = "other_flag")]command: String, args: Vec<String> over command: Vec<String>Example of good flag design:
#[derive(clap::Args)]
struct Args {
#[arg(long, conflicts_with = "push")]
fetch: bool,
#[arg(long, conflicts_with = "fetch")]
push: bool,
// Clear semantics: when neither specified, both are true
// When one specified, only that one is true
}
This ensures users can predict behavior and reduces maintenance burden by leveraging framework validation.
Select data structures and algorithms based on their performance characteristics and expected usage patterns. Consider the size of collections, access patterns, and computational complexity when making implementation choices.
Key considerations:
HashSet instead of Vec for membership testing when collections can be largeIndexMap vs HashMap)Example:
// Instead of Vec for large collections with frequent lookups
let already_tracked_bookmarks: Vec<String> = ...;
if already_tracked_bookmarks.contains(&bookmark) { ... } // O(n) lookup
// Use HashSet for O(1) average lookup time
let already_tracked_bookmarks: HashSet<String> = ...;
if already_tracked_bookmarks.contains(&bookmark) { ... } // O(1) lookup
This applies especially when dealing with user-facing operations that may scale with repository size or when processing large collections where the choice of data structure significantly impacts performance.
Write documentation that prioritizes user understanding over technical precision. Avoid unclear phrases, overly technical explanations, and unhelpful references. When in doubt, choose clarity over brevity, especially for user-facing documentation that may be someone’s first encounter with a feature.
Key principles:
Example of improvement:
// Before: Technical and unclear
/// Template which, upon being forced (`extract()`ed), will evaluate its
/// condition and select between a template for the true case and a template
/// for the false case (which will yield nothing if it is [`None`]).
// After: Clear and user-focused
/// Template which selects output based on a boolean condition.
This approach ensures documentation serves its primary purpose: helping users understand and effectively use the code.
Configuration logic should adapt based on environmental context rather than using static values. Examine the current environment state (file system, process hierarchy, feature flags) and adjust configuration accordingly to ensure optimal behavior in different scenarios.
When implementing configuration logic, consider:
Example from file walker configuration:
walker.git_ignore(use_ignores);
if use_ignores {
// disable the parent gitignore if the directory is a git repo, otherwise use the parent gitignore
walker.parents(!directory.join(".git").exists());
walker.add_custom_ignore_filename(".nxignore");
}
This approach ensures that configuration decisions are made based on actual environmental state rather than assuming a one-size-fits-all approach. For instance, when NX_ISOLATE_PLUGINS=true NX_DAEMON=false, the system adapts its process architecture accordingly, with the main process managing plugin workers as child processes.
Configure CI pipelines to use appropriately scoped access tokens based on branch protection status. Use read-write tokens only for protected branches (branches that don’t allow direct push) and read-only tokens for all other branches and environments.
Read-write tokens allow full cache access but should be restricted to trusted environments to prevent cache poisoning. Read-only tokens allow reading from the shared primary cache and writing to branch-specific isolated caches, providing cache benefits while maintaining security.
Additionally, ensure CI commands are non-interactive by using appropriate flags like --yes to prevent pipelines from hanging on user prompts.
# GitHub Actions example
jobs:
main:
runs-on: ubuntu-latest
steps:
- run: npx nx affected -t build,lint,test
- run: npx nx release --yes # Prevent prompts in CI
env:
# Use read-write token for protected branches only
NX_CLOUD_ACCESS_TOKEN: ${{ github.ref == 'refs/heads/main' && secrets.NX_CLOUD_ACCESS_TOKEN_RW || secrets.NX_CLOUD_ACCESS_TOKEN_RO }}
This approach prevents unauthorized cache modifications while maintaining the performance benefits of remote caching across all CI runs.
Maintain consistent naming and terminology throughout code and documentation. This includes proper capitalization of product names, technical terms, and consistent use of domain-specific vocabulary.
Key guidelines:
jj revert, use jj op revert for consistencyExample corrections:
# Before
### Commit Evolution (Change-IDs and Changes)
amend or rewrite your commits
change id
# After
### Commit evolution (change IDs and changes)
update your revisions
change ID
This ensures users can easily understand and predict naming patterns, reducing cognitive load and improving overall code/documentation quality.
Always define technical terms and concepts explicitly in documentation rather than assuming reader knowledge. Avoid ambiguous phrasing that could be interpreted multiple ways.
When introducing technical terms:
Examples of good practice:
# Good: Clear definition
* `.trailers() -> List<Trailer>`: The trailers at the end of the commit
description that are formatted as `<key>: <value>`.
# Bad: Ambiguous phrasing
* `.trailers() -> List<Trailer>`: The trailers at the end of the commit
description, formatted as `<key>: <value>`.
# Good: Precise terminology
* `.synced() -> Boolean`: For a local bookmark, true if synced with all tracked remotes.
# Bad: Imprecise terminology
* `.synced() -> Boolean`: For a local bookmark, true if synced with all remotes.
This prevents confusion, reduces the need for readers to maintain external references, and ensures documentation is self-sufficient. Pay special attention to terms that may have different meanings in different contexts or tools.
When implementing network operations that fetch data from remote sources, configure specific refspecs or patterns to fetch only the required data rather than everything available. This reduces network bandwidth usage, improves performance, and ensures future operations remain efficient.
For Git remote operations, specify target branches/bookmarks explicitly:
// Instead of fetching everything
expand_fetch_refspecs(remote_name, vec![StringPattern::everything()])
// Fetch only specified branches
expand_fetch_refspecs(
remote_name,
target_branches
.unwrap_or(&[StringPattern::everything()])
.to_vec(),
)
Configure remotes with specific refspecs so that future fetch operations automatically use the same selective patterns. This prevents unnecessary network traffic and keeps the local repository focused on relevant data.
The same principle applies to other network operations: be explicit about what data you need rather than fetching everything available, and persist these preferences for consistency across operations.
Remove unnecessary code, operations, and annotations that don’t add value. This includes redundant type annotations when types are already constrained, unnecessary conditional checks, redundant operations like path normalization in multiple places, and overly complex patterns that can be simplified.
Examples of improvements:
let out_property: BoxedTemplateProperty<'a, bool> = → let out_property = when the type is already constrained by the function signatureif created_dirs.write().await.insert(dir_path.clone()) { → just use created_dirs.write().await.insert(dir_path.clone()); when the condition isn’t neededmatch expression.evaluate(repo) { Ok(_) => Ok(()), Err(e) => Err(e) } → expression.evaluate(repo).map(|_| ())let mut hint = ui.hint_default(); writeln!(hint, "...")?;, directly use writeln!(ui.hint_default(), "...")?;Focus on the principle that code should be as simple and direct as possible while maintaining clarity and correctness.
Use descriptive, unambiguous names for configuration files to clearly indicate their scope and prevent user confusion about configuration hierarchy.
When introducing new configuration files, especially in systems with multiple configuration layers (user, repo, workspace), choose names that explicitly indicate the scope rather than generic names that could be mistaken for broader configuration files.
For example, prefer .jj/workspace-config.toml over .jj/config.toml when the configuration is workspace-specific, as users might assume .jj/config.toml is the primary repository configuration file and overlook .jj/repo/config.toml.
// Good: Clear scope indication
let workspace_config_path = workspace_root.join(".jj").join("workspace-config.toml");
let repo_config_path = repo_root.join(".jj").join("repo").join("config.toml");
// Avoid: Ambiguous naming that could confuse users
let config_path = workspace_root.join(".jj").join("config.toml"); // Could be mistaken for main config
Consider the user’s mental model when navigating configuration files. If multiple configuration files exist in the same conceptual space, their names should make the hierarchy and precedence clear at first glance. This reduces support burden and prevents configuration mistakes.
Implement algorithms that handle edge cases and avoid brittle assumptions about input data or structure formats. Instead of relying on simple string manipulation or assuming data structure behavior, use comprehensive approaches that account for various scenarios.
For parsing operations, handle multiple input formats:
// Brittle approach
const target = task.target.target.split('--')[0];
const lines = content.split('\n');
// Robust approach
const target = getTargetFromMetadata(task, projectGraph);
const lines = content.split(/\r\n|\r|\n/);
For data structure access, verify assumptions and implement proper traversal:
// Assumption-based approach
const children = reflection.children;
// Verified approach
const childReflections = reflections.filter(
(r) => r.parent && r.parent.id === reflection.id
);
This approach prevents bugs caused by incomplete parsing, platform differences, or incorrect assumptions about data structure behavior, leading to more reliable and maintainable code.
Configuration values should be externalized from code and read from standard locations like package.json or environment variables. Implement environment-aware validation that fails fast in production when required configuration is missing, while providing sensible defaults for development environments.
For environment variables, validate required values at application startup:
if (!process.env.NEXT_PUBLIC_ASTRO_URL) {
// If we're building for production throw error as each env must set this value.
if (process.env.NODE_ENV === 'production') {
throw new Error(
`The NEXT_PUBLIC_ASTRO_URL environment variable is not set. Please set it to the URL of the Astro site.`
);
}
// For dev, default to the canary docs.
else {
process.env.NEXT_PUBLIC_ASTRO_URL = 'https://master--nx-docs.netlify.app';
}
}
For scripts, read configuration from package.json or config files rather than hardcoding values. This ensures configuration is centralized, version-controlled, and easily maintainable across different environments and deployment scenarios.
Ensure testing documentation is properly categorized and uses precise terminology to maintain clarity and accessibility. Testing concepts should be organized into appropriate sections (e.g., “Testing Tools” rather than generic categories) and described with accurate language that clearly conveys the intended meaning.
When documenting testing processes, choose precise terms that accurately describe the verification steps. For example, use “valid” instead of “correct” when referring to proposed fixes that meet acceptance criteria, as this better conveys the nature of the validation being performed.
Proper organization helps developers quickly locate relevant testing guidance, while precise terminology prevents misunderstandings about testing procedures and requirements. This approach ensures that testing documentation serves as an effective reference for development teams implementing various testing strategies.
Always use appropriate assertion methods in tests to ensure proper verification of command behavior. When you don’t need to examine command output, use .success() to verify the command completed without errors. When the output content is meaningful for testing the functionality, capture and snapshot it for verification.
Problematic approach:
// Ignoring output when we should verify success
let _output = test_env.run_jj_in(&workspace_root, ["git", "colocation", "enable"]);
// Using .success() when output should be verified
work_dir.run_jj(["metaedit", "--author-timestamp", "2001-02-03 04:05:14.000+07:00"]).success();
Better approach:
// Use .success() when only caring about command completion
test_env.run_jj_in(&workspace_root, ["git", "colocation", "enable"]).success();
// Snapshot output when it's meaningful for verification
let output = work_dir.run_jj(["metaedit", "--author-timestamp", "2001-02-03 04:05:14.000+07:00"]);
insta::assert_snapshot!(output, @"...");
This practice ensures that tests properly verify both command success and expected behavior, making test failures more informative and catching regressions in command output or error handling.
Always include file path comments in CI configuration code blocks and use officially recommended setup actions for CI tools. This improves documentation clarity and ensures reliable CI pipeline configuration.
When showing configuration examples, add file path comments to help developers understand where the code belongs:
# .github/workflows/ci.yml
name: CI
jobs:
main:
runs-on: ubuntu-latest
steps:
- run: npx nx affected -t lint test build
// module-federation.config.ts
export default {
remotes: [
['shop', 'https://shop.example.com'],
['cart', 'https://cart.example.com'],
]
}
Additionally, prefer official tool setup actions over custom alternatives. For example, continue using pnpm/action-setup@v4 for pnpm projects since that’s what the official documentation recommends, rather than implementing custom setup steps.
This approach reduces confusion about file locations, makes configurations easier to implement correctly, and ensures compatibility with tool updates and best practices.
When documenting or describing algorithmic operations, use precise, unambiguous terminology that clearly distinguishes between different types of operations. Avoid reusing terms that already have specific meanings in the domain, as this can lead to confusion about the actual algorithmic behavior.
For example, when describing set operations and graph traversals:
x..y as a “set-difference operator” when there’s already a dedicated ~ operator for set differencex..y is the set of revisions introduced from x to y” (equivalent to ::y ~ ::x)x::y, be specific about the traversal: “all commits along all direct paths from x to y”This precision is especially important when operations involve complex algorithmic concepts like graph traversals, set operations, or range queries, where subtle differences in behavior can significantly impact correctness and performance. Clear terminology helps developers understand the computational complexity and expected behavior of the operations they’re using.
When modifying test configurations or tooling settings, provide clear explanations of what the changes actually do and why specific options were chosen. Test configuration changes can be confusing without proper context.
For commit messages, explain the current behavior and what’s being changed:
# Good
nextest: mark tests that last >10s as "SLOW"
Nextest currently marks tests as SLOW if they take more than 5 seconds.
This increases the threshold to 10 seconds to reduce noise.
# Avoid
nextest: mark tests that last >10s as "SLOW"
For configuration files, consider adding comments explaining non-obvious settings:
[tasks."check:test"]
tools."cargo:cargo-nextest" = "{{vars.cargo_nextest_version}}"
# Show slow and retried tests to balance informativeness with readability
env.NEXTEST_STATUS_LEVEL="slow"
This prevents confusion about what configuration changes actually accomplish and helps future maintainers understand the reasoning behind specific test tool settings.
Choose names that clearly communicate purpose and intent without requiring additional documentation or context. Names should be self-explanatory to users who encounter them for the first time.
For commands and functions, prefer descriptive verbs that indicate the action being performed. Instead of cryptic or technical references, use names that directly describe what the operation does:
// Poor: Unclear what "touch" does
jj touch
// Better: Clear action and target
jj metaedit
jj modify
For files and assets, include context about their purpose and location:
// Poor: Generic placement
docs/favicon.png
// Better: Organized with clear purpose
docs/images/favicon.png
docs/images/jj-logo.jpg
For types and data structures, avoid introducing similar names that could cause confusion. If creating new types that serve similar purposes to existing ones, either reuse the existing type or clearly deprecate the old one to maintain consistency.
This approach reduces cognitive load for developers and users, making the codebase more maintainable and intuitive to navigate.
Ensure all identifiers, file references, and generated names follow established conventions and patterns rather than using arbitrary or hardcoded values. This includes using correct file extensions in imports, following consistent naming patterns for generated targets, and using template variables instead of hardcoded names in templates.
Key practices:
ciTargetName--merge-reports with double dashes).mts vs .mjs)Example violations and fixes:
// ❌ Wrong: Single dash instead of established double-dash pattern
e2e-ci-merge-reports
// ✅ Correct: Follow the established pattern with double dashes
e2e-ci--merge-reports
// ❌ Wrong: Hardcoded name in template
import { rule, RULE_NAME } from './my-custom-rule';
// ✅ Correct: Use template variable
import { rule, RULE_NAME } from './<%= name %>';
This ensures consistency across the codebase and prevents confusion when names don’t follow expected patterns.
When creating configuration files and build tasks, prioritize cross-platform compatibility by avoiding shell-specific syntax and considering how tools discover their configuration files across different environments.
Key considerations:
Example from mise configuration:
[tasks."check:codespell"]
description = "Check code for common misspellings"
tools.uv = "{{vars.uv_version}}"
# Good: Uses tool that auto-discovers config, works cross-platform
run = "uv run codespell"
# Avoid: Shell-specific syntax that breaks on Windows
# run = "jj file list | xargs mise run codespell"
This approach ensures your development environment works consistently for all team members regardless of their operating system, reducing setup friction and debugging time spent on platform-specific issues.
When designing APIs, prioritize simplicity and focused scope over feature completeness. Before adding new API methods or expanding existing ones, evaluate whether the functionality can be achieved with existing interfaces. APIs that spread across multiple modules or introduce complex signatures often indicate scope creep that should be avoided.
Key principles:
For example, instead of adding a new ext: fileset operator when glob:"**/*.rs" already works, consider whether the convenience justifies the additional API surface. Similarly, when an API signature becomes complex like:
pub fn search(
&self,
path: &RepoPath,
attribute_names: impl AsRef<[&str]>,
priority: SearchPriority,
) -> Result<HashMap<String, gix_attributes::State>>
Consider simpler alternatives that drop unnecessary parameters or use more focused types:
pub fn search(
&self,
path: &RepoPath,
attribute_names: &[&str]
) -> Result<...>
This approach prevents APIs from becoming unwieldy and reduces maintenance burden while keeping the codebase more approachable for contributors.
When handling errors, preserve the original error context and avoid exposing internal representations to users. Use IoResultExt::context() to attach meaningful path information to I/O errors, and maintain error source chains using .with_source() or similar mechanisms.
For user-facing error messages, avoid displaying internal data structures that users cannot understand. Instead, provide clear, actionable error descriptions.
Example of good error context preservation:
// Good: Attach path context to I/O errors
std::fs::write(&jj_gitignore_path, "/*\n")
.context(&jj_gitignore_path)?;
// Good: Preserve error source chain
TemplateParseError::expression(message, span).with_source(err)
// Bad: Expose internal representation to user
format!("The given revset '{:?}' was expected to have {} elements", set, count)
// Good: User-friendly message
format!("revset that was expected to have {} revision had {} revisions", expected, actual)
This approach ensures that developers get sufficient debugging information while users receive comprehensible error messages. The error context helps with troubleshooting without overwhelming end users with implementation details.
Decorative images, icons, and other visual elements that don’t convey meaningful content should include aria-hidden="true" to prevent screen readers from announcing them. This ensures a cleaner experience for users with assistive technologies and maintains consistent accessibility markup patterns across the codebase.
Apply this attribute to any img, svg, or icon elements that serve purely decorative purposes:
<!-- Decorative sidebar icon -->
<img
src={icon}
alt=""
aria-hidden="true"
class="sidebar-icon w-4 h-4 dark:invert"
/>
<!-- Decorative group icon -->
<img
src={icon}
alt=""
aria-hidden="true"
class="sidebar-icon w-4 h-4 dark:invert"
/>
This practice should be consistently applied to maintain clean, accessible markup throughout the application.
Optimize performance by being selective about resource consumption - process only necessary data, avoid redundant operations, and use lightweight alternatives when possible.
Key strategies:
require.resolve() over require() when you don’t need to execute the moduleExample:
// Instead of storing full external nodes data
const externalNodesData = getExternalNodesData(externalNodes);
writeToCache(externalNodesData); // Large disk usage
// Store hash instead
const externalNodesHash = hashObject(getExternalNodesData(externalNodes));
writeToCache(externalNodesHash); // Minimal disk usage
// Conditional require
function assertBuilderPackageIsInstalled(packageName: string): void {
try {
require.resolve(packageName); // Lighter than require(packageName)
} catch {
throw new Error(`Package ${packageName} not found`);
}
}
This approach can yield significant performance improvements - benchmarks show up to 6x speed improvements when reducing data before processing.
Avoid recalculating expensive operations in frequently called methods by caching results and only recalculating when necessary. This is especially important in rendering loops, event handlers, and other high-frequency code paths where the same computation may be performed repeatedly with the same inputs.
Store calculated values in instance variables or state, and invalidate the cache only when the underlying data changes. This prevents performance bottlenecks from redundant computations.
Example of the problem:
fn draw(&mut self, f: &mut Frame<'_>, area: Rect) -> Result<()> {
// Recalculates on every draw call - expensive!
let column_visibility = self.calculate_column_visibility(area.width);
// ... rest of drawing logic
}
Example of the solution:
fn draw(&mut self, f: &mut Frame<'_>, area: Rect) -> Result<()> {
// Only recalculate if width changed or cache is invalid
if self.column_visibility.is_none() || self.last_width != area.width {
self.column_visibility = Some(self.calculate_column_visibility(area.width));
self.last_width = area.width;
}
let column_visibility = self.column_visibility.as_ref().unwrap();
// ... rest of drawing logic
}
Consider caching at initialization or on state changes rather than in performance-critical loops. When facing circular dependencies in calculations, pre-reserve space or use conservative estimates to avoid expensive recalculation cycles.
When documenting or implementing features that involve multiple remote repositories, provide clear guidance on different remote configuration strategies and their appropriate use cases. This includes explaining the distinction between remotes you have write access to (typically origin) versus read-only upstream remotes, and when to track or sync different remote branches.
For example, when documenting repository setup options, include all available initialization methods:
# Option 1: Start JJ in an existing Git repo with remotes
$ jj git init --colocate
# Option 2: Clone directly from remote
$ jj git clone <remote-url>
# Option 3: Initialize new repo and add remotes
$ jj git init
$ jj git remote add origin <your-fork>
$ jj git remote add upstream <canonical-repo>
Address common workflow questions explicitly, such as whether to keep fork repositories synchronized with upstream, and explain the trade-offs of different tracking strategies. This helps developers understand the networking implications of their remote configuration choices and select the approach that best fits their collaboration model.
Always explicitly specify the configuration scope using --user or --repo flags when setting configuration values with jj config set. This prevents ambiguity about where the configuration should be stored and ensures settings are applied at the intended level.
Use --user for settings that should apply across all repositories for the current user, and --repo for settings specific to the current repository.
Example:
# Repository-specific configuration
jj config set --repo 'revset-aliases."trunk()"' main@upstream
jj config set --repo gerrit.default_for main
# User-wide configuration
jj config set --user gerrit.default_for main
jj config set --user git.push origin
Without explicit scope specification, it’s unclear whether the configuration will be stored in the user’s global config or the repository’s local config, leading to unexpected behavior and configuration management issues.
Maintain consistent formatting and style patterns across all documentation to improve readability and user experience. This includes using proper shell command notation, consistent punctuation choices, and aligned configuration examples.
For shell commands, use the $ prefix with explanatory comments:
$ jj upload # "upload" is an alias using "jj util exec"
Choose consistent punctuation throughout documentation (prefer commas over em dashes for better readability):
time, exactly how Gerrit wants you to work
Maintain consistent configuration patterns across different tools and sections:
[language-server.rust-analyzer.config.rust-analyzer.rustfmt]
extraArgs = ["+nightly"]
This approach ensures that documentation maintains a professional, cohesive appearance and reduces cognitive load for readers by establishing predictable formatting patterns.
Ensure network-related data like URLs and IP addresses are properly encoded and typed to prevent validation failures and type mismatches. When working with network protocols, use precise types that match the actual return values and apply consistent encoding across all network operations.
For IP family handling, use accurate type annotations:
// Incorrect - net.isIP returns 0 for invalid IPs
const isIP = net.isIP(host) as net.family
// Correct - includes 0 for invalid IP case
const isIP = net.isIP(host) as net.family | 0
For URL operations, ensure consistent encoding:
// Incorrect - raw path may contain unencoded characters
shouldLoad: () => document.location.pathname.includes("${file.absolute}")
// Correct - properly encode URL for comparison
shouldLoad: () => document.location.pathname.includes("${encodeURI(file.absolute)}")
This prevents runtime errors from type mismatches and ensures URL validation works correctly when paths contain special characters.
When handling errors, transform technical exceptions into user-friendly messages that include clear remediation steps and actionable guidance. Avoid exposing raw technical errors to users, and instead provide context about what went wrong and how to resolve the issue.
Rather than letting technical errors bubble up:
try {
isNpmInstalled = getPackageManagerVersion('npm', process.cwd(), true) !== '';
} catch (e) {
throw e; // Raw technical error
}
Provide controlled, user-facing error messages:
try {
isNpmInstalled = getPackageManagerVersion('npm', process.cwd(), true) !== '';
} catch (e) {
console.error(`npm was not found in the current environment. This is only supported when using \`bun\` as a package manager, but your detected package manager is "${pm}"`);
return { success: false };
}
Error messages should:
For documentation, apply strict formatting rules to both code samples and embedded assets:
mermaid-example and keep indentation consistent.--- on its own line (the first line must contain only ---).Example:
---
config:
layout: tidy-tree
---
```mermaid-example
mindmap
root((mindmap is a long thing))
A
B
C
- Image accessibility: keep `alt` text short and descriptive (avoid long sentences for banners/thumbnails).
---
## require explicit security consent
<!-- source: jj-vcs/jj | topic: Security | language: Rust | updated: 2025-09-02 -->
Always require explicit user consent and validation before executing potentially dangerous operations, especially those involving external configuration or dynamic user inputs. This prevents security vulnerabilities from being introduced through seemingly innocent features.
For external configuration (like repo-provided settings), implement a trust model that forces users to explicitly review and approve dangerous settings rather than silently executing them. As noted in the discussions: "If we do let repos set dangerous settings then we should certainly have a trust model for it."
For user inputs in templates or dynamic systems, avoid allowing arbitrary string interpolation that could lead to injection vulnerabilities. Consider restricting to literal strings or implementing strict validation, since "dealing with dynamic template strings is a known problem spot in basically every language (c.f. printf vulnerabilities in C, etc)."
Example approach for configuration:
```rust
// Bad: Silently execute repo config
load_and_execute_repo_config();
// Good: Require explicit user consent
if user_explicitly_trusts_repo_config() {
load_and_execute_repo_config();
} else {
show_diff_and_prompt_for_approval();
}
The key principle is that downloading files should never be implicit consent to execute arbitrary code, and systems should be secure by default rather than relying on users to exercise unrealistic caution.
When managing configuration via package.json/tsconfig.json, treat version and target specifiers as compatibility controls—not defaults. Choose constraints based on the dependency/toolchain’s real compatibility behavior, and wire compatibility between packages explicitly.
Apply these rules:
^; use ~x.y.z or a fixed version (and document the exception).@types/*) are fixed/unchangeable and don’t assume compatible upgrades.^ only when the dependency truly follows semver and you’re OK with patch/minor updates.~ when you only want patch updates.tsconfig module/target settings match current TypeScript semantics (e.g., prefer Node16/Node18 settings over ambiguous NodeNext if TS changed behavior).Example:
{
"dependencies": {
"langium": "1.2.0", // non-semver: pin
"chokidar": "^3.6.0", // semver: allow compatible updates
"@iconify/utils": "3.0.1" // pinned to known-good version
},
"peerDependencies": {
"mermaid": "~11.7.0" // compatible minor/patch range
}
}
And for tsconfig.json, keep module/moduleResolution consistent with the TS version you run (e.g., Node16/Node16 or Node18/Node16), rather than blindly using NodeNext.
Choose names that clearly communicate their purpose and avoid ambiguity or misinterpretation. Names should be self-documenting and consider what developers will wonder about at the call site.
Key principles:
isExecutableNonTestRule instead of isExecutableRule when the distinction matters to callersunderlying with more precise terms like hidden or server when the context is unclearUNKNOWN_CPU_TIME over generic UNKNOWN when the context mattersapplyInvalidation accurately reflect what the method does rather than how it might be interpretedExample:
// Ambiguous - what kind of rule?
public static boolean isExecutableRule(Target target)
// Clear - specifies it excludes test rules
public static boolean isExecutableNonTestRule(Target target)
// Vague constant
private static final long UNKNOWN = -1;
// Descriptive constant
private static final long UNKNOWN_CPU_TIME = -1;
This approach reduces cognitive load, prevents misunderstandings, and makes code more maintainable by ensuring names serve as clear documentation of intent.
Resist the urge to eagerly invalidate cache entries unless you have definitive proof that the cached data is invalid and cannot provide value for future operations. Cache entries can still be valuable even when their associated remote artifacts have expired or been removed.
The key principle is that cache invalidation should be conservative - err on the side of keeping potentially useful cache entries rather than aggressively removing them. Even when remote cache artifacts are no longer available, the local cache entry may still save build time for actions whose outputs are never materialized.
Consider these approaches instead of eager invalidation:
Example of conservative cache management:
if (actionCache != null && token != null) {
// Don't eagerly delete - cache entry can still save build time
// for actions whose outputs are never materialized
if (token.dirty) {
actionCache.put(token.key, token.entry);
}
}
// Only clean up definitively stale entries
actionCache.removeIf(entry ->
entry.getOutputFiles().values().stream()
.anyMatch(e -> e.getExpireAtEpochMilli() == SERVER_EXPIRATION_SENTINEL));
This approach maximizes cache hit rates while maintaining correctness, leading to better build performance overall.
Use explicit existence checks instead of truthiness checks when dealing with object properties, null/undefined values, or when falsy values are valid data.
Truthiness checks can cause bugs in several scenarios:
0, "", or false that should be processed but fail truthiness checksExamples:
// ❌ Bad: Promise objects are always truthy
if (fileProcessors[filePath]) {
return fileProcessors[filePath]
}
// ✅ Good: Check for property existence
if (filePath in fileProcessors) {
return fileProcessors[filePath]
}
// ❌ Bad: Filters out valid falsy values like "0"
return trim ? dequote(_.trim(result)) : result
// ✅ Good: Only filter out null/undefined
return trim && result != null ? dequote(_.trim(result)) : result
// ❌ Bad: Boolean true is falsy in this context check
if (keyEntry === undefined) {
// handle undefined case
}
// ✅ Good: Explicit check avoids confusion with boolean values
if (!keyEntry) {
// This would incorrectly trigger for boolean false
}
Use in operator for object property existence, != null for null/undefined checks when falsy values are valid, and be explicit about what condition you’re actually testing for.
Always validate environment variables with proper type checking, fallback values, and defensive handling to prevent runtime failures and unexpected behavior.
Environment variables can be undefined, have incorrect types, or contain invalid values. Implement defensive validation patterns that ensure your application gracefully handles these scenarios:
// Bad: Direct usage without validation
const timeout = +process.env.CYPRESS_VERIFY_TIMEOUT || 30000
const baseUrl = process.env.CYPRESS_DOWNLOAD_MIRROR
// Good: Defensive validation with proper fallbacks
const getVerifyTimeout = (): number => {
const verifyTimeout = +(process.env.CYPRESS_VERIFY_TIMEOUT || 'NaN')
if (_.isNumber(verifyTimeout) && !_.isNaN(verifyTimeout)) {
return verifyTimeout
}
return 30000
}
const getBaseUrl = (): string => {
const baseUrl = process.env.CYPRESS_DOWNLOAD_MIRROR
if (!baseUrl?.endsWith('/')) {
return baseUrl ? baseUrl + '/' : defaultBaseUrl
}
return baseUrl || defaultBaseUrl
}
// Remember: Environment variables are always strings
const forceColor = process.env.FORCE_COLOR === '0' // not === 0
Key principles:
CYPRESS_CRASH_REPORTSWhen designing/typing internal and public APIs, keep signatures tight and future-proof:
config isn’t needed, remove it from the function signature (or make it optional only where truly required).Example (extensible options object):
type ShapeOptions = {
config?: { themeVariables: unknown };
};
export const filledCircle = (
parent: SVG,
node: Node,
{ config }: ShapeOptions = {}
) => {
const themeVariables = config?.themeVariables;
// ...render using themeVariables (or a default if absent)
};
Example (prefer optional/options instead of extra required positional params):
type RenderDraw = (
text: string,
id: string,
version: string,
diagramObject: Diagram,
opts?: { error?: Error | null }
) => void;
Applying these standards reduces breaking changes, makes internal renderer/diagram code easier to evolve, and ensures public APIs behave predictably.
Write tests that verify specific behavior and outcomes rather than relying on weak assertions like snapshots or generic checks. Tests should validate the actual functionality being tested, not just capture output or run without proper verification.
Instead of snapshot tests that become non-deterministic and don’t validate real behavior:
// Avoid: Weak snapshot testing
cy.findByTestId('file-match-indicator').should('exist')
Write tests with specific, meaningful assertions:
// Prefer: Specific behavior verification
cy.findByTestId('file-match-indicator').should('contain', '2 Matches')
cy.findByRole('link', { name: 'Okay, run the spec' })
.should('have.attr', 'href', '#/specs/runner?file=src/App.cy.jsx')
When adding test coverage, ensure tests verify the expected functionality rather than just exercising code paths. Include assertions that validate the actual behavior users would experience, such as checking that clicking a component correctly finds matches or that spec generation produces the expected output files.
This approach creates more reliable, maintainable tests that catch real regressions and provide confidence in the system’s behavior.
Always review GitHub Actions workflows for security implications before merging, particularly focusing on authentication mechanisms and credential handling. Understand what permissions like id-token: write grant and their potential attack vectors. Ensure secure defaults are explicitly configured, such as disabling credential persistence.
Key security considerations:
persist-credentials: falseWhen implementing new authentication mechanisms, ensure team members understand the security model and document any special permissions required for maintainer approval.
Use specific commit hashes instead of version tags when referencing GitHub Actions in CI/CD workflows. Version tags can be moved or updated, potentially introducing security vulnerabilities or breaking changes, while commit hashes are immutable and provide reproducible builds.
Replace version tags like @v4 or @v3 with the full commit hash:
# Instead of:
- uses: actions/checkout@v4
- uses: DeterminateSystems/determinate-nix-action@v3
# Use:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- uses: DeterminateSystems/determinate-nix-action@b7303d63f88908d15f0bcb207e60b3a0ea7f1712
This practice enhances security by preventing supply chain attacks where malicious actors could update the code behind a version tag, and ensures reproducible builds by guaranteeing the exact same action code runs every time.
When implementing concurrent operations, always use appropriate synchronization mechanisms and ensure all asynchronous code paths complete properly. This includes specifying explicit timing parameters, using efficient blocking primitives, and guaranteeing promise resolution in all execution branches.
Key practices:
Example of proper synchronization:
// Bad: Missing delay parameter
setTimeout(() => {
this.sendToDaemonViaQueue(msg).then(res, rej);
});
// Good: Explicit delay with reasoning
setTimeout(() => {
// Wait 100ms for daemon to finish shutting down
this.sendToDaemonViaQueue(msg).then(res, rej);
}, 100);
// Good: Efficient blocking with Atomics.wait
while (!projectGraphCache && Date.now() - startTime < maxWaitTime) {
Atomics.wait(sharedArray, 0, 0, pollInterval);
projectGraphCache = readProjectGraphCache(minimumComputedAt);
}
// Good: Promise resolved in all paths
this.childProcess.onExit((message) => {
this.isAlive = false;
const code = messageToCode(message);
this.childProcess.cleanup();
this.exitCallbacks.forEach((cb) => cb(code));
res({ success: false, code, terminalOutput: this.terminalOutput }); // Don't forget this!
});
This prevents race conditions, ensures predictable timing behavior, and maintains proper async operation completion.
Make rendering/runtime failures observable instead of silently tolerated.
Apply two concrete rules:
1) Cover failure-prone inputs in tests: when your code parses special syntaxes (e.g., @{ ... } blocks), add variations that stress spacing/quoting/formatting so broken input is exercised.
2) Don’t swallow async dependency errors: if loading external assets/fonts fails, avoid try/catch that only logs. Either let the promise reject (so Cypress/test fails) or rethrow after adding context.
Example (preferred: errors surface and tests fail):
async function contentLoaded() {
await loadFontAwesomeCSS();
await Promise.all(Array.from(document.fonts, (font) => font.load()));
}
Example (log and propagate):
const contentLoaded = async () => {
try {
await loadFontAwesomeCSS();
await Promise.all(Array.from(document.fonts, (font) => font.load()));
} catch (err) {
console.error('Error loading fonts', err);
throw err;
}
};
Outcome: developers get a clear stack/error when something breaks, and tests/CI catch edge-case syntax issues instead of only validating the happy path.
Favor simple, readable implementations over complex or overly abstracted solutions. This includes eliminating code duplication through better function design, simplifying complex expressions, and using standard library functions instead of custom helpers.
Key practices:
paths.basename or AsciiStrToUpper) over custom helper functionsExample of simplification:
# Instead of duplicating calls:
if generate_no_pic_action:
_create_helper(..., use_pic=False)
if generate_pic_action:
_create_helper(..., use_pic=True)
# Use a loop:
use_pic_values = []
if generate_no_pic_action:
use_pic_values.append(False)
if generate_pic_action:
use_pic_values.append(True)
for use_pic in use_pic_values:
_create_helper(..., use_pic=use_pic)
This approach reduces maintenance burden, improves readability, and makes code easier to understand for future developers.
Select data structures and types that optimize for both memory usage and computational efficiency. Avoid unnecessary copies, use appropriately sized types, and consider the performance characteristics of your choices.
Key principles:
_argDescriptors lazy-initialized constants rather than mutable copies per instance)IndexType instead of size_t for color indices, char32_t instead of int for character data)std::vector<int> for numeric arrays rather than std::basic_string<int>)Example of inefficient vs efficient approach:
// Inefficient: Creates new vector every time
std::vector<ArgDescriptor> GetDescriptors() {
std::vector<ArgDescriptor> merged;
for (const auto desc : thisArgs) {
merged.push_back(desc); // Unnecessary copying
}
return merged;
}
// Efficient: Use shared immutable data
static const auto& GetDescriptors() {
static const auto descriptors = InitializeDescriptors();
return descriptors; // Return reference to shared data
}
Consider the computational complexity and memory footprint of your data structure choices, especially for frequently accessed or large-scale data.
Always validate that required features are enabled before using feature-dependent functionality. Feature flags should be the primary condition for enabling code paths, not the presence of related data or parameters.
When implementing feature-dependent behavior:
Example of proper feature validation:
# Good: Check feature first, regardless of data presence
if feature_configuration.is_enabled("cpp_modules"):
_create_cc_compile_actions_with_cpp20_module(...)
return
# Also good: Validate required features with clear error messages
def _check_cpp20_module(ctx, feature_configuration):
if len(ctx.files.module_interfaces) > 0 and not cc_common.is_enabled(
feature_configuration = feature_configuration,
feature_name = "cpp20_module",
):
fail("to use C++20 Modules, the feature cpp20_module must be enabled")
# Avoid: Making feature enablement dependent on data availability
if module_interfaces_sources and feature_configuration.is_enabled("cpp_modules"):
This approach ensures consistent behavior, prevents silent failures, and makes feature dependencies explicit and debuggable.
Use explicit null/undefined checks instead of methods that silently handle missing values. When you expect a value to be present, use access patterns that will fail fast if the value is missing rather than returning default values or silently continuing.
Prefer explicit checks that fail on missing values:
[key] instead of get(key) when the key must be present!= None instead of truthy checks when distinguishing null from empty collectionsExample from code review:
# Instead of using .get() which silently returns None:
ddi_file = source_to_ddi_file_map.get(source_artifact)
# Use direct access that fails if key is missing:
ddi_file = source_to_ddi_file_map[source_artifact]
# For collections, distinguish None from empty:
if lib.pic_objects != None: # Not just: if lib.pic_objects:
# Handle non-null collection (may be empty)
This approach makes your code more robust by catching bugs early when values are unexpectedly missing, rather than allowing silent failures that can be harder to debug later.
Always use specific, accurate terminology rather than vague or generic terms when naming sections, referencing products, or writing documentation. Ensure grammatical correctness and technical precision in all naming contexts.
When referencing specific products or technologies, use their official names rather than broad categories. For example, use “JetBrains IDEs” instead of “IDEA based editors” when referring to IntelliJ, WebStorm, and similar tools. Similarly, maintain proper article usage and grammatical structure, such as “the Angular CLI” rather than “Angular CLI” when used as a subject.
This principle applies to:
Example from documentation:
// Vague and imprecise
### VS Code / Cursor Setup
// Precise and accurate
### VS Code Setup
### Cursor / JetBrains IDEs Setup
Precise terminology reduces ambiguity, improves clarity, and demonstrates attention to detail in both code and documentation.
Implement thorough error handling that goes beyond basic logging and provides contextually accurate, actionable error messages. Error handling should include proper propagation, recovery mechanisms where appropriate, and messages that reflect the actual system state and available options.
Avoid minimal error handling that only logs errors:
// Inadequate - just logs and continues
socket.on('error', (error) => console.log('socket error from wrapper', error));
Instead, implement comprehensive error handling with context-aware messaging:
// Better - proper error handling with context
socket.on('error', (error) => {
console.error('Socket connection failed:', error.message);
process.exit(1); // or appropriate recovery mechanism
});
// Context-aware error messages
if (!(await fs.promises.stat(executable)).isFile()) {
const packageManager = detectPackageManager(); // Use actual detected manager
throw new Error(`Executable does not exist. Did you update Playwright recently? Make sure to run ${packageManager} playwright install webkit-wsl`);
}
Error messages should be accurate to the current system context and provide specific, actionable guidance rather than generic assumptions about user environment or tooling.
Avoid unnecessary reference counting operations that can impact performance, especially in frequently called code paths. Use move semantics, appropriate pointer types, and efficient parameter passing to reduce AddRef/Release churn.
Key strategies:
std::shared_ptr with raw pointers when the object lifetime is managed by a parent that outlives the consumerstd::move when assigning to members to avoid extra AddRef/Release cyclesstd::vector internally and wrap with winrt::multi_threaded_vector only when needed for WinRT interfacesExample transformations:
// Before: Unnecessary shared_ptr overhead
void Constructor(const std::shared_ptr<Cache>& cache) : _cache(cache) {}
// After: Raw pointer when lifetime is guaranteed
void Constructor(Cache* cache) : _cache(cache) {}
// Before: Extra AddRef/Release on assignment
Constructor(const IVector<T>& items) : _items(items) {}
// After: Move to avoid reference count churn
Constructor(IVector<T> items) : _items(std::move(items)) {}
This optimization is particularly important for frequently instantiated objects and hot code paths where reference counting overhead can accumulate significantly.
Prefer established, type-safe abstractions over primitive types or direct property access when designing APIs. This improves maintainability, enables future extensibility, and provides better developer experience.
Use standard library types and framework-provided abstractions instead of custom primitives:
google.protobuf.Duration instead of int64 millisecond fieldsstd::string_view instead of const char* for string parameters.pathExample improvements:
// Instead of:
static bool IsValidEnvName(const char* p) { ... }
// Use:
static bool IsValidEnvName(std::string_view name) { ... }
// Instead of:
int64 critical_path_time_in_ms = 4;
// Use:
google.protobuf.Duration critical_path_time = 4;
These abstractions often provide additional functionality (like automatic path mapping, timezone handling, or memory efficiency) and make APIs more robust and future-proof.
Log messages should be clear, informative, and include specific details to help users understand what is happening. Avoid vague messages that could cause confusion, and ensure proper stream handling to prevent garbled output in concurrent scenarios.
When logging status or waiting messages, include the specific values or URLs being referenced:
// Bad - vague and potentially confusing
console.log('Waiting for registry configuration to change from default...');
// Good - includes specific information
console.log('Waiting for registry configuration to change from https://registry.npmjs.org/...');
For concurrent processes that write to stdout/stderr, implement proper stream management to prevent output corruption:
// Use LineAwareStream or similar mechanisms to ensure complete lines
task.childProcess.stdout?.on('data', (data) => {
globalLineAwareStream.write(data, task.id);
});
This prevents garbled output when multiple processes are writing simultaneously and ensures logs remain readable and useful for debugging.
When documenting network-related features, clearly specify compatibility constraints, browser limitations, and potential side effects. This is especially critical for experimental features or those with platform-specific restrictions.
Always include:
Example:
// Good: Clear limitations and warnings
/**
* Mocking proxy is **experimental** and subject to change.
* Limitations:
* - Extra headers will affect CORS preflight requests
* - Server requests not triggered by browser won't be routed
* - Only works with persistent browser contexts
*/
export default defineConfig({
use: { mockingProxy: true }
});
This prevents user confusion, reduces support burden, and helps developers make informed decisions about feature adoption.
Ensure Python code follows proper naming conventions and syntax rules. Use snake_case for variable and parameter names instead of camelCase, and use capitalized boolean literals (True/False) instead of lowercase variants from other languages.
This addresses common issues when adapting code examples from other languages or when developers switch between different programming contexts. Both naming and boolean literal consistency are essential for Python code correctness and readability.
Example:
# Incorrect
context = await browser.new_context(
isMobile=false
)
# Correct
context = await browser.new_context(
is_mobile=False
)
When documenting changes to algorithms, data structures, or computational approaches, explicitly identify the specific components affected rather than using vague or generic descriptions. This includes naming exact data structure classes, clarifying the scope and limitations of algorithmic improvements, and using precise technical terminology.
For example, instead of writing “improve subscript narrowing for safe mutable classes”, specify the exact classes: “improve subscript narrowing for collections.ChainMap, collections.Counter, collections.deque and collections.OrderedDict”. Similarly, when describing algorithmic support, clarify what is and isn’t included - such as noting that recursive type alias support is limited to “non-generic recursive type aliases that use the type statement” rather than implying full recursive type support.
This precision helps developers understand exactly which algorithms and data structures are affected, prevents misconceptions about capabilities, and enables more targeted testing and usage of the improvements.
Ensure configuration documentation, setup instructions, and changelogs use precise, clear language with proper technical terminology. Avoid ambiguous words like “sometimes” or “generally” that create uncertainty. Use correct capitalization for technical terms (e.g., “Node.js” not “Node”, “CommonJS/ESM” not “commonjs/ESM”). Remove redundant words and fix grammatical errors that can confuse users.
Examples of improvements:
Configuration documentation should provide definitive, tested instructions rather than vague guidance, as users rely on this information to set up their development environments correctly.
Ensure API documentation, including changelogs and feature descriptions, prioritizes user understanding over implementation details. Write descriptions that explain what users can expect from the API behavior rather than how it’s technically implemented. Avoid redundant information when context is already established (e.g., don’t repeat “language server feature” under a “Server” section). Provide proper references and links to specifications or external documentation when mentioning technical concepts.
Example improvements:
Write: “Prefer the runtime definition, not the stub definition, on a go-to-definition request for a class or function”
This approach makes API documentation more accessible to users who need to understand functionality and behavior, not internal implementation choices.
When designing APIs, prioritize clarity and self-documentation over implementation convenience. Choose interface patterns that make the code’s intent immediately obvious to consumers and debuggers.
For data access APIs, prefer descriptive string-based keys over numerical indexing when the performance impact is acceptable. As noted in code review discussions: “If you were to debug it and see ‘5’ it’s not immediately clear what you want, whereas with ‘windowTitle’ you kind of know already.”
For interface definitions, avoid unnecessary annotations that add complexity without benefit. Only use attributes like [default_interface] when the runtime class has no other interface and no identifying characteristics.
Example of preferred approach:
// Instead of numerical indexing:
GetArgAt(5) // Unclear what argument this represents
// Prefer descriptive access:
GetArgByName("windowTitle") // Self-documenting intent
// Or return descriptors that include names:
auto descriptor = GetArgDescriptorAt(index); // descriptor.Name provides context
This principle applies broadly to API design: choose patterns that make debugging easier and code more self-documenting, even if they require slightly more implementation effort.
Choose efficient algorithms and data structures to improve performance and reduce computational overhead. This involves selecting appropriate containers, avoiding unnecessary operations, and leveraging language features for optimization.
Key optimization strategies:
til::static_map over std::unordered_map for compile-time initialization, or wil::to_vector for collection cloninginsert() instead of separate contains() + insert() callsstd::move when transferring ownership, especially with expensive objects like std::filesystem::pathlstrcmpiW with more efficient alternatives like ICU functions for Unicode handlingExample of inefficient vs optimized approach:
// Inefficient: separate contains + insert
if (!state->DismissedBadges->contains(badgeId)) {
state->DismissedBadges->insert(badgeId);
inserted = true;
}
// Optimized: use insert return value
auto [iter, inserted] = state->DismissedBadges->insert(badgeId);
For mathematical computations, choose appropriate distance metrics - use squared Euclidean distance r*r + g*g + b*b instead of Manhattan distance abs(r) + abs(g) + abs(b) for color comparisons to better represent perceptual differences.
Always use consistent and safe patterns when dealing with potentially null or undefined values. This includes using safe casting methods, explicit null checks, proper initialization, and immutable variables after validation.
Key practices:
try_as<T>() instead of as<T>() to avoid runtime exceptions when casting might failconst auto when storing results of null checks to prevent accidental modificationExample from the codebase:
// Inconsistent - uses try_as in one place but as in another
if (const auto newTermArgs = _ContentArgs.try_as<NewTerminalArgs>())
{
return newTermArgs->GetArgCount() + gsl::narrow<uint32_t>(_argDescriptors.size());
}
// Should also use try_as here for consistency
return _ContentArgs.as<NewTerminalArgs>()->GetArgDescriptorAt(index - additionalArgCount);
// Better approach - consistent safe casting
if (const auto newTermArgs = _ContentArgs.try_as<NewTerminalArgs>())
{
return newTermArgs->GetArgDescriptorAt(index - additionalArgCount);
}
// Proper null handling in serialization
if (json.isNull())
{
return MediaResource::FromString(L"");
}
// Proper initialization to prevent undefined behavior
UINT _systemMenuNextItemId = 0; // Instead of leaving uninitialized
This pattern prevents runtime crashes, undefined behavior, and makes code more predictable and maintainable.
Documentation should prioritize clarity and actionable guidance over comprehensive coverage. Organize content logically by placing the most relevant information first, provide clear recommendations on preferred approaches, and avoid unnecessary complexity or redundant details that don’t add value.
Key principles:
Example of good practice:
:::note
The `context.tracing` API records different information than the automatic tracing enabled through [Playwright Test configuration](https://playwright.dev/docs/api/class-testoptions#test-options-trace). For most use cases, you should use the configuration option instead as it captures both browser operations and test assertions.
:::
This approach ensures documentation serves as an effective guide rather than just a comprehensive reference, helping users make informed decisions quickly.
Choose testing methods, configurations, and approaches that prioritize user experience and reliability over theoretical completeness. Consider the practical needs of your development team and testing environment when making decisions.
Key principles:
--ui over --list for better developer experience when exploring tests.toEqual for most equality checks rather than toStrictEqual, as it provides sufficient validation without unnecessary strictness.round-robin may provide better distribution than partition depending on your test organization. For flaky test handling, consider stricter settings in CI environments.Example of contextual configuration:
// playwright.config.ts
export default defineConfig({
// Stricter flaky test handling in CI
failOnFlakyTests: !!process.env.CI,
// Better test distribution for organized test suites
shardingMode: 'round-robin'
});
This approach ensures your testing setup serves your team’s actual workflow rather than following rigid theoretical ideals.
When a graph/geometry algorithm is used recursively (or downstream computations depend on its shape/metrics), don’t patch symptoms. Preserve invariants end-to-end:
Map over plain objects for wrapper/global state (descendants/parents/cluster DB) to avoid key collisions and make updates predictable.Example (subgraph config propagation):
// In recursive render for subgraphs
const { ranksep, nodesep } = graph.graph();
node.graph.setGraph({
...node.graph.graph(),
ranksep,
nodesep,
});
Example (wrapper state as Map):
export let clusterDb = new Map();
let descendants = new Map();
let parents = new Map();
export const clear = () => {
clusterDb = new Map();
descendants = new Map();
parents = new Map();
};
Always explicitly declare security requirements and provide clear security guidance in both configuration files and user-facing content. When operations require elevated privileges, specify the security context to ensure proper UAC prompting. When features have security implications, include explanatory text to help users make informed decisions.
For configuration files requiring elevation:
- resource: Microsoft.Windows.Developer/DeveloperMode
directives:
description: Enable Developer Mode
allowPrerelease: true
securityContext: elevated # Required for UAC prompting
For user-facing security features, provide context about the security implications:
<data name="Globals_WarnAboutMultiLinePaste.HelpText" xml:space="preserve">
<value>If your shell does not support "bracketed paste" mode, we recommend setting this to "Always" for security reasons.</value>
</data>
This practice ensures that security requirements are transparent to both the system (for proper privilege handling) and users (for informed decision-making), reducing the risk of security misconfigurations or unintended security bypasses.
Organize documentation sections and content to match user mental models and workflows, not internal technical implementation details. Use descriptive, specific section names instead of generic ones like “Other changes” or overly technical terms. Present information in the order users will encounter or need it, prioritizing common use cases before advanced configuration options.
For example, when documenting configuration options, lead with default behavior that most users will experience, then explain override mechanisms:
# Good: User-centric organization
## Python environment
By default, ty searches for a `.venv` folder in the project root. If the `VIRTUAL_ENV` environment variable is set, ty will use that path instead.
The Python environment can also be explicitly specified using the `--python` flag...
# Better section naming
## Typing semantics and features
(instead of "Other changes")
## Logging options
(instead of "Initialization options" when content is logging-specific)
Consider future extensibility when naming sections - avoid overly specific names that may need renaming as features expand. Structure content to minimize cognitive load by following the user’s natural workflow and decision-making process.
Names should clearly communicate their purpose, type, and behavior to improve code maintainability and accessibility. Avoid misleading or ambiguous terminology that can confuse developers or users.
Key principles:
ProposedShortcutActionName over ProposedShortcutAction when the value is specifically a string.required for validation checks when it’s not actually a boolean requirement flag.AutomationProperties.Name with descriptive text rather than leaving buttons to be read as just “button”.ScrollToZoom instead of DisableMouseZoom to avoid double negatives and improve clarity.Example of improved naming:
// Before: misleading parameter name
#define DECLARE_ARGS(type, name, jsonKey, required, ...)
// 'required' is actually a validation expression, not a boolean
// After: clearer parameter name
#define DECLARE_ARGS(type, name, jsonKey, validation, ...)
// 'validation' clearly indicates this is a validation expression
// Before: unclear type
VIEW_MODEL_OBSERVABLE_PROPERTY(IInspectable, ProposedShortcutAction);
// After: type-indicating name
VIEW_MODEL_OBSERVABLE_PROPERTY(IInspectable, ProposedShortcutActionName);
This approach reduces cognitive load, improves accessibility, and makes code self-documenting.
Configuration documentation should be precise, specific, and include helpful context for users. Avoid vague or ambiguous language that could lead to misunderstanding of how settings behave.
Key principles:
For example, instead of writing:
Paths passed explicitly are checked even if they are otherwise ignored by an exclude or ignore file.
Write:
Paths that are passed as positional arguments to `ty check` are included even if they would otherwise be ignored through `exclude` filters or an ignore-file.
Similarly, when explaining pattern matching behavior, be explicit about anchoring:
Include patterns are anchored: The pattern `src` only includes `<project_root>/src` but not something like `<project_root>/test/src`. To include any directory named `src`, use the `**/src` prefix match.
This approach helps users understand exactly how configuration options will behave in their specific use cases and reduces confusion about expected vs. actual behavior.
Tests should be comprehensive and cover edge cases, complete scenarios, and use specific assertions rather than generic checks. When writing tests, include multiple test cases that validate different states, use precise count assertions instead of simple visibility checks, and ensure all relevant interactions are tested.
For example, instead of just checking visibility:
// Weak test
await expect(codeSnippets.first()).toBeVisible();
// Better test with specific counts
await expect(codeSnippets).toHaveCount(3);
await toggleCheckbox.click();
await expect(codeSnippets).toHaveCount(0);
When testing complex scenarios, include comprehensive cases:
// Simple test
await page.setContent(`<div inert><button>Second</button></div>`);
// More comprehensive test
await page.setContent(`
<div aria-hidden="true"><button>First</button></div>
<div inert><button>Second</button></div>
<button>Third</button> <!-- not hidden for comparison -->
`);
await expect(page.getByRole('button')).toHaveCount(1); // only Third is visible
Always test edge cases like whitespace handling, empty states, and boundary conditions. Include tests for all relevant UI interactions such as expansion/collapse, toggling, and state changes.
Choose clear, self-documenting names for variables, methods, parameters, and properties that explicitly convey their purpose and context. Avoid ambiguous or generic names that require additional context to understand.
Key principles:
_OnTabClick instead of _OnClick)SendKeyDownEvent() instead of SendKeyEvent(vkey, scanCode, flags, true))charSizeInDips vs charSizeInPixels)Example improvements:
// Instead of:
_terminal->SendKeyEvent(vkey, scanCode, flags, true);
tabViewItem.PointerReleased({ this, &TerminalPage::_OnClick });
// Use:
_terminal->SendKeyDownEvent(vkey, scanCode, flags);
tabViewItem.PointerReleased({ this, &TerminalPage::_OnTabClick });
// Instead of:
double PaddingValueFromIndex(const winrt::hstring& paddingString, uint32_t paddingIndex)
// Use:
double PaddingValueFromIndex(const winrt::hstring& paddingString, PaddingDirection direction)
This approach reduces cognitive load, makes code self-documenting, and prevents misuse of APIs by making intent explicit through naming.
Always use explicit checks for undefined values and return appropriate nullable types instead of relying on implicit conversions or unsafe type assertions. Use modern JavaScript equality checks and proper TypeScript utility types for null safety.
When a function might not have a value to return, use undefined as the return type and check explicitly:
// Good: Explicit undefined check and nullable return type
export function formatProtocolParam(params: Record<string, string> | undefined, alternatives: string): string | undefined {
if (!params)
return undefined;
if (params[name] !== undefined)
return params[name];
}
// Good: Use modern equality check
if (a.description === undefined) {
// handle undefined case
}
// Good: Use proper TypeScript utility types
type HtmlReportOpenOption = NonNullable<Options['open']>;
// Avoid: Using 'any' when 'unknown' provides better type safety
async setFileChooserInterceptedBy(enabled: boolean, by: unknown): Promise<void> {
This approach prevents null reference errors, makes code intentions explicit, and leverages TypeScript’s type system for compile-time safety rather than relying on runtime type coercion.
Add comments that explain the reasoning behind non-obvious code decisions, technical constraints, or complex logic, while avoiding over-documentation of self-evident functionality. Focus on the “why” rather than the “what” - document implementation choices that future developers (including yourself) might need to rediscover.
Examples of good rationale documentation:
Avoid over-documenting obvious boolean returns or simple getters. Instead of “// Returns: true if successful, false otherwise”, prefer concise descriptions like “// indicates the operation succeeded” when the return value needs explanation at all.
Always validate inputs, check boundaries, and avoid relying on undocumented API behavior or assumptions about how functions handle edge cases. When dealing with potentially null or invalid data, implement explicit checks rather than assuming the API will behave consistently across all scenarios.
Key practices:
Example from the codebase:
// Instead of assuming SystemParametersInfoW preserves the value on failure
unsigned int hoverTimeoutMillis{ 400 };
if (FAILED(SystemParametersInfoW(SPI_GETMOUSEHOVERTIME, 0, &hoverTimeoutMillis, 0)))
{
hoverTimeoutMillis = 400; // Explicit fallback value
}
// Validate before processing
if (!settingsModelEntries)
{
return single_threaded_observable_vector<Editor::NewTabMenuEntryViewModel>(std::move(result));
}
// Check boundaries to prevent crashes
if (iter.Pos() < _selection->start || iter.Pos() > _selection->end)
{
// Safe to proceed with operation
}
This approach prevents crashes, undefined behavior, and makes code more robust by not relying on implementation details that may change or vary across different environments.
When code involves complex relationships between multiple components or non-obvious usage patterns, add comprehensive explanatory comments that consolidate key information in one accessible location. This is especially important for files with multiple structs, classes, or APIs that work closely together.
The comment should explain:
Example for a header file with multiple related structs:
/*
* Media Resource Management System
*
* This file contains structs that work together to handle media resources:
* - MediaResource: Represents a media file with both original and resolved paths
* - 'ok' indicates if the resource was found, 'resolved' indicates if path resolution succeeded
* - 'value' is the original path, 'resolvedValue' is the absolute/canonical path
* - MediaResourceManager: Handles loading and caching of MediaResource objects
*
* Usage: Create MediaResource objects through MediaResourceManager.load() to ensure
* proper path resolution and caching. Direct construction bypasses validation.
*/
Avoid scattering this information across PR descriptions, comments, or other files. Centralize it where developers will naturally look when working with the code.
Ensure configuration property paths are accurate and complete, especially for nested configurations and context-specific placement. Many configuration issues stem from incorrect or incomplete property paths that prevent features from working properly.
Key areas to verify:
release.docker.repositoryNamerelease.repositoryNamenx property in package.jsonmyorg/app-nameExample of correct nested configuration:
{
"nx": {
"release": {
"docker": {
"repositoryName": "myorg/my-app"
}
}
}
}
Always double-check configuration paths against official documentation and test that configurations work as expected, as incorrect paths often fail silently or produce unexpected behavior.
Environment variables should be properly validated, parsed, and have sensible fallback values. Always validate boolean environment variables using explicit string comparisons rather than truthy checks, provide clear default values, and implement proper error handling for malformed values.
Key practices:
process.env.VAR === '1' || process.env.VAR === 'true'PLAYWRIGHT_FORCE_TTY supporting boolean, width, or “widthxheight” formats)Example:
// Good: Explicit validation with defaults
const headless = process.env.PLAYWRIGHT_HEADLESS === '1' || process.env.PLAYWRIGHT_HEADLESS === 'true';
const allowAndroid = process.env.PLAYWRIGHT_ALLOW_ANDROID === '1';
// Good: Complex parsing with fallbacks
const sizeMatch = process.env.PLAYWRIGHT_FORCE_TTY?.match(/^(\d+)x(\d+)$/);
if (sizeMatch) {
ttyWidth = +sizeMatch[1];
ttyHeight = +sizeMatch[2];
} else {
ttyWidth = +process.env.PLAYWRIGHT_FORCE_TTY || DEFAULT_TTY_WIDTH;
}
// Bad: Truthy check without explicit validation
if (process.env.SOME_FLAG) { /* unreliable */ }
This prevents configuration bugs, improves security by requiring explicit opt-ins for sensitive features, and ensures consistent behavior across different environments.
Choose specific, descriptive names for variables, methods, types, and other identifiers that clearly communicate their purpose and behavior. Avoid generic names, unnecessary abbreviations, and assumptions about usage context.
Key principles:
_allNativeContexts instead of _allContexts when the method only returns native contexts)InstalledBrowserInfo instead of Options)typedArrayConstructors instead of typedArrayCtors)alreadyRegistered instead of foo)getAllByAria if it’s not exclusively for aria purposes)Example:
// Avoid generic or abbreviated names
type Options = { ... }; // ❌ Too generic
const typedArrayCtors = { ... }; // ❌ Unnecessary abbreviation
// Use descriptive, specific names
type InstalledBrowserInfo = { ... }; // ✅ Clear purpose
const typedArrayConstructors = { ... }; // ✅ Full, clear name
// Method names should reflect actual behavior
_allContexts() { return this._browserTypes().flatMap(...); } // ❌ Misleading scope
_allNativeContexts() { return this._browserTypes().flatMap(...); } // ✅ Accurate scope
This approach improves code readability, reduces confusion, and makes the codebase more maintainable by ensuring identifiers clearly communicate their intended purpose.
Always validate inputs and check return values of operations that can fail, providing clear error messages when failures occur. This includes system calls, library functions, and user input validation.
For file operations, check return values and handle errors appropriately:
FILE* procs = fopen(procs_path, "w");
if (procs != NULL) {
if (fprintf(procs, "%d", pid) < 0) {
// Log error and handle failure
}
if (fclose(procs) != 0) {
// Log error and handle failure
}
}
For input validation, check for invalid states and provide helpful error messages:
if (command.empty()) {
blaze_util::StringPrintf(error, "Command cannot be the empty string (try 'help')");
return nullptr;
}
Additionally, implement proactive measures to prevent predictable failures, such as proper argument escaping before passing to system commands. This defensive approach reduces the likelihood of runtime failures and makes debugging easier when issues do occur.
Always validate and sanitize input data against established standards to prevent injection attacks and ensure consistent behavior. This includes validating ARIA attributes according to W3C specifications and encoding potentially dangerous content in CSS or HTML contexts.
For ARIA attributes, ensure they follow W3C standards - aria-disabled should only apply to elements with suitable roles as defined in the specification. For CSS content, encode URLs that could break HTML parsing:
// Validate ARIA attributes against standards
if (isAncestor || kAriaDisabledRoles.includes(getAriaRole(element) || '')) {
// Only apply aria-disabled to elements with suitable roles
}
// Encode dangerous CSS URLs to prevent HTML injection
function escapeURLsInStyleSheet(text: string): string {
const replacer = (match: string, url: string) => {
// Conservatively encode only urls with a closing tag
if (url.includes('</')) {
return `url('${encodeURIComponent(url)}')`;
}
return match;
};
return text.replace(urlToEscapeRegex, replacer);
}
This prevents both accessibility bypasses and XSS attacks through malformed input that doesn’t conform to expected standards.
Ensure proxy configuration follows proper precedence hierarchy and handles different proxy types correctly. User-specified proxy settings should always take priority over environment variables, similar to how browsers handle proxy configuration.
When implementing proxy support:
getProxyAgent(host: string, port: number) {
const proxyFromEnv = getProxyForUrl(`https://${host}:${port}`);
if (proxyFromEnv)
return createProxyAgent({ server: proxyFromEnv });
return createProxyAgent(this._proxy); // User config takes precedence
}
sslProxy for HTTPS connections, not httpsProxy:
switch (url.protocol) {
case 'http:':
proxy.httpProxy = url.host;
break;
case 'https:':
proxy.sslProxy = url.host; // Not httpsProxy
break;
}
// TODO: switch to URL instance instead of legacy object once https-proxy-agent supports it.
return new HttpsProxyAgent(convertURLtoLegacyUrl(proxyOpts));
This approach ensures consistent proxy behavior across different network scenarios and maintains compatibility with existing proxy infrastructure while preparing for future modernization.
Write concise, efficient tests by eliminating repetitive code and combining related test cases. Avoid verbose patterns that can be simplified with better approaches.
Key strategies:
screen:expect() calls with unchanged=true{MATCH: +}Example of verbose vs. concise screen testing:
-- Verbose (avoid):
screen:expect({ any = '.nvim.lua' })
screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny:'), unchanged = true })
-- Concise (prefer):
screen:expect({ any = 'Allowed.*\n.exrc' })
The goal is maintainable tests that clearly express intent without unnecessary repetition or complexity.
Ensure all function documentation accurately reflects the actual code behavior and includes complete, properly formatted descriptions of parameters and return values.
Key requirements:
Match function signatures: Documentation must accurately describe what the function actually does and returns. A void function should not claim to “return true”.
@param[in/out] name Description with two spaces after name@return as the start of a sentence, not embedded within it:
// Incorrect:
/// @return Always return 0.
// Correct:
/// @return always 0.
/// Get information about Num/Caps/Scroll Lock state
///
/// To be used in nvim_get_keyboard_mods_state() API function.
///
/// @param[out] dict Pointer to dictionary where information about modifiers
/// is to be dumped.
/// @param[out] err Location where error message is to be saved, set to NULL
/// if no error.
///
/// @return true in case of error, false otherwise.
This ensures developers can rely on documentation to understand function behavior without needing to read the implementation.
Write code that prioritizes readability and clarity over brevity. Use proper formatting, clear expressions, and consistent patterns to make code easier to understand and maintain.
Key practices:
('Updated state to %s in %s'):format(version_str, name) instead of 'Updated state to ’ .. version_str .. ‘ in ’ .. name .. ‘'(metadata.conceal ~= nil) and metadata.conceal or (metadata[capture] and metadata[capture].conceal) instead of metadata.conceal ~= nil and metadata.conceal or metadata[capture] and metadata[capture].concealif status then instead of if status == true thenlocal version_str = resolve_version() and local version_ref = get_reference() instead of local version_str, version_ref = resolve_version(), get_reference()The goal is to write code that another developer can quickly understand without having to parse complex expressions or guess at intentions.
Write concise, readable code by choosing the most direct expression for simple operations. Use ternary operators for simple boolean assignments instead of verbose if-else blocks, but avoid unnecessary ternaries when direct boolean assignment works. Return comparison results directly rather than using intermediate variables or verbose conditional blocks.
Examples of preferred concise expressions:
// Good: Use ternary for simple assignment
hl.flags |= is_concealed ? kSHConceal : kSHConcealOff;
// Bad: Unnecessary ternary when direct boolean works
bool use_float = strstr(p_cot, "popup") != NULL ? true : false;
// Good: Direct boolean assignment
bool use_float = strstr(p_cot, "popup") != NULL;
// Good: Return comparison directly
return (GetKeyState(VK_CAPITAL) & 0x0001) != 0;
// Bad: Verbose conditional return
if ((GetKeyState(VK_CAPITAL) & 0x0001) != 0) {
return 1;
} else {
return 0;
}
// Good: Direct conditional check
if (!os_get_locks_status(&mods, err)) {
return false;
}
// Bad: Unnecessary intermediate variable
bool status = os_get_locks_status(&mods, err);
if (!status) {
return false;
}
// Good: Readable comparison order
wlv.char_attr = hl_combine_attr(wlv.vcol < TERM_ATTRS_MAX ? term_attrs[wlv.vcol] : 0, wlv.char_attr);
This approach reduces code verbosity while maintaining clarity, making the codebase more maintainable and easier to read.
Algorithms must be thoroughly tested at boundary conditions and edge cases to prevent subtle bugs. Pay special attention to off-by-1 errors in mathematical calculations, empty collections, and boundary values that might cause unexpected behavior.
Common edge cases to validate:
Math.log10(10) edge case)Example from the codebase:
// Problematic - fails for totalTestCount === 10
const indexLength = Math.ceil(Math.log10(this.totalTestCount));
// Correct - handles the edge case properly
const indexLength = Math.ceil(Math.log10(this.totalTestCount + 1));
When implementing algorithms, create test cases that specifically target these boundary conditions. Consider reusing existing, well-tested algorithmic logic rather than reimplementing similar functionality, as proven algorithms are less likely to contain edge case bugs.
When implementing network protocols or communication formats, prioritize standardized specifications over legacy or device-specific formats, even when existing code uses older approaches. Legacy formats may work but can cause compatibility issues and confusion for applications that expect standard compliance.
For example, when implementing Device Attributes (DA) responses, use the standard format with proper parameter meanings rather than legacy device-specific formats:
// Instead of legacy format that predates standardization:
char vterm_primary_device_attr[] = "1;2;52"; // Device-specific format
// Use standardized format:
char vterm_primary_device_attr[] = "61;52"; // Standard level-1 device with clipboard extension
Similarly, ensure protocol detection logic is explicit and follows expected patterns:
// Clear boolean conversion for protocol detection
bool is_tcp = !!strrchr(server_address, ':');
This approach improves interoperability, reduces maintenance burden, and ensures your implementation works correctly with a broader range of clients and tools that expect standard-compliant behavior.
Security-related warnings and error messages should provide clear, actionable guidance on how users can safely resolve the issue, not just inform them of the problem. When displaying security warnings, include specific instructions that guide users through the secure workflow.
For example, instead of just stating a file is untrusted:
local msg = cwd .. pathsep .. 'Xfile is not trusted.'
Provide clear next steps:
local msg = cwd .. pathsep .. 'Xfile is not trusted. To enable it, choose (v)iew then run `:trust`.'
This approach helps users understand both the security concern and the proper way to address it, reducing the likelihood of unsafe workarounds or user confusion.
Maintain consistency in syntax highlighting patterns by using appropriate, specific scopes and avoiding overly complex or noisy patterns. Follow Helix-specific conventions rather than generic tree-sitter patterns.
Key guidelines:
@keyword.control.repeat instead of generic @keyword when appropriate@constant.numeric.integer instead of generic @number(ERROR) @error that distract during typing#any-of? for multiple similar matches#match? instead of platform-specific ones like #lua-match?Example of good pattern specificity:
; Good - specific scopes
[
"for"
"while"
] @keyword.control.repeat
[
"if"
"else"
] @keyword.control.conditional
; Avoid - overly generic
[
"for"
"while"
"if"
"else"
] @keyword
Example of proper precedence:
; Specific pattern first
((comment) @comment.block.documentation
(#match? @comment.block.documentation "^//!"))
; Generic pattern second
(comment) @comment.line
This approach ensures highlighting is consistent, follows project conventions, and provides clear visual feedback without being distracting or overly complex.
Perform comprehensive input validation and precondition checks at the beginning of functions, before executing any operations that could have side effects or modify system state. This prevents partial execution, inconsistent states, and resource leaks when validation fails.
Key principles:
Example from the codebase:
// BAD: Validation after side effects
FILE *f = fopen(path.data, "w"); // Side effect first
if (f == NULL) {
return; // But cursor was already moved
}
// GOOD: Validation before side effects
if (HAS_KEY(opts, set_extmark, conceal)) {
if (opts->conceal.type == kObjectTypeBoolean) {
// Handle boolean case
} else if (opts->conceal.type == kObjectTypeString) {
// Handle string case
} else {
// ERROR: type is neither string nor boolean
goto error;
}
}
This approach prevents crashes, data corruption, and difficult-to-debug partial state changes by catching problems before they can cause damage.
Ensure similar API functions use consistent parameter patterns, types, and behaviors. When designing new APIs or modifying existing ones, identify related functions and align their interfaces to create predictable, reusable patterns.
Key principles:
Use consistent parameter types across similar functions (e.g., if one diagnostic function accepts namespace as number |
table, others should too) |
Example from diagnostic APIs:
-- Inconsistent: some functions support table namespace, others don't
vim.diagnostic.get(bufnr, { namespace = {ns1, ns2} }) -- supported
vim.diagnostic.open_float(opts) -- namespace as table not supported
-- Consistent: all diagnostic functions handle namespace parameter the same way
vim.diagnostic.get(bufnr, { namespace = ns_or_table })
vim.diagnostic.open_float({ namespace = ns_or_table })
This approach reduces cognitive load for users, enables code reuse, and makes the API more maintainable. Before implementing new functionality, survey existing similar APIs and adopt their established patterns rather than inventing new ones.
Maintain consistent naming patterns and terminology across the codebase to reduce cognitive load and improve code clarity. The same concept should always use the same name in different contexts.
Key principles:
on_ for event handlers/callbacks, is_ for boolean predicates, get_ for accessorsstart/end for ranges, refresh() for common update operationsExamples:
-- Good: consistent callback naming
function on_document_highlight(err, result, ctx) end
-- Bad: inconsistent suffix
function document_highlight_cb(err, result, ctx) end
-- Good: consistent terminology
local function get_logical_pos(diagnostic) end
-- Bad: mixing terminology
local function get_logical_location(diagnostic) end
-- Good: established convention
local mark = { start_line = start_row, start_col = start_col }
-- Bad: non-standard naming
local mark = { begin_line = start_row, begin_col = start_col }
When introducing new names, check existing code for established patterns. Consistency trumps personal preference - if the codebase uses a particular naming convention, follow it even if you prefer alternatives.
Ensure all functions have comprehensive, accurate documentation including required tags (@param, @return, @since), clear descriptions that match actual behavior, and explanatory comments for complex logic.
Functions should include:
Example of complete documentation:
--- Makes an HTTP GET request to the given URL.
--- Can either return the body or save it to a file.
---
--- @param url string The URL to fetch.
--- @param opts? table Optional parameters:
--- - verbose (boolean|nil): Enables curl verbose output.
--- - retry (integer|nil): Number of retries on transient failures (default: 3).
--- - output (string|nil): If set, path to save response body instead of returning it.
--- @param on_exit? fun(err?: string, content?: string) Optional callback for async execution
--- @return string|boolean|nil Response body on success; `nil` on failure
--- @since 14
function M.get(url, opts, on_exit)
-- Compute positions, set them as extmarks, and store in diagnostic._extmark_id
-- (used by get_logical_location to adjust positions)
once_buf_loaded(bufnr, function()
-- complex logic here
end)
end
Avoid confusing wording, inaccurate descriptions, or missing required documentation tags. Future developers should be able to understand the function’s purpose, parameters, and behavior without studying the implementation.
Don’t use mechanisms that suppress or hide errors unless absolutely necessary for the application flow. Error masking makes debugging difficult and can hide important issues from users and developers.
Problematic patterns to avoid:
pcall() just to ignore errors: “pcall masks errors”silent! to commands unnecessarily: “silent with ‘!’ silences errors…”vim.v.shell_errorBetter alternatives:
vim.schedule() if you need to prevent errors from disrupting flowt.pcall_err for testingvim.system():wait() instead of vim.fn.system() to avoid fragile error handlingExample:
-- Bad: Masks the actual error
local ok, _ = pcall(api.nvim_command, 'edit')
-- Better: Use proper error handling utility
eq(':edit command in prompt buffer throws error',
t.pcall_err(api.nvim_command, 'edit'))
-- Bad: Silences all errors
nvim_command('silent! edit `=__fname`')
-- Better: Let errors show unless specifically needed
nvim_command('edit `=__fname`')
Only suppress errors when you have a clear reason and a plan for handling the error condition appropriately.
Avoid creating special-purpose configuration options when simpler alternatives exist. Don’t force users to call setup functions or provide explicit configuration for basic functionality to work.
As noted in the discussions: “special-purpose options are clumsy and a maintenance burden” and “users will be forced to call this function in order to use your plugin, even if they are happy with the default configuration.”
Instead of creating configuration options, consider:
Example of what to avoid:
-- Don't force this pattern
vim.g.query_autoreload_on = { 'InsertLeave', 'TextChanged' }
-- Instead, document the underlying mechanism
vim.api.nvim_create_autocmd('BufWritePost', {
pattern = '*.scm',
callback = function() vim.treesitter.query.invalidate_cache() end
})
For operations that require user consent (like network downloads), provide confirmation prompts rather than configuration flags. This maintains security while avoiding configuration complexity.
When implementing network functionality, consolidate around standardized APIs like vim.net.request() instead of maintaining custom download functions or direct curl calls. Implement comprehensive testing for network operations using integration test guards to prevent failures in environments without network access.
Key practices:
vim.net.request()NVIM_TEST_INTEG)t.skip() to conditionally skip network tests when integration testing is disabledExample implementation:
-- Instead of custom download functions
local function download(url)
-- Replace with vim.net.request()
end
-- Proper test guarding
describe('network functionality', function()
local skip_integ = os.getenv('NVIM_TEST_INTEG') ~= '1'
it('handles text responses', function()
if skip_integ then t.skip() end
-- network test implementation
end)
it('handles binary responses', function()
if skip_integ then t.skip() end
-- binary response test
end)
end)
This approach ensures consistent network handling across the codebase while maintaining testability in various environments.
Choose parameter and method names that accurately reflect their semantic meaning and implementation reality, rather than names that may be misleading or platform-specific.
Avoid names that imply specific technical requirements when the actual implementation is more flexible. For example, a parameter named guid suggests it must be a GUID format, when the implementation may accept any unique string identifier.
Similarly, method names should accurately describe their action. Names like evaluate can be misleading if they suggest using eval() when the actual implementation executes code differently.
Examples of improvements:
guid → identifier (when the parameter accepts any unique string, not just GUIDs)roundedCorner → roundedCorners (when the property affects multiple corners)evaluateInMainWorld → executeScriptInMainWorld (when the method executes rather than evaluates code)This principle helps prevent developer confusion and makes APIs more intuitive across different platforms and use cases.
CI/CD processes should eliminate unnecessary repetition and redundant operations across projects and builds. This includes avoiding repeated warning messages, preferring template-based configurations over runtime string replacements, and ensuring operations are performed once at the appropriate level rather than repeatedly for each project.
Key practices:
Example of the problem:
// Avoid: Warning shown for every project
logger.warn(
`Docker support is experimental. Breaking changes may occur and not adhere to semver versioning.`
);
// Better: Show warning once at the process level during nx-release
Example of preferred approach:
// Instead of runtime string replacement logic
// Update the template at packages/node/src/generators/application/files/common/webpack.config.js__tmpl__
// This ensures consistent configuration without repeated processing
This approach reduces build times, minimizes log noise, and creates more maintainable CI/CD pipelines by eliminating unnecessary duplication of operations.
Ensure consistent parameter handling across API methods by using appropriate defaults, proper type conversion, validation with meaningful constants, and cross-platform behavior consistency.
Key practices:
void SetBounds(const gfx::Rect& bounds, bool animate = false)dict.Get("frameOrigin", &frame_origin_url) where frame_origin_url is a GURLconstexpr int kMinSizeReqdBySpec = 100; // Per Web API specwidth = std::max(kMinSizeReqdBySpec, inner_width)SetUserAgent(user_agent, std::move(ua_metadata))This approach reduces API complexity, improves type safety, and ensures predictable behavior across different platforms and use cases.
Keep code well-organized by separating interface from implementation, managing dependencies properly, and following consistent structural patterns. Function bodies should remain in implementation files rather than headers to reduce compilation dependencies and improve maintainability. Organize includes strategically - move them to implementation files when possible and always use relative paths rather than src-based paths. Structure classes and functions appropriately by preferring namespaces over global functions, placing functions within relevant classes when they operate on class data, and following standard member ordering with private members last. Avoid unnecessary code elements like redundant this usage.
Example of proper structure:
// Header file - interface only
class CHyprCtl {
public:
static std::string getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format);
private:
// private members come last
wl_event_source* m_eventSource = nullptr;
};
// Implementation file - bodies and includes
#include "relative/path/to/header.hpp" // relative paths only
#include <fcntl.h> // moved from global includes
std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
// implementation here, avoid unnecessary 'this->'
return result;
}
Write comprehensive tests that cover edge cases and platform-specific scenarios to uncover underlying implementation issues rather than masking them with workarounds. When encountering failures, investigate the root cause through targeted testing before implementing fallback mechanisms.
For platform-specific issues, add integration tests that run on the affected platforms:
// Instead of adding fallbacks like:
if (!IsReadableFile(*result)) {
// fallback logic
}
// Add platform-specific integration tests to investigate the root cause
For complex functionality, test edge cases systematically:
// Test comprehensive scenarios like:
// * UTF-16 strings with non-ASCII BMP characters
// * UTF-16 strings with surrogate pairs
// * Latin1-hack strings with invalid UTF-8
// * Unpaired surrogates in various positions
This approach often reveals bugs in existing implementations that would otherwise remain hidden. As noted in one review: “This was both a nightmare and super helpful as the previous implementation had a number of bugs.” Comprehensive testing serves as both quality assurance and debugging tool, helping teams understand the true behavior of their code rather than working around symptoms.
Security credentials and access control mechanisms should be pre-configured at deployment or configuration time rather than resolved dynamically at runtime. Dynamic credential fetching introduces injection risks and makes security boundaries harder to audit and control.
Instead of fetching credentials from APIs or using runtime variables for security decisions, embed credentials in secure configuration stores (like Terraform-managed secrets) or integrate with centralized identity providers and zero-trust systems.
Example of problematic runtime resolution:
# Risky: Dynamic API call with potentially injectable variable
api_response=$(curl -s "https://api.github.com/users/$GITHUB_ACTOR/keys")
echo "$api_response" | jq -r '.[].key' > authorized_keys
Preferred approaches:
# Better: Pre-configured credentials from secure store
echo "$PRECONFIGURED_SSH_KEYS" > authorized_keys
# Best: Centralized identity-based access control
# Configure hostname as SSH target in zero-trust system
# Assign IDP roles (e.g., wg-infra) access to hostname
This approach eliminates injection vectors, improves auditability, and centralizes security policy management.
When implementing configuration settings, carefully consider and limit their scope to prevent unintended broad impact across systems or workflows. Configuration changes should be targeted and controlled rather than applied globally when only specific contexts require them.
For example, instead of enabling debugging for all pipelines:
env:
ACTIONS_STEP_DEBUG: ${{ secrets.ACTIONS_STEP_DEBUG }}
Consider using conditional logic to scope the configuration:
env:
ACTIONS_STEP_DEBUG: ${{ github.ref == secrets.DEBUG_BRANCH_NAME && secrets.ACTIONS_STEP_DEBUG || '' }}
Similarly, when processing configuration-driven logic, implement safeguards to prevent excessive or uncontrolled behavior:
// Add limits to prevent configuration from causing excessive operations
labels.push(versionLabel);
if (labels.length >= 5) {
break;
}
This approach ensures configuration changes remain predictable and don’t inadvertently affect unrelated parts of the system.
Ensure proper object lifetime management in concurrent scenarios to prevent crashes from dangling pointers and premature destruction. Use weak references for event handlers that may outlive their target objects, and capture strong references in async operations to keep objects alive during coroutine execution.
Key practices:
get_weak() pattern for event handlers: handler({ get_weak(), &Class::Method }) instead of raw this pointersthis when the object needs to stay alive across async boundaries: auto strongThis = get_self<implementation::ClassName>();Example of proper weak reference usage:
// Good: Uses weak reference pattern
_connection.StateChanged(winrt::auto_revoke, { get_weak(), &ControlCore::_connectionStateChangedHandler });
// Bad: Raw pointer that can dangle
_accessibilitySettings.HighContrastChanged([this](auto&&, auto&&) {
// 'this' may be destroyed while handler is still registered
});
This prevents race conditions where objects are destroyed while concurrent operations are still referencing them, which is a common source of crashes in multithreaded applications.
Establish consistent patterns for nullable return values in APIs and document them clearly. Use null consistently for “not found” or “unavailable” cases rather than mixing null, undefined, and false. Always document when and why nullable values are returned, explaining the specific conditions that lead to these values.
For return type documentation, specify the nullable type and provide clear explanations:
// Good: Consistent use of null with clear documentation
Returns `WebContents | null` - The `WebContents` owned by this view
or `null` if the contents are destroyed.
Returns `WebFrameMain | null` - A frame with the given process and frame token,
or `null` if there is no WebFrameMain associated with the given IDs.
// Avoid: Mixing null, undefined, and false inconsistently
Returns `string | false` // when documented as `string | null`
Returns `ServiceWorkerMain | undefined` // when other APIs use `null`
Ensure implementation matches documentation - if the docs specify string | null, the implementation should return null, not false or undefined. This consistency helps developers understand and handle edge cases predictably across the entire API surface.
Actively identify and eliminate unnecessary computational overhead in algorithms, particularly focusing on nested loops and inefficient data operations that can significantly impact performance.
Key areas to review:
Nested Loop Analysis: Question the necessity of multiple nested loops. As seen in diagnostic processing code, triple-nested loops were “completely unnecessary” and could be eliminated entirely. Always ask: “Can this nesting be reduced or avoided?”
String Building Efficiency: Avoid repeated string concatenation in loops, which creates O(n²) complexity. Instead, use table-based accumulation:
-- Inefficient: O(n²) due to string immutability
local result = ''
for char in text do
result = result .. char -- Creates new string each time
end
-- Efficient: O(n) using table accumulation
local parts = {}
for char in text do
table.insert(parts, char)
end
local result = table.concat(parts)
Iterator Overhead: When implementing custom iterators, avoid expensive operations like pack/unpack for multiple return values. Consider the performance implications of each abstraction layer and whether the convenience justifies the overhead.
Algorithmic Alternatives: Before implementing complex nested logic, research if existing utilities or algorithms can solve the problem more efficiently. For example, reusing proven range-checking logic instead of reimplementing it.
The goal is to maintain code clarity while ensuring algorithms scale appropriately with input size. When in doubt, prefer simpler algorithms with better complexity characteristics over complex optimizations that may introduce bugs.
Write thorough JSDoc comments for interfaces, functions, and methods that clearly explain their purpose and behavior. Include:
For interfaces:
/**
* Represents a configured task in the system.
*
* This interface is used to define tasks that can be executed within the workspace.
* It includes optional properties for identifying and describing the task.
*
* Properties:
* - `type`: (optional) The type of the task, which categorizes it (e.g., "build", "test").
* - `label`: (optional) A user-facing label for the task, typically used for display purposes.
* - `_label`: (optional) An internal label for the task, used for unique identification.
*/
interface IConfiguredTask {
type?: string;
label?: string;
_label?: string;
}
For functions:
/**
* Determines the type of token based on command line and cursor position.
*
* Examples:
* - `getTokenType({commandLine: "git commit", cursorPosition: 3}, TerminalShellType.Bash)`
* Returns TokenType.Command as cursor is within the command
* - `getTokenType({commandLine: "git commit -m", cursorPosition: 11}, TerminalShellType.Bash)`
* Returns TokenType.Argument as cursor is after a command argument flag
*
* @param ctx The command context containing command line and cursor position
* @param shellType The type of shell being used
* @returns The determined token type based on context
*/
function getTokenType(ctx: { commandLine: string; cursorPosition: number }, shellType: TerminalShellType | undefined): TokenType {
// Implementation
}
Prefer descriptive main comments over tag-only documentation and ensure every component of your API is properly documented. This practice significantly improves code maintainability and reduces onboarding time for new developers.
Remove redundant code patterns that add complexity without value. This includes:
Example of simplifying control flow:
// Before
if (filename.endsWith(PROMPT_FILE_EXTENSION)) {
return filename.slice(0, -PROMPT_FILE_EXTENSION.length);
} else if (filename.endsWith(INSTRUCTION_FILE_EXTENSION)) {
return filename.slice(0, -INSTRUCTION_FILE_EXTENSION.length);
} else if (filename === COPILOT_CUSTOM_INSTRUCTIONS_FILENAME) {
return filename.slice(0, -3);
}
// After
if (filename.endsWith(PROMPT_FILE_EXTENSION)) {
return filename.slice(0, -PROMPT_FILE_EXTENSION.length);
}
if (filename.endsWith(INSTRUCTION_FILE_EXTENSION)) {
return filename.slice(0, -INSTRUCTION_FILE_EXTENSION.length);
}
if (filename === COPILOT_CUSTOM_INSTRUCTIONS_FILENAME) {
return filename.slice(0, -3);
}
For repeated patterns, extract into helper functions:
// Before
const FAILED_TASK_STATUS = { icon: { ...Codicon.error, color: { id: problemsErrorIconForeground } }};
const WARNING_TASK_STATUS = { icon: { ...Codicon.warning, color: { id: problemsWarningIconForeground } }};
// After
const createColoredIcon = (icon: Codicon, colorId: string) => ({ ...icon, color: { id: colorId }});
const FAILED_TASK_STATUS = { icon: createColoredIcon(Codicon.error, problemsErrorIconForeground) };
const WARNING_TASK_STATUS = { icon: createColoredIcon(Codicon.warning, problemsWarningIconForeground) };
Make test assertions specific and verifiable rather than relying on generic metrics or counts. Use explicit checks for expected behaviors and implement proper error handling to ensure tests fail fast when something goes wrong.
Instead of asserting on generic counts like “2 total actions”, verify that specific actions were executed by using detailed logging and targeted assertions:
# Poor: Generic assertion
expect_log "2 total actions"
# Better: Specific assertion
bazel build --experimental_ui_debug_all_events //pkg:a
expect_log "Executing genrule //pkg:a"
Additionally, use proper error handling mechanisms like set -e in shell tests to ensure failures are caught immediately:
#!/bin/sh
set -e # Fail fast on any error
touch "$TEST_TMPDIR/test_file" # Will properly fail if directory not writable
This approach makes tests more reliable, easier to debug when they fail, and provides clearer feedback about what specifically went wrong during test execution.
Add explanatory comments and documentation for complex logic, non-obvious code behavior, method parameters, and API functionality to improve code readability and maintainability.
This applies to several scenarios:
Examples:
// Comment explaining complex logic
if (entry.getKey() == null) {
// Remove entry when key is null - using value as the key to remove
normalizedEntries.remove(entry.getValue());
}
// Comment explaining boolean parameter meaning
SpawnInputExpander spawnInputExpander = new SpawnInputExpander(execRoot, /* relativeToExecRoot= */ false);
// Complete method documentation
/**
* Renames the file or directory from src to dst.
* Parent directories are created as needed. If the target already exists, it will be overwritten.
*
* @param clientEnv the client environment variables used for subprocess execution
*/
The goal is to make code self-documenting through clear comments that explain the “why” behind non-obvious implementation decisions, parameter meanings, and expected behavior.
Identify and optimize expensive operations in frequently executed code paths to prevent performance bottlenecks. Hot paths include rendering loops, input event handlers, and frequently called utility functions.
Key optimization strategies:
Example of caching expensive system calls:
static bool checkDrmSyncobjTimelineSupport(int drmFD) {
static bool cached = false;
static bool result = false;
if (!cached) {
uint64_t cap = 0;
int ret = drmGetCap(drmFD, DRM_CAP_SYNCOBJ_TIMELINE, &cap);
result = (ret == 0 && cap != 0);
cached = true;
}
return result;
}
Example of early bailout optimization:
void damageEntireParent() {
CBox box = getParentBox();
if (box.empty()) // Skip expensive damage calculation
return;
g_pHyprRenderer->damageBox(box);
}
Avoid config lookups in hot paths like input handlers - instead store values in object state during initialization. This prevents “extreme performance kill” scenarios where expensive operations execute on every mouse movement or render frame.
When manipulating URLs for API calls, prioritize preserving the original URL structure over using convenience APIs that may normalize or modify the URL unexpectedly. This is especially important when appending query parameters or handling URL fragments.
Use manual string building approaches when you need to maintain exact URL formatting, as browser APIs like new URL() may normalize paths, convert case, or modify other URL components in ways that could break existing API integrations.
Example approach for parameter appending:
// Avoid: May normalize the URL
const urlObj = new URL(finalUrl);
urlParams.forEach(p => urlObj.searchParams.append(p.name, p.value));
// Prefer: Preserves original URL structure
const [base, hash] = finalUrl.split('#');
const separator = base.includes('?') ? '&' : '?';
const queryString = urlParams
.map(p => `${encodeURIComponent(p.name)}=${encodeURIComponent(p.value)}`)
.join('&');
finalUrl = base + separator + queryString + (hash ? `#${hash}` : '');
Always test URL manipulation with edge cases including fragments, special characters, and non-standard but valid URL formats to ensure your API calls work with diverse endpoint structures.
Always handle null and undefined values explicitly through proper type declarations and validation patterns rather than using non-null assertions or unsafe type casts. This ensures type safety and prevents runtime errors.
Key practices:
Example:
// ❌ Avoid
function processItem(item: Item | undefined) {
return item!.value; // Unsafe non-null assertion
}
// ✅ Better
function processItem(item: Item | undefined) {
if (!item) {
return undefined;
}
return item.value;
}
// ✅ Even better - using type guards
function processItem(item: Item | undefined): string | undefined {
if (isValidItem(item)) {
return item.value;
}
return undefined;
}
// ✅ Best - with proper typing and validation
interface ItemProcessor {
process(item: Item): string;
}
class SafeItemProcessor implements ItemProcessor {
process(item: Item): string {
// Type system ensures item is never null/undefined
return item.value;
}
}
When writing concurrent code, always execute independent operations in parallel rather than sequentially to improve performance and responsiveness. Using parallel execution patterns can significantly reduce waiting time for I/O-bound operations.
For API calls or file operations that don’t depend on each other:
// Instead of sequential execution:
const entitlements = await this.getEntitlements(session.accessToken, tokenEntitlementUrl);
const chatEntitlements = await this.getChatEntitlements(session.accessToken, chatEntitlementUrl);
// Prefer parallel execution:
const [entitlements, chatEntitlements] = await Promise.all([
this.getEntitlements(session.accessToken, tokenEntitlementUrl),
this.getChatEntitlements(session.accessToken, chatEntitlementUrl)
]);
When implementing operations that can take variable time to complete:
Promise.race() to process results as they arriveRemember that excessive parallelism can lead to resource contention, so balance parallelism with the available system resources. For CPU-bound tasks, consider using worker threads or a task queue to prevent blocking the main thread.
All code elements should have sufficient documentation to understand their purpose, usage, and context. This includes adding explanatory comments for non-obvious constants, documenting private functions for maintainability, ensuring grammatical accuracy in all documentation, and providing necessary context such as prerequisites or limitations.
Key areas to address:
DWP = "dwp" // Name of the debug package action)Example of complete documentation:
// Returns the repository name for the current source file.
// Requires C++20 support for __builtin_FILE functionality.
// Use this from within `cc_test` rules.
static std::string CurrentRepository(const std::string& file = __builtin_FILE());
This ensures that future developers can understand and maintain the code without needing to reverse-engineer functionality or guess at requirements.
Choose explicit, unambiguous names for functions, variables, and parameters to avoid conflicts with common types and reduce reliance on implicit assumptions. Prefer descriptive names that clearly indicate purpose over generic terms that might be confused with built-in types or require string parsing.
For function names, avoid generic terms like error that commonly appear as type instances. Instead, use prefixed names like log_error or logError to clearly indicate the function’s purpose.
For parameters, prefer explicit values over implicit extraction. Rather than parsing identifiers from formatted strings, pass the required values directly as separate parameters.
Example:
// Avoid: Generic name that conflicts with Error type
pub fn error(message: String) { ... }
// Prefer: Explicit, descriptive name
pub fn log_error(message: String) { ... }
// Avoid: Implicit extraction from formatted strings
let project_name = task_id.split(':').next().unwrap_or(task_id);
// Prefer: Explicit parameter passing
fn process_task(task_id: String, project_name: String) { ... }
Names should accurately reflect their purpose and behavior, providing users and developers with clear expectations. For identifiers, use specific qualifiers that indicate their intended context rather than generic terms. For UI elements like commands, ensure the name accurately represents the behavior (e.g., only use ellipsis ‘…’ when additional input will be requested).
Good example:
{
"id": "chat-instructions", // Qualified to show specific purpose
"command": "Delete Worktree" // No ellipsis as no picker is shown
}
Poor example:
{
"id": "instructions", // Too generic, lacks context
"command": "Delete Worktree..." // Misleading ellipsis suggests a picker
}
Always keep dependencies, runtime environments, and libraries updated with the latest security patches to mitigate known vulnerabilities. Prioritize security updates even for minor version changes.
Example:
# Incorrect
# .nvmrc
22.15.1
# Correct
# .nvmrc
22.17.1 # Latest version with security fixes
Regular dependency updates are a critical security practice. When security patches are available (like Node.js 22.17.1 that fixes security issues), they should be applied promptly rather than waiting for future update cycles. Establish a process for monitoring security advisories related to your project dependencies and implement patches in a timely manner.
Choose efficient data structures and algorithms to minimize computational overhead and improve performance. This involves selecting appropriate containers based on usage patterns, avoiding unnecessary operations like redundant copies or conversions, and leveraging optimized library functions.
Key practices:
absl::flat_hash_map instead of std::unordered_map, or base::MakeFixedFlatSet for compile-time known setsconst auto& item) or range-based algorithmsbase::ranges::any_of over custom implementationsstd::move on temporary values that already have move semanticsExample of optimization:
// Less efficient - custom loop with copies
for (size_t i = 0; i < val.planes.size(); ++i) {
auto plane = val.planes[i]; // Unnecessary copy
// process plane...
}
// More efficient - range-based with references
for (const auto& plane : val.planes) {
// process plane...
}
// Even better - use library algorithms when applicable
auto v8_planes = base::ToVector(val.planes, [isolate](const auto& plane) {
// transform logic...
});
This approach reduces computational complexity, memory usage, and improves overall performance by making algorithmic choices that align with actual usage patterns.
Identify and eliminate unnecessary duplicate operations, redundant function calls, and repeated computations that can impact performance. Common patterns include: avoiding redundant parameter retrieval when values are already available, preventing duplicate map lookups by caching results, checking for changes before performing expensive operations, and caching expensive computations for reuse.
Examples of optimization opportunities:
UpdateWindowAccentColor(active) rather than calling IsActive() againif (const auto* orig = base::FindOrNull(options.environment, key)) instead of separate find() and second lookupif (title == GetTitle()) return; before triggering update eventsbase::NoDestructor<std::string> for values computed repeatedly during module loadingv8::Local<v8::String> keys once and reuse them instead of recreating identical strings multiple timesConsider debouncing rapidly-triggered operations like window state saves during resize events to prevent performance degradation from excessive I/O operations.
Always reuse existing defined constants, resources, and reusable components instead of duplicating values or creating redundant implementations. This improves maintainability, ensures consistency across the codebase, and reduces the risk of introducing inconsistencies when values need to be updated.
Key practices:
{StaticResource StandardControlMaxWidth} instead of hardcoding values like “1000”SettingsStackStyle and PivotStackStyle if they’re identical)Example of good practice:
<!-- Good: Reuse existing resource -->
<muxc:BreadcrumbBar MaxWidth="{StaticResource StandardControlMaxWidth}" />
<!-- Bad: Hardcode the same value -->
<muxc:BreadcrumbBar MaxWidth="1000" />
Example for C++ constants:
// Good: Move constant into function scope to avoid duplication
uint64_t rapidhash_withSeed(const void* key, size_t len, uint64_t seed) {
static const uint64_t rapid_secret[3] = { /* values */ };
// use rapid_secret here
}
// Bad: Global constant duplicated in every compilation unit
static const uint64_t rapid_secret[3] = { /* values */ };
This approach reduces maintenance burden and ensures consistent behavior across the application.
Before performing expensive operations, check if the work is actually needed or if more efficient alternatives exist. This includes validating preconditions, using optimized system calls, and avoiding duplicate method invocations.
Key patterns to apply:
Guard expensive operations with feature flags: Don’t perform costly work when features are disabled. For example, avoid expensive cache pruning operations that add startup time for users not using the feature.
Use efficient system calls: Replace multiple system calls with single, more informative ones: ```java // Instead of: if (!path.exists()) { return true; }
// Use: var stat = path.statNullable(); if (stat == null) { return true; }
3. **Cache method results**: Avoid calling the same method multiple times:
```java
// Instead of:
if(Profiler.getProcessCpuTimeMaybe() != null) {
// ... use Profiler.getProcessCpuTimeMaybe() again
}
// Use:
var processCpuTime = Profiler.getProcessCpuTimeMaybe();
if(processCpuTime != null) {
// ... use processCpuTime
}
if (pathMapper.isNoop()) {
return new StringValue(name);
}
// ... expensive path mapping logic
// Instead of manual filtering with singleton lists
// Use Iterables.filter to avoid allocation overhead
This approach reduces unnecessary CPU cycles, I/O operations, and memory allocations, leading to better overall performance.
Identify and cache the results of expensive operations that are computed repeatedly with the same inputs. This includes function calls, data structure creation, regex compilation, and complex calculations that don’t change between invocations.
Common patterns to watch for:
Examples of optimization opportunities:
// Before: Each CommandViewModel duplicates the same data
class CommandViewModel {
IMap<ShortcutAction, hstring> _AvailableActionsAndNamesMap; // Duplicated across instances
};
// After: Share expensive data across instances
class CommandViewModel {
static const IMap<ShortcutAction, hstring> _SharedActionsAndNames; // Computed once
};
// Before: Repeated expensive function calls
if (_WindowProperties.WindowName() != L"") {
auto name = _WindowProperties.WindowName(); // Called again
}
// After: Cache the result
if (const auto windowName = _WindowProperties.WindowName(); !windowName.empty()) {
// Use windowName variable
}
// Before: Regex compiled on every validation
void _validateRegex(const hstring& regex) {
std::wregex{ regex.cbegin(), regex.cend() }; // Expensive compilation each time
}
// After: Cache compiled regex instances
static std::unordered_map<hstring, std::wregex> _regexCache;
This optimization is particularly important for operations in hot paths, UI updates, or when processing large datasets. Always measure performance impact to ensure the caching overhead doesn’t exceed the benefits.
When adding new configuration options or settings, leverage existing configuration frameworks and patterns rather than implementing custom solutions. This ensures consistency, reduces boilerplate code, and maintains alignment with established practices.
For settings, use the appropriate macro systems:
// Instead of manual implementation
bool UseMicaAlt() const;
bool _useMicaAlt = false;
// Use the established macro pattern
#define MTSM_GLOBAL_SETTINGS_FIELDS(X) \
X(bool, UseMicaAlt, "useMicaAlt", false)
For configuration files, follow existing patterns in the codebase. When multiple variants are needed (like different Visual Studio editions), create separate configuration files following established naming conventions rather than trying to handle all cases in one file.
Avoid runtime configuration decisions that should be compile-time. Configuration values should not be exposed broadly with generic names, and branding-specific code should be compiled out rather than decided at runtime.
When adding new configuration options, ensure corresponding schema files and documentation are updated to maintain consistency across the system.
Use const for variables that are not modified after initialization, and avoid creating unnecessary temporary variables when the value can be computed directly in the declaration.
This improves code clarity by making immutability explicit and reduces cognitive load by eliminating intermediate variables that don’t add semantic value.
Examples:
// Preferred
const auto paneActiveBorderColor = theme.Pane() ? theme.Pane().ActiveBorderColor() : nullptr;
const auto setter = setterBase.as<winrt::Windows::UI::Xaml::Setter>();
const auto property = setter.Property();
// Avoid
auto paneActiveBorderColor = theme.Pane() ? theme.Pane().ActiveBorderColor() : nullptr;
const bool isAudibleSet = WI_IsFlagSet(bellStyle, BellStyle::Audible);
const bool isWindowSet = WI_IsFlagSet(bellStyle, BellStyle::Window);
// ... later using these bools
if (isAudibleSet && isWindowSet) // Instead, use direct flag checks
For parameter passing, prefer const& over copying when the parameter won’t be modified, or use move semantics when transferring ownership. Avoid the auto{} brace-initialization syntax as it can be brittle and is not widely adopted in the ecosystem.
Always use correct and explicit parameters when calling APIs, rather than relying on defaults or passing incorrect values. This includes passing appropriate objects to API methods, specifying all required parameters explicitly, and using correct operation patterns.
Key practices:
nullptr instead of *this when documentation suggests it)--iterator when you don’t need the previous result)ReplaceAll() instead of Clear() followed by multiple Append() calls)Example from the codebase:
// Instead of passing potentially incorrect object reference
eventArgs.GetCurrentPoint(*this).Properties().IsMiddleButtonPressed()
// Pass the correct parameter as documented
eventArgs.GetCurrentPoint(nullptr).Properties().IsMiddleButtonPressed()
// For programmatic operations, always specify explicit parameters
profile->Commandline(winrt::hstring{
fmt::format(FMT_COMPILE(L"cmd /k winget install --interactive --id Microsoft.PowerShell --source winget & echo. & echo {} & exit"),
RS_(L"PowerShellInstallationInstallerGuidance"))
});
This approach reduces bugs, improves maintainability, and ensures APIs behave as intended rather than relying on potentially fragile default behaviors.
Ensure React components avoid unnecessary rerenders by maintaining object identity in dependencies and eliminating unused state variables. When objects are recreated on every render, they cause effects and child components to re-execute unnecessarily, leading to performance issues.
Key practices:
useMemo to maintain object identity for effect dependencies when the underlying data hasn’t changedExample of the problem:
// Bad: Creates new object every render, causing effect to run unnecessarily
const snapshotUrls = {
snapshotInfoUrl: snapshot?.url
};
React.useEffect(() => {
// This runs on every render due to new snapshotUrls object
}, [snapshotUrls]);
// Good: Memoize to maintain object identity
const snapshotUrls = React.useMemo(() => ({
snapshotInfoUrl: snapshot?.url
}), [snapshot?.url]);
Also avoid state variables used only for calculations:
// Bad: Unnecessary state that causes rerenders
const [containerWidth, setContainerWidth] = React.useState(0);
// Good: Use ref or calculate directly if not needed for rendering
const containerRef = React.useRef();
Using !important in CSS declarations should be avoided as it makes styles difficult to override and maintain. Instead, use more specific selectors to achieve the desired styling hierarchy. This improves code maintainability and follows CSS best practices.
For example, instead of:
.monaco-workbench .part.editor > .content .gettingStartedContainer .test-banner {
background: linear-gradient(45deg, #ff6b6b, #4ecdc4) !important;
color: white !important;
}
Prefer using more specific selectors:
.monaco-workbench .part.editor > .content .gettingStartedContainer .test-banner.special-banner {
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
color: white;
}
This approach ensures styles can be more easily maintained, understood, and overridden when necessary without creating specificity wars in your stylesheets.
Documentation should include sufficient context, practical examples, and helpful hints to make it truly useful for developers. Avoid assuming users have background knowledge - explain concepts, provide examples, and mention related functionality.
Key practices:
:EditQuery <tab> completes injected language names”)Example of good contextual documentation:
:restart[!] [+cmd] *:restart*
Restart Nvim. This fails when changes have been made.
Use :confirm restart to override.
Examples:
:restart +PluginUpdate " Restart and run command
:confirm restart " Restart with change confirmation
This approach transforms documentation from mere reference material into genuinely helpful guidance that reduces the learning curve for users.
Only execute expensive operations when they are actually necessary. Avoid paying performance costs for functionality that may not be used or when conditions don’t require the expensive computation.
Key strategies:
Examples:
-- Bad: Always pay the fs_stat cost
local stat = vim.uv.fs_stat(f)
-- Good: Only pay the cost when needed
if follow_param then
local stat = vim.uv.fs_stat(f)
end
-- Bad: Eager loading causes performance hit
complete = vim.treesitter.language._complete,
-- Good: Lazy loading avoids eager initialization
complete = function(...) return vim.treesitter.language._complete(...) end,
-- Bad: Everyone pays the cost regardless of usage
vim.api.nvim_create_autocmd('DiagnosticChanged', {
callback = function() -- expensive string formatting end
})
-- Good: Only setup when default statusline is used
if using_default_statusline then
vim.api.nvim_create_autocmd('DiagnosticChanged', {
callback = function() -- expensive string formatting end
})
end
This approach prevents unnecessary performance overhead by ensuring expensive operations are only executed when their results will actually be used or when the conditions genuinely require them.
Use structured naming patterns and avoid polluting the global namespace when managing configuration variables. Prefer storing configuration state on relevant objects rather than creating numerous top-level global variables.
For naming patterns, use separators like “:” to distinguish variable components:
-- Good: structured naming with clear separation
local function get_client_augroup(client_id)
return 'nvim.lsp.linked_editing_range.client:' .. client_id
end
When dealing with client-specific or feature-specific configuration, consider storing the data directly on the relevant object instead of creating many global variables:
-- Instead of: many global variables like __lsp_feature_client_42_enabled
-- Prefer: storing on the client object itself
client._feature_enabled = true
For complex configuration hierarchies, use nested tables rather than flat naming schemes:
-- Good: organized structure
_lsp_enable = {
client = { [42] = true, [78] = true },
feature = { hover = true, completion = false }
}
-- Avoid: namespace pollution
-- __lsp_hover_client_42_enabled = true
-- __lsp_completion_client_78_enabled = false
This approach reduces global namespace pollution, improves code maintainability, and makes configuration relationships more explicit.
Avoid ambiguous or vague identifiers in favor of specific, self-documenting names that clearly convey purpose and context.
Names should be immediately understandable without requiring additional context or documentation. Generic terms like “float” should be replaced with specific terms like “floatwin” or “win_float” to eliminate ambiguity. Function names should clearly indicate their action and scope.
Examples of improvements:
parse_float_option() → win_float_parse_option() or parse_previewpopup_option()get_current_prompt() → prompt_gettext() or prompt_cur_input()"wintype" with value "cmdwin" instead of single-character codeswintype=="cmdwin" is clearer than checking strlen(wintype)==1This approach reduces cognitive load for developers, makes code more maintainable, and prevents confusion about identifier scope and purpose. When multiple similar functions exist, ensure names clearly distinguish their specific use cases rather than creating generic catch-all names.
Avoid repeatedly performing expensive operations like adding event handlers, loading resources, or fetching preferences. Instead, initialize these resources once when first needed and reuse them thereafter. This prevents memory leaks, reduces unnecessary work, and improves performance.
Key principles:
Example of problematic code:
openTabsPopup(event) {
// BAD: Adds new event handler every time popup opens
search.addEventListener('input', () => {
// handler logic
});
// BAD: Fetches preference on every call
if(Services.prefs.getBoolPref("zen.some-pref", false)) {
// logic
}
}
Better approach:
constructor() {
// Initialize event handlers once during setup
this.#setupEventHandlers();
// Setup lazy preference observer
this.#setupPrefObserver();
}
loadResourcesOnDemand() {
if (!this.#resourcesLoaded) {
Services.scriptloader.loadSubScript("chrome://browser/content/resource.mjs", this);
this.#resourcesLoaded = true;
}
}
When writing tree-sitter queries, prioritize performance by choosing efficient predicates and avoiding computationally expensive operations. Use #any-of? instead of complex #match? patterns when checking against multiple literal values, as it reduces regex compilation overhead. Avoid predicates like #has-ancestor? which have poor performance characteristics due to unbounded tree traversal. Consider the computational complexity of your queries, especially for features that run frequently like syntax highlighting during scrolling.
Example of optimization:
; Instead of expensive regex matching:
((identifier) @variable.builtin
(#match? @variable.builtin "^(this|msg|block|tx)$"))
; Use efficient literal matching:
((identifier) @variable.builtin
(#any-of? @variable.builtin "this" "msg" "block" "tx"))
For performance-critical features, ensure optimized builds are used and consider caching strategies when queries involve expensive calculations that run repeatedly during user interactions.
Define shared dependencies at the workspace level in the root Cargo.toml to ensure version consistency and prevent conflicts across the project. This approach centralizes dependency management and makes it easier to maintain uniform versions throughout the codebase.
When multiple crates in your workspace use the same dependency, declare it in the workspace dependencies section and reference it from individual crates. This prevents version mismatches and reduces the risk of using unmaintained or conflicting dependency versions.
Example:
# Root Cargo.toml
[workspace.dependencies]
toml = "0.9.2"
toml_edit = "0.23.1"
dirs = "2.0" # Use consistent version across workspace
# Individual crate Cargo.toml
[dependencies]
toml = { workspace = true }
dirs = { workspace = true }
This practice is especially important when dealing with dependencies that have breaking changes between major versions or when some dependencies are unmaintained and you need to stick with specific stable versions across your entire workspace.
When documenting network connection operations, clearly specify the scope of when operations are supported and their limitations. Include information about initial connection requirements, fallback behaviors, and unsupported scenarios to help users understand operational boundaries.
For connection management commands, document:
| Fallback behaviors (e.g., “this command is equivalent to | :detach | ”) |
Example:
:connect {address}
Detaches the UI from the server it is currently attached to
and attaches it to the server at {address} instead.
Note: If the current UI hasn't implemented the "connect" UI
event, this command is equivalent to |:detach|.
This prevents user confusion and sets proper expectations about connection operation capabilities and constraints.
Choose algorithms and data structures that provide both deterministic behavior and optimal performance characteristics. Prefer ordered collections when iteration order matters, optimize pattern matching to avoid expensive operations, and be mindful of algorithmic complexity.
Key principles:
std::set instead of unsorted_set, ImmutableListMultimap instead of custom maps) to ensure consistent outputindexOf) over regex patterns for simple substring matchingExample optimization:
// Instead of complex regex for simple suffix matching
if (LITERAL_PATTERN_WITH_DOT_UNESCAPED.matcher(suffixPattern).matches()) {
String literalSuffix = suffixPattern.replace("\\.", ".");
return s -> s.endsWith(literalSuffix); // Much faster than regex
}
// Use ordered collections for deterministic behavior
ImmutableListMultimap<Label, SpawnStrategy> platformToStrategies; // Preserves order
// Instead of: Map<Label, List<SpawnStrategy>>
This approach ensures both correctness through deterministic behavior and performance through algorithmic efficiency.
Use consistent naming patterns that reflect the semantic role of identifiers:
const MAX_RETRY_COUNT = 3;
const API_BASE_URL = "https://api.example.com";
struct UserProfile { }
class DatabaseConnection { }
fn calculateTotal() { }
fn validateUserInput() { }
struct Widget {
m_width: i32,
m_height: i32
}
This pattern makes code more readable by allowing quick visual identification of an identifier’s role. It also helps catch semantic errors where identifiers might be used incorrectly (e.g., using a type name where a function was intended).
Choose variable, function, and struct names that clearly communicate their purpose and content while considering their surrounding context. Avoid generic names like x, normal, or data that provide no semantic meaning. When naming within a specific scope or module, avoid redundant prefixes that repeat the context.
Bad examples:
// Generic, meaningless names
let x = error_result;
let normal = should_use_standard_input;
let first_line = column_count; // Misleading content
// Redundant context
struct WindowConfig {
pub window_level: WindowLevel, // "window" is redundant
}
// Implementation-focused naming
pub fn try_from_textual(&self) -> Option<SequenceBase> // Doesn't return Self
Good examples:
// Descriptive, purpose-driven names
let err = error_result;
let use_standard_input = should_use_standard_input;
let column_count = first_line_columns;
// Context-aware naming
struct WindowConfig {
pub level: WindowLevel, // Context is clear from struct name
}
// Semantic naming
pub fn try_build_textual(&self) -> Option<SequenceBase> // Clear about what it builds
Consider the scope and context when naming - a variable named level inside a WindowConfig is clearer than window_level. Use domain-specific terminology that your team understands, and prefer full words over abbreviations unless the abbreviation is universally recognized in your domain (like fd for file descriptor).
Eliminate unnecessary operations and choose appropriate data structures to improve algorithmic efficiency. Look for opportunities to remove redundant computations, avoid unnecessary allocations, and leverage built-in methods instead of manual implementations.
Key areas to focus on:
saturating_sub when the subtraction cannot underflow:
```rust
// Instead of this when bounds are guaranteed:
let middle_lines = total_lines.saturating_sub(1);// Use this: let middle_lines = total_lines - 1;
2. **Use built-in iterator methods** instead of manual iteration:
```rust
// Instead of manual zip:
for (p1, p2) in iter::zip(f_x, g_x) {
// Use built-in zip:
for (p1, p2) in f_x.zip(g_x) {
// Consider fixed-size alternatives when applicable
4. **Avoid duplicate iterations** by combining operations or using more efficient algorithms:
```rust
// Instead of iterating twice to find byte and char indices:
if let Some(mut index) = self.state.find("://") {
for (char_index, (byte_index, _)) in self.state.char_indices().enumerate() {
if byte_index == index { index = char_index; break; }
}
// Use char_indices directly with appropriate logic
// Use simplified form: 1_000_000_000 / 60_000
6. **Optimize conditional logic** by restructuring boolean expressions for better performance and clarity:
```rust
// Instead of:
if uniq_hyperlinks.contains(&hyperlink) {
return None;
}
uniq_hyperlinks.insert(hyperlink.clone());
Some((cell, hyperlink))
// Use:
if !uniq_hyperlinks.contains(&hyperlink) {
uniq_hyperlinks.insert(hyperlink.clone());
Some((cell, hyperlink))
} else {
None
}
These optimizations improve both performance and code maintainability while reducing the likelihood of algorithmic inefficiencies.
Always handle errors specifically and explicitly, avoiding generic catch blocks that mask or ignore errors. Ensure proper resource cleanup and consistent error propagation. Key practices:
Example of proper error handling:
private async getWorktreesFS(): Promise<Worktree[]> {
const worktreesPath = path.join(this.repositoryRoot, '.git', 'worktrees');
try {
const raw = await fs.readdir(worktreesPath);
// ... processing ...
} catch (err) {
// Handle specific error condition
if (/ENOENT/.test(err.message)) {
return [];
}
// Propagate unexpected errors
throw err;
} finally {
// Clean up resources
this.disposables.dispose();
}
}
Bad practice to avoid:
try {
// ... operations ...
} catch (err) {
// DON'T: Silently swallow errors
}
Choose names that reflect the semantic purpose and meaning rather than implementation details or internal mechanisms. Names should communicate what something does or represents from the user’s perspective, not how it works internally.
For example, prefer on_response over on_exit for HTTP request callbacks, since “response” describes the semantic event while “exit” exposes the internal detail that curl process exits. Similarly, use version to describe the semantic concept rather than checkout which exposes the Git implementation detail.
Follow established project conventions consistently:
on_ prefix for event-handling callbacks and handlerscallback for continuation functions (single callback parameter)Example of good semantic naming:
-- Good: describes the semantic purpose
vim.net.request(url, opts, on_response)
-- Poor: exposes implementation detail
vim.net.request(url, opts, on_exit)
When multiple naming options exist, prioritize the one that best communicates the intended use and meaning to other developers, while maintaining consistency with existing codebase patterns.
When implementing custom network protocol behavior, ensure that modifications are properly scoped to only the intended protocol types and include upstream context documentation. Avoid applying protocol-specific changes broadly across all network protocols, as this can break assumptions and cause unintended side effects.
Key principles:
Example from streaming protocol handling:
// Good: Scoped to streaming custom protocols only
if (IsStreamingCustomProtocol(url)) {
destination_url_data->set_range_supported();
}
// Avoid: Broad application that could break other protocols
destination_url_data->set_range_supported(); // Applied to all protocols
When modifying network service initialization, ensure proper guards are in place:
SystemNetworkContextManager* SystemNetworkContextManager::GetInstance() {
if (!g_system_network_context_manager) {
content::GetNetworkService();
DCHECK(g_system_network_context_manager);
}
return g_system_network_context_manager;
}
This approach prevents breaking buffering assumptions for protocols like file:// URLs while enabling the required functionality for custom streaming protocols that support range requests.
Perform lightweight validation checks before executing expensive operations to avoid unnecessary resource consumption. This is especially important in hot paths or frequently called functions.
Key practices:
Example - Before:
async function getWorktrees(): Promise<Worktree[]> {
// Spawns process on hot path
const result = await spawn('git', ['worktree', 'list']);
return parseWorktrees(result);
}
After:
async function getWorktrees(): Promise<Worktree[]> {
// Use fs operations first
const hasWorktrees = await fs.exists('.git/worktrees');
if (!hasWorktrees) {
return [];
}
// Only spawn process if needed
const result = await spawn('git', ['worktree', 'list']);
return parseWorktrees(result);
}
Guard against reentrancy issues when operations may trigger autocommands or async events that could invalidate state or cause recursive execution. Check for existing execution context before proceeding and validate that pointers/state remain valid after operations that may trigger autocommands.
Key practices:
win_new_tabpage() or win_set_buf(), verify that pointers and handles are still valid before using themmultiqueue_put() to schedule on appropriate event loops rather than blockingExample from the codebase:
// Check for reentrancy before proceeding
if (in_filetype_autocmd()) {
api_set_error(err, kErrorTypeException,
"Cannot detect default while FileType autocommands are running");
return;
}
// After operations that trigger autocommands, validate state
tabpage_T *tp = win_new_tabpage(after, buf->b_ffname, enter);
if (!tp) {
// tp may have been freed by autocommands
api_set_error(err, kErrorTypeException, "Failed to create tabpage");
return 0;
}
// Validate tp->tp_firstwin is still valid before using
This prevents race conditions where autocommands modify global state during API operations, leading to crashes or data corruption.
Error messages should be user-friendly, readable, and provide actionable guidance for resolution. Avoid exposing technical implementation details like raw dictionaries, regex patterns, or internal data structures to end users. Instead, format errors clearly and include specific steps users can take to resolve the issue.
When validation fails or errors occur, provide context about what went wrong and suggest concrete next steps. For example, instead of showing raw validation output like {'errors': ['project.name must match pattern ^([a-zA-Z\\d]|[a-zA-Z\\d][\\w.-]*[a-zA-Z\\d])$']}, format it as:
# Bad - exposes technical details
self.line_error(f"<error>Validation failed: {validation_results}</error>")
# Good - clear and actionable
self.line_error(
"<error>"
"Error: poetry.lock is not consistent with pyproject.toml. "
"Run `poetry lock [--no-update]` to fix it."
"</error>"
)
Consider your audience - error messages should be understandable by developers of all experience levels. When technical details are necessary, provide them in debug/verbose modes while keeping the default error message focused on what the user needs to do to resolve the issue.
Always use Zig’s if-unwrap pattern (if (optional) |value| {...}) when working with optional values instead of forced unwrapping with .?. This pattern is safer as it avoids runtime panics, more readable, and aligns with Zig’s idioms for null safety.
When checking an optional only to see if it’s not null and discarding the value, use != null instead of additional syntax. When you need to use the value, use the if-unwrap pattern to create a new non-optional variable in a limited scope:
// Bad - prone to crashes if null
if (self.current_background_image != null) {
switch (self.current_background_image.?) {
.ready => {},
// ...
}
}
// Good - compiler enforced null safety
if (self.current_background_image) |current_background_image| {
switch (current_background_image) {
.ready => {},
// ...
}
}
// Bad - will crash if background-image is null
const background_image = try config.@"background-image".?.clone(alloc);
// Good - handles null case explicitly
const background_image = if (config.@"background-image") |v| try v.clone(alloc) else null;
// Alternative approach - early return
const current_background_image = self.current_background_image orelse return;
// Now use current_background_image without unwrapping
This approach not only prevents runtime crashes but also makes the code’s intent clearer and leverages the compiler’s ability to enforce null safety.
When capturing objects in callbacks or lambdas that may execute asynchronously, use weak pointers instead of raw pointers or shared pointers to prevent use-after-free bugs. Always validate the weak pointer before dereferencing it, and avoid redundant lock() calls on the same weak pointer.
This pattern is essential for thread safety when objects may be destroyed while callbacks are still pending execution. The weak pointer allows the callback to safely check if the object still exists before attempting to use it.
Example of proper weak pointer usage in callbacks:
// Good: Use weak pointer and validate before use
auto weakBuffer = WP<IHLBuffer>(PBUFFER);
PBUFFER->onBackendRelease([weakBuffer]() {
if (auto buffer = weakBuffer.lock())
buffer->unlock();
});
// Avoid: Redundant lock() calls in comparisons
if (weakPtr1.lock() == weakPtr2.lock()) // redundant double .lock()
// Better: Store locked pointers if comparing multiple times
auto ptr1 = weakPtr1.lock();
auto ptr2 = weakPtr2.lock();
if (ptr1 == ptr2)
This approach prevents crashes when the referenced object is destroyed before the callback executes, which is common in asynchronous systems with complex object lifetimes.
Avoid using the condition and expr1 or expr2 pattern when expr1 can be nil or false, as this will always return expr2 regardless of the condition result. This is a common source of subtle bugs in Lua code.
The pattern condition and expr1 or expr2 only works correctly when expr1 is guaranteed to be truthy. When expr1 can be nil or false, the or expr2 part will always execute, making the condition meaningless.
Problematic examples:
-- This will always return `enable`, never `nil`
vim.b[bufnr][var] = enable == vim.g[var] and nil or enable
-- This fails when enable is false
bufstate.enabled = enable ~= globalstate.enabled and enable or nil
Safe alternatives:
-- Use explicit if-else
if enable == vim.g[var] then
vim.b[bufnr][var] = nil
else
vim.b[bufnr][var] = enable
end
-- Use vim.F.if_nil for nil-specific cases
result = vim.F.if_nil(potentially_nil_value, fallback)
This pattern is particularly dangerous because it appears to work correctly in many cases, making the bug difficult to detect during testing.
Always verify that test commands documented in project guides work exactly as written. Test commands should be copy-paste executable without modification. When adding or updating test command examples in documentation:
Example:
# ✅ GOOD: Complete, verified command
cargo coverage -- --open # Runs tests with coverage and opens the report
# ❌ BAD: Incorrect command syntax
cargo run --bin coverage -- --open # May not work in all environments
For integration tests that target specific files or tests:
# ✅ GOOD: Correctly specifies how to run a specific test
pnpm --filter turborepo-tests-integration test tests/turbo-help.t
# ❌ BAD: Incorrect or platform-dependent command
pnpm test:interactive -F turborepo-tests-integration -- run-summary.t
This practice ensures developers can efficiently run tests without debugging documentation issues first.
When documenting configuration options in changelogs, README files, or other user-facing documentation, focus on specific implementation details and user-actionable information rather than vague feature descriptions. Write from the user’s perspective, specifying exact configuration keys, values, and behaviors.
Key principles:
Examples:
/etc/alacritty/alacritty.toml for system wide configuration”Write: “Add /etc/alacritty/alacritty.toml fallback for system wide configuration”
~/.hushlogin file”Write: “Pass -q to login on macOS if ~/.hushlogin is present”
window.level = "AlwaysOnTop" to force Alacritty to always be the toplevel window”Remember: “We don’t document things for developers, we document them for users.” Configuration documentation should help users understand exactly what to configure and what behavior to expect.
When implementing SSH integration in your application, follow these practices to ensure reliability across different systems:
# AVOID: Only capturing hostname
ssh_hostname="$(ssh -G "$@" | grep hostname | cut -d' ' -f2)"
# BETTER: Capture full user@host target
ssh_config=$(ssh -G "$@" 2>/dev/null)
while IFS=' ' read -r key value; do
case "$key" in
user) ssh_user="$value" ;;
hostname) ssh_hostname="$value" ;;
esac
done < <(ssh -G "$@" 2>/dev/null)
ssh_target="${ssh_user}@${ssh_hostname}"
# AVOID: Modifying and restoring environment
export TERM="$ssh_term_override"
command ssh "${ssh_opts[@]}" "$@"
export TERM="$original_term"
# BETTER: Override at command level
command TERM="$ssh_term_override" ssh "${ssh_opts[@]}" "$@"
# Local check (infocmp needed locally)
if ! command -v infocmp >/dev/null 2>&1; then
echo "Warning: infocmp command not available locally for terminfo export." >&2
return 1
fi
# Remote check (tic needed remotely)
if ! ssh "$host" "command -v tic >/dev/null 2>&1"; then
echo "Warning: tic command not available on remote host for terminfo installation." >&2
return 1
fi
# AVOID: Redundant commands
ssh "$host" 'mkdir -p ~/.terminfo/x 2>/dev/null && tic -x -o ~/.terminfo /dev/stdin'
# BETTER: Let tic handle directory creation
ssh "$host" 'tic -x - 2>/dev/null'
APIs should follow documented conventions and established patterns within the codebase to ensure consistency and predictability. This includes adhering to naming conventions, parameter structures, and interface designs that users already expect.
Key patterns to follow:
enable(boolean) pattern instead of separate start() and stop() functions:help dev-patterns and :help dev-namingExample of inconsistent API:
-- Inconsistent - uses start/stop pattern
vim.lsp.on_type_formatting.start(bufnr, client_id)
vim.lsp.on_type_formatting.stop(bufnr, client_id)
-- Inconsistent - individual parameters
enable(enable, bufnr, client_id)
Example of consistent API following established patterns:
-- Consistent - follows enable(boolean) pattern like other LSP features
vim.lsp.on_type_formatting.enable(true, {bufnr = bufnr, client_id = client_id})
-- Consistent - uses filter kwargs like other APIs
vim.lsp.linked_editing_range.enable(true, {bufnr = bufnr, client_id = client_id})
This consistency reduces cognitive load for users who can predict API behavior based on established patterns, and makes the codebase easier to maintain by following uniform conventions.
When working with Turborepo, be aware of implicit configurations and special files that affect behavior even when not explicitly configured. For example, turbo.json and package.json are always considered inputs when determining if a package has changed, even if you try to explicitly ignore them. Package manager lockfiles are also always parsed and included in task hashes.
When setting up framework integrations in library packages, use peerDependencies in your package.json to make framework APIs available without direct installation:
{
"name": "@repo/ui",
"peerDependencies": {
"next": ">=15"
}
}
Note that for older package managers, you may need to configure them to install peer dependencies or add the dependency to devDependencies as a workaround.
For repositories without a packageManager field, you can use --dangerously-disable-package-manager-check or set dangerouslyDisablePackageManagerCheck: true in turbo.json to bypass lockfile validation, but be aware this can lead to unpredictable behavior as Turborepo will attempt to discover the package manager through best-effort methods.
Prioritize algorithmic efficiency and avoid unnecessary computational overhead in performance-critical code paths. Look for opportunities to reduce time complexity and eliminate redundant calculations.
Key optimization strategies:
prefer distanceSq over distance() for performance-critical geometric calculationsstd::erase_if directly instead of the std::ranges::remove_if + erase pattern when possibleExample from distance calculations:
// Instead of:
if (m_vBeginDragXY.distance(mousePos) <= *PDRAGTHRESHOLD)
// Use:
if (m_vBeginDragXY.distanceSq(mousePos) <= (*PDRAGTHRESHOLD * *PDRAGTHRESHOLD))
Example from workspace checking:
// Instead of checking all workspaces against all rules O(n*m):
for (auto& workspace : workspaces) {
for (auto& rule : rules) { /* check */ }
}
// Optimize to O(n) by checking only the changed workspace:
recheckPersistent(); // Only checks current workspace against rules
This approach reduces CPU cycles in frequently called functions and improves overall application responsiveness.
Choose efficient comparison patterns and algorithms based on the data type and use case. Key guidelines:
// Efficient if [[ “$FEATURES” == ssh-env ]]
2. For floating-point comparisons, use epsilon-based or range checks:
```zig
// Incorrect
if (opacity == 1.0)
// Correct
const epsilon = 1e-6;
if (@fabs(opacity - 1.0) < epsilon)
// Cleaner and more efficient return version.order(required) != .lt;
These patterns improve both code reliability and performance by using more appropriate comparison techniques for each data type.
---
## reuse concurrency infrastructure
<!-- source: neovim/neovim | topic: Concurrency | language: Other | updated: 2025-07-06 -->
Avoid implementing custom concurrency patterns when existing infrastructure is available. Before creating new debouncing, async/await, or parallel execution code, check if suitable implementations already exist in the codebase.
For example, instead of implementing a custom debounce function:
```lua
local function debunce(f, timeout)
local timer = nil
return function(...)
local args = { ... }
if timer then
vim.uv.timer_stop(timer)
timer:close()
timer = nil
end
timer = assert(vim.uv.new_timer())
vim.uv.timer_start(timer, timeout, 0, vim.schedule_wrap(function()
if timer then
vim.uv.timer_stop(timer)
timer:close()
timer = nil
end
f(unpack(args))
end))
end
end
Reuse existing debouncing infrastructure like next_debounce in lsp/_changetracking.lua. Similarly, prefer established async patterns like vim.async.await(3, vim.system, cmd, opts) over manual coroutine implementations.
This reduces code duplication, ensures consistent behavior across the codebase, and leverages battle-tested concurrency primitives that handle edge cases and performance optimizations.
Design scripts to be easily integrated into build pipelines and CI/CD workflows by using standard I/O streams instead of hardcoded file paths. Scripts that read from stdin and write to stdout can be easily composed in pipelines, redirected, and incorporated into various build systems without modification.
Example - Before:
if __name__ == "__main__":
project_root = Path(__file__).resolve().parents[2]
patcher_path = project_root / "vendor" / "nerd-fonts" / "font-patcher.py"
source = patcher_path.read_text(encoding="utf-8")
patch_set = extract_patch_set_values(source)
out_path = project_root / "src" / "font" / "nerd_font_attributes.zig"
# Write results to out_path
Example - After:
import sys
if __name__ == "__main__":
# Read from stdin if no arguments provided
if len(sys.argv) > 1:
with open(sys.argv[1], "r", encoding="utf-8") as f:
source = f.read()
else:
source = sys.stdin.read()
patch_set = extract_patch_set_values(source)
# Write results to stdout
print(generate_zig_output(patch_set))
This approach allows the script to be used in various CI contexts: cat input.txt | python script.py > output.zig or as part of more complex build rules without requiring code changes.
API documentation must use specific, well-defined types instead of generic ones, and clearly define behavior for all scenarios including edge cases. When documenting return types, use explicit union types or named type aliases rather than generic strings. For complex APIs with multiple options, document the interaction between different parameters and their expected behavior.
For example, instead of:
- returns: <[string]>
Use specific union types:
- returns: <["log"|"debug"|"info"|"error"|"warning"|"dir"|"dirxml"|"table"|"trace"|"clear"|"startGroup"|"startGroupCollapsed"|"endGroup"|"assert"|"profile"|"profileEnd"|"count"|"timeEnd"]>
Or better yet, use named types:
- returns: <[ConsoleMessageType]>
Additionally, when introducing new API options, clearly document their behavior in all scenarios, especially when combined with other options or in edge cases. This prevents ambiguity and improves developer experience by making API contracts explicit and predictable.
Use descriptive, consistent naming that follows language and platform conventions. Choose names that clearly communicate purpose and context, and maintain consistency across similar elements.
For variables:
pub fn waitXev(
For APIs and actions:
Choose names that balance brevity with clarity, and consider how names will be interpreted by other developers.
When designing APIs that may need additional parameters in the future, use objects instead of individual parameters to enable extension without breaking changes. This approach allows new properties to be added while maintaining backward compatibility.
Instead of adding individual parameters that create rigid function signatures:
// Avoid: Hard to extend without breaking changes
win.setVibrancy(type, animate, animationDuration)
Use an options object that can accommodate future parameters:
// Preferred: Extensible design
win.setVibrancy(type, {
animate: boolean,
animationDuration: number
// Future properties can be added here
})
For events, group related parameters into a details object rather than individual parameters:
// Avoid: Individual parameters
app.on('notification-activation', (event, appUserModelId, invokedArgs, dataCount, inputData) => {})
// Preferred: Details object
app.on('notification-activation', (event, details) => {
// details.appUserModelId, details.invokedArgs, etc.
})
This pattern is especially important for APIs that interact with evolving web standards or platform capabilities, where new options frequently become available. Consider how Chrome extension APIs and DOM APIs use this pattern successfully - they can add new properties without breaking existing code that only uses a subset of the available options.
When functions may not return valid values, use std::optional or absl::optional instead of raw types that could represent invalid states. Always check the validity of optional values before accessing them to prevent null pointer dereferences and invalid value usage.
For functions that might fail or return invalid data, prefer optional return types:
// Instead of returning 0 or invalid values on failure
std::optional<DWORD> GetAccentColor() {
// ... implementation that may fail
if (RegOpenKeyEx(...) != ERROR_SUCCESS) {
return std::nullopt; // Explicit failure indication
}
return accent_color;
}
// Always check validity before use
std::optional<DWORD> system_accent_color = GetAccentColor();
if (system_accent_color.has_value()) {
border_color = RGB(GetRValue(system_accent_color.value()),
GetGValue(system_accent_color.value()),
GetBValue(system_accent_color.value()));
} else {
should_apply_accent = false;
}
For pointer returns, check for null before dereferencing:
auto* contents = electron::api::WebContents::From(web_contents);
return contents ? contents->ID() : -1;
// For optional pointers, use both checks
if (frame && frame.value()) {
auto* frame_rfh = frame->render_frame_host();
auto* rfh = frame_rfh ? frame_rfh->GetOutermostMainFrameOrEmbedder() : nullptr;
if (rfh) {
// Safe to use rfh
}
}
This pattern prevents crashes from accessing invalid pointers or using sentinel values that could lead to unexpected behavior. Note that base::Optional has been deprecated in favor of absl::optional in newer codebases.
Names should be descriptive and consistent with existing patterns in the codebase. This applies to methods, variables, and DSL elements:
# Good: Follows pattern of post_install_defined?, resource_defined?
def livecheck_defined?
method(:livecheck).owner != Formula
end
# Bad: Inconsistent with existing pattern
def has_livecheck?
method(:livecheck).owner != Formula
end
# Good: Clear what the variable contains
basename = File.basename(path, ".*")
match_github = url.match(%r{github\.com/(?<user>\S+)/(?<repo>\S+)})
# Bad: Unclear or ambiguous names
m = url.match(%r{github\.com/(?<user>\S+)/(?<repo>\S+)})
filename = File.basename(path, ".*") # When actually storing basename
# Good: Clear boolean nature and what's being checked
def binary_linked_to_library?(binary, library)
# Bad: Unclear if returns boolean
def check_binary_linkage(binary, library)
Documentation must precisely reflect the current codebase implementation. When documenting features, options, or APIs:
- Package manager lockfile content, e.g. `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` or `bun.lockb`.
+ Package manager lockfile content, e.g. `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lock`, or `bun.lockb`.
- The value can also be an [options object] passed to `https.createServer()`.
+ The value is an [options object] passed to `https.createServer()`.
interface ModuleRunnerOptions {
/**
* Root of the project
+ * @deprecated not used anymore and to be removed
*/
- root: string
+ root?: string
}
Choose names that are both semantically accurate and consistent with established patterns. Names should clearly convey their purpose, data type, and behavior while following existing conventions in the codebase and upstream dependencies.
Key principles:
CheckSwitchNameValid returning an error message vs IsSwitchNameValid returning boolean)reasons for a vector, not reason)Example:
// Better: Descriptive and indicates return type
std::optional<std::string_view> CheckSwitchNameValid(std::string_view key) {
if (!std::ranges::none_of(key, absl::ascii_isupper))
return "Switch name must be lowercase";
return {};
}
// Better: Plural name for collection parameter
void OnWindowEndSession(const std::vector<std::string> reasons) {
// ...
}
Establish secure default configurations in project metadata files to prevent accidental publishing and ensure proper version constraints. This is particularly important for private packages and build system configurations.
Key practices:
[project]
classifiers = [
"Private :: Do Not Upload",
# Other classifiers...
]
[build-system]
# Prefer narrow version ranges for build backends
requires = ["uv>=0.4.18,<0.5"]
This approach helps prevent accidental package uploads to public repositories and ensures reproducible builds through proper version constraints.
Configure dependencies with their minimum necessary scope to maintain clean architecture and improve build times. Key practices:
#[cfg(test)] annotations:
// Instead of adding to main Cargo.toml
// unicode-width = "0.2"
// Add to [dev-dependencies] section instead
// And restrict usage to test code:
#[cfg(test)]
use unicode_width::UnicodeWidthStr;
// Instead of this in util/Cargo.toml:
// schemars.workspace = true
// Create plain enums in util:
pub enum SortStrategy {
Lexicographical,
Alphabetical,
}
// Then convert in settings module where JsonSchema is available
# In workspace Cargo.toml:
tokio = { version = "1.0", features = ["rt", "rt-multi-thread"] }
# In module Cargo.toml:
tokio.workspace = true
Identify and eliminate duplicate computations, unnecessary object creation, and redundant function calls to improve performance. This is especially critical in memory-sensitive areas and frequently executed code paths.
Key practices:
Example from codebase:
// Before: Redundant calls
const isVisible1 = isElementVisible(element);
const isVisible2 = isElementVisible(element); // Same element, duplicate call
// After: Cache the result
const isVisible = isElementVisible(element);
// Use 'isVisible' variable in both places
// Before: Creating new array
return annotations.map(annotation => ({ ...annotation, location: absolutePath }));
// After: Modify in place when safe
annotations.forEach(annotation => annotation.location = absolutePath);
return annotations;
This optimization becomes increasingly important in hot code paths, loops, and memory-constrained environments where even small inefficiencies can compound into significant performance impacts.
Documentation should be formatted to optimize readability and information retention. Apply these principles to make documentation more user-friendly:
Place explanatory text close to related code examples, avoiding isolated sentences that break the flow of information.
Use text formatting (especially bold) to highlight key terms and important concepts that readers might need when skimming the document.
Structure information logically, with explanations preceding code examples when they provide context for understanding the example.
Example of good formatting:
Add a line to the CODEOWNERS file (where `xx_YY` is your locale):
```diff
# Localization
/po/README_TRANSLATORS.md @ghostty-org/localization
/po/com.mitchellh.ghostty.pot @ghostty-org/localization
/po/zh_CN.UTF-8.po @ghostty-org/zh_CN
+/po/xx_YY.UTF-8.po @ghostty-org/xx_YY
This standard helps documentation serve both careful readers and those quickly scanning for specific information.
---
## API extensibility parameters
<!-- source: neovim/neovim | topic: API | language: C | updated: 2025-07-04 -->
Always design API functions with extensible parameter structures to accommodate future feature expansion without breaking changes. Use `Dict opts` parameters instead of individual boolean or primitive parameters, unless you are absolutely certain no expansion will ever be needed (which is usually wrong).
This approach prevents the need for API versioning or breaking changes when new functionality is added. Even if the initial implementation doesn't use all possible options, the extensible structure allows for seamless feature additions.
Example of preferred API design:
```c
// Good: Extensible with opts parameter
Tabpage nvim_open_tabpage(Buffer buffer, Boolean enter, Dict opts, Error *err)
// Avoid: Fixed parameters that may need expansion later
Tabpage nvim_open_tabpage(Buffer buffer, Boolean enter, Error *err)
The opts dictionary can initially be empty or contain basic options, but provides a clear path for adding features like positioning (after parameter mirroring [count]tabnew), styling options, or behavioral flags without requiring new API endpoints or breaking existing client code.
This principle applies even when the API seems simple initially - consider future use cases like custom commands (:restart +qall) or additional configuration options that users might request.
Documentation should use appropriate linking strategies to ensure content remains accessible and navigable across all deployment environments:
Use absolute URLs for repository links: When referencing files within the codebase (like READMEs or source files), always use absolute GitHub URLs instead of relative paths that may break when documentation is deployed to external sites.
<!-- Incorrect -->
Follow the steps in the [collab README](../../../crates/collab/README.md)
<!-- Correct -->
Follow the steps in the [collab README](https://github.com/organization/repo/blob/main/crates/collab/README.md)
Implement cross-references between related documentation: When functionality is documented across multiple locations, add cross-references to help users find all relevant information. This is particularly important for features that have both configuration and usage instructions in different sections.
Test links in the deployed environment: Verify that all documentation links work correctly not just in the source repository, but also in the final deployed documentation site.
Following these practices ensures documentation remains navigable and useful regardless of where or how users access it.
Always use mktemp instead of manually constructing temporary file paths with random values. Manually constructed paths with elements like $RANDOM or timestamp values can be vulnerable to race conditions, predictability issues, and permission problems, potentially leading to security exploits.
Instead of:
cpath="/tmp/ghostty-ssh-$USER-$RANDOM-$(date +%s)"
Use:
cpath=$(mktemp -d /tmp/ghostty-ssh-XXXXXX)
# or for a file
cpath=$(mktemp /tmp/ghostty-ssh-XXXXXX)
The mktemp utility creates unique temporary files/directories safely, sets appropriate permissions, and handles race conditions properly. This prevents potential security vulnerabilities like file-based race conditions, symbolic link attacks, and information disclosure that could occur with manually constructed paths.
Use Rust’s Option type and its methods effectively to handle nullable values. This improves code clarity and safety by making null cases explicit and leveraging the type system.
Key practices:
Example - Before:
// Using tuple return
fn is_pragma_comment(comment: &str) -> (bool, usize) {
// Returns (is_pragma, offset)
if comment.contains("pragma") {
(true, comment.find("pragma").unwrap_or(0))
} else {
(false, 0)
}
}
After:
// Using Option for clearer semantics
fn is_pragma_comment(comment: &str) -> Option<usize> {
// Returns offset if comment is pragma, None otherwise
comment.contains("pragma").then(|| {
comment.find("pragma").expect("pragma exists")
})
}
// Usage with appropriate Option methods
let offset = is_pragma_comment(comment)
.unwrap_or_default(); // Use default when None
This approach:
Design API parameters to be self-documenting and minimize cognitive overhead. Avoid boolean parameters in favor of descriptive enums or string literals, leverage type inference where possible, and prefer clean parameter passing over state mutation patterns.
Key principles:
Example of boolean parameter improvement:
// Instead of:
async function processSnapshot(updateIndex: boolean) {
// unclear what true/false means
}
// Use descriptive options:
async function processSnapshot(indexBehavior: 'updateAnonymousSnapshotIndex' | 'dontUpdateAnonymousSnapshotIndex') {
// behavior is immediately clear
}
Example of parameter inference:
// Instead of requiring explicit contentType:
await testInfo.attach('report.html', {
path: attachmentFile,
contentType: 'text/html' // redundant
});
// Infer from file extension:
await testInfo.attach('report.html', {
path: attachmentFile // contentType inferred from .html extension
});
This approach reduces API surface area, prevents misuse, and makes code more maintainable by encoding intent directly in the parameter names and types.
When implementing algorithms or data structures, carefully evaluate the tradeoffs between computational complexity, memory usage, and code maintainability. Consider:
For example, when choosing between different implementations:
// Less efficient but simpler and more maintainable
match to_remove[..] {
[] => self.elements.push(to_add),
[index] => self.elements[index] = to_add,
_ => {
// Simple but potentially slower approach
for index in to_remove.into_iter().rev() {
self.elements.swap_remove(index);
}
self.elements.push(to_add);
}
}
// More efficient but harder to understand
if let Some((&first, rest)) = to_remove.split_first() {
self.elements[first] = to_add;
// Complex optimization logic...
}
Choose the simpler implementation unless profiling shows that the optimization provides meaningful benefits for your use case. Document the rationale for choosing more complex implementations when necessary.
Documentation should clearly explain the purpose, behavior, and relationships between code components using accessible terminology. This helps other developers understand the code without needing to dig into implementations.
Key practices:
Example of improved documentation:
/// A tuple length specification.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum TupleLength {
/// A tuple with exactly `n` elements
Fixed(usize),
/// A variable-length tuple with `prefix_len` required elements at the start
/// and `suffix_len` required elements at the end
Variable(usize, usize),
}
/// Return true if this is a type that is always fully static (has no dynamic part;
/// represents a single set of possible values.)
///
/// Note: This function may have false negatives (return false for some static types),
/// but should not have false positives (will never return true for non-static types).
fn is_fully_static(&self) -> bool {
// implementation...
}
When documenting methods that may panic or fail under certain conditions, clearly state these conditions:
/// Get the AST node for this class.
///
/// # Panics
/// Panics if the provided module belongs to a different file than this class.
fn node<'ast>(self, db: &'db dyn Db, module: &'ast ParsedModuleRef) -> &'ast ast::StmtClassDef {
// implementation...
}
Comprehensive documentation reduces the learning curve for new contributors and helps prevent bugs caused by misunderstandings about component behavior.
Before implementing data structures or algorithms, analyze allocation patterns and optimize for common cases. Key strategies:
// After pub const fn all() -> [&’static str; 15] { [“namespace”, “class”, …] }
2. Leverage specialized data structures to avoid allocations:
- Use `hashbrown::HashMap` with `entry_ref` for string keys
- Consider `smallvec` for collections that are usually small
- Keep allocations behind `Arc` when possible
3. Profile before optimizing:
- Measure binary size impact of changes
- Use tools like cargo-bloat to identify hot spots
- Consider both debug and release mode implications
The goal is to minimize allocations in hot paths while keeping code maintainable. Always validate optimizations with benchmarks and profiles.
---
## Optimize CI/CD commands
<!-- source: astral-sh/uv | topic: CI/CD | language: Yaml | updated: 2025-07-03 -->
Design CI/CD workflows to be efficient, consistent, and purposeful across all environments. When writing or modifying pipeline scripts:
1. Batch related operations to minimize redundant commands and improve performance
2. Apply security practices consistently across all deployment targets
3. Make intentional choices about caching strategies based on the pipeline's purpose
4. Document the reasoning behind non-obvious configuration decisions
For example, when working with Docker images, prefer batched operations:
```bash
# Inefficient: Multiple separate registry operations
for tag in $TAGS; do
docker buildx imagetools create -t "${tag}" "${image}@${DIGEST}"
done
# Efficient: Batched operations per registry
readarray -t lines < <(grep "^${image}:" <<< "$TAGS"); tags=();
for line in "${lines[@]}"; do tags+=(-t "$line"); done
docker buildx imagetools create "${tags[@]}" "${image}@${DIGEST}"
For build caching strategies, be intentional about clean vs. incremental builds:
# Explicitly using source files in cache key to ensure clean builds in release pipelines
- name: Docker Cargo caches
uses: actions/cache@v4
with:
key: docker-cargo-caches-${{ matrix.platform }}-${{ hashFiles('Dockerfile', 'crates/**', 'Cargo.toml', 'Cargo.lock') }}
Names should clearly reflect their domain-specific meaning and purpose, avoiding generic or ambiguous terms. This applies to variables, methods, classes, and other identifiers. When naming, consider:
Example:
// Avoid: Generic or ambiguous names
pub fn tokens(&self) -> &Arc<SemanticTheme> { ... }
let askpass_content = format!(...);
// Better: Domain-specific semantic names
pub fn semantic_tokens(&self) -> &Arc<SemanticTheme> { ... }
let askpass_script = format!(...);
This approach helps maintain clarity and reduces confusion, especially in large codebases where context may not be immediately apparent. When introducing new names, ensure they align with the domain language used throughout the project.
When implementing or consuming APIs, always prefer using existing utility methods and abstractions over manual implementations. This reduces code duplication, improves consistency, and helps avoid subtle bugs in conversion logic or interface handling.
For example, when working with text ranges in a language server:
// Instead of this manual conversion:
let start_offset = params.range.start.to_text_size(&source, &line_index, snapshot.encoding());
let end_offset = params.range.end.to_text_size(&source, &line_index, snapshot.encoding());
let requested_range = ruff_text_size::TextRange::new(start_offset, end_offset);
// Use the existing utility method:
let requested_range = params.range.to_text_range(...);
Similarly, when checking module types or other special cases:
// Instead of string comparison:
builtin: module_name.as_str() == "builtins"
// Use the domain-specific API:
builtin: module.is_known(KnownModule::Builtins)
And when performing pattern matching on expressions:
// Instead of nested match statements:
match expr {
Expr::Call(expr_call) => match checker.semantic().resolve_qualified_name(&expr_call.func) {
Some(name) => name.segments() == ["pathlib", "Path"],
None => false,
},
_ => false,
}
// Use method chaining with is_some_and:
expr.as_call_expr().is_some_and(|expr_call| {
checker
.semantic()
.resolve_qualified_name(&expr_call.func)
.is_some_and(|name| matches!(name.segments(), ["pathlib", "Path"]))
})
Take time to familiarize yourself with the available utilities in the API you’re working with, particularly for common operations like conversions, validations, and pattern matching.
Keep modules focused and well-organized by grouping related functionality together and splitting large files into logical submodules. Each file should have a clear, single responsibility. When a file grows too large or handles multiple concerns, consider breaking it into smaller, more focused modules.
For example, instead of:
// types.rs (large file with mixed concerns)
pub(crate) trait VarianceInferable<'db>: Sized {
// ... variance-related code
}
pub(crate) struct TypeVarInstance<'db> {
// ... type variable code
}
Prefer:
// types/variance.rs
pub(crate) trait VarianceInferable<'db>: Sized {
// ... variance-related code
}
// types/type_var.rs
pub(crate) struct TypeVarInstance<'db> {
// ... type variable code
}
Key guidelines:
Always provide meaningful context for errors and avoid code that can panic in production. Use .context() or .with_context() to add rich error information, making debugging easier. Replace .unwrap() and .expect() with proper error handling mechanisms like error propagation or logging.
Example - Poor error handling:
// No context added to errors
fs::write(&askpass_script_path, askpass_script).await?;
// Potential panics in production
let file_path = python_extract_path_and_line(file_line.as_str())
.expect("Cannot parse python file line syntax");
Example - Better error handling:
// Rich context added to errors
fs::write(&askpass_script_path, askpass_script)
.await
.with_context(|| format!("Creating askpass script at {askpass_script_path:?}"))?;
// No panic risk, proper error propagation
let file_path = match python_extract_path_and_line(file_line.as_str()) {
Some(result) => result,
None => {
log::warn!("Failed to parse Python file line syntax: {}", file_line);
return None;
}
};
For error handling in library code, preserve full error information rather than simplifying too early (e.g., prefer returning Result over Option when information might be useful). When handling errors that shouldn’t propagate, use .log_err() rather than silently discarding them with let _.
Always assert exact expected values in tests rather than using loose assertions. When testing the presence of elements or count of items, use equality assertions (assert_eq!) instead of non-empty checks (assert!(!items.is_empty())) or inequality assertions (assert!(items.len() >= 2)).
Exact assertions:
For example, instead of:
// Testing that some tokens exist (too loose)
let class_tokens = tokens.iter()
.filter(|t| matches!(t.token_type, SemanticTokenType::Class))
.collect();
assert!(!class_tokens.is_empty());
// Using inequality (can hide issues)
let variable_tokens = tokens.iter()
.filter(|t| matches!(t.token_type, SemanticTokenType::Variable))
.collect();
assert!(variable_tokens.len() >= 2);
Use this approach instead:
// Test for the exact expected count
let class_tokens = tokens.iter()
.filter(|t| matches!(t.token_type, SemanticTokenType::Class))
.collect();
assert_eq!(class_tokens.len(), 1);
// Or use a helper function for multiple assertions
assert_token_count([
(SemanticTokenType::BuiltinConstant, 3),
(SemanticTokenType::Variable, 3),
]);
When practical, consider extracting assertions into helper functions that verify the exact composition of test results, making tests more readable and consistent.
Documentation should follow a consistent structure where explanations precede code examples, preferably ending with a colon to introduce the code. When documenting special cases or complex behaviors, include links to relevant external specifications or standards. Consolidate similar documentation to avoid duplication across files.
Example:
## The `nonlocal` keyword
Without the `nonlocal` keyword, `x += 1` (or `x = x + 1` or `x = foo(x)`) is not allowed in an inner
scope like this. It might look like it would read the outer `x` and write to the inner `x`, but it
actually tries to read the not-yet-initialized inner `x` and raises `UnboundLocalError` at runtime:
```py
def f():
x = 1
def g():
x += 1 # error: [unresolved-reference]
See Python language reference for more details.
---
## Minimize credential exposure lifetime
<!-- source: zed-industries/zed | topic: Security | language: Rust | updated: 2025-07-03 -->
Credentials and secrets should never be stored persistently in memory or written to files. Instead, use ephemeral patterns that limit the lifetime of sensitive data:
1. Use one-time channels or receivers to pass credentials only when needed
2. Immediately consume credentials rather than storing them in struct fields
3. Ensure sensitive data is properly cleared/dropped after use
Example of a problematic pattern:
```rust
pub struct AskPassSession {
askpass_helper: String,
_askpass_task: Task<()>,
secret: std::sync::Arc<std::sync::Mutex<String>>, // Stores credential persistently
}
Better pattern:
// Create a one-time channel for the credential
let (askpass, askpass_rx) = create_oneshot_channel();
// Use the credential only when needed
let Some(password) = askpass_rx.next().await else { /* handle error */ };
let socket = SshSocket::new(connection_options, &temp_dir, password)?;
// Password is consumed and doesn't persist in memory
This approach ensures credentials exist in memory only for the minimum time necessary and reduces the security risk if the application memory is compromised.
Organize code to maximize readability and maintainability. When code becomes complex, break it down into smaller, more manageable pieces with clear responsibilities:
// Instead of:
struct FilesystemLocks {
root: PathBuf,
}
impl FilesystemLocks {
fn from_path(root: impl Into<PathBuf>) -> Self {
Self { root: root.into() }
}
fn init(self) -> Result<Self, std::io::Error> {
// Initialize here...
}
}
// Prefer:
struct FilesystemLocks {
root: PathBuf,
}
impl FilesystemLocks {
fn from_path(root: impl Into<PathBuf>) -> Result<Self, std::io::Error> {
let this = Self { root: root.into() };
// Initialize here...
Ok(this)
}
}
Extract complex expressions: Assign complex expressions to named variables outside of nested structures to clarify their purpose and make code flow easier to follow.
Create dedicated types: When functionality around a concept grows complex, consider creating a dedicated type to encapsulate that logic and provide a cleaner interface.
Combine related implementations: Keep related functionality together by avoiding multiple separate impl blocks for the same type when they’re logically connected.
Following these principles leads to code that is easier to understand, maintain, and extend.
Always make null handling explicit through proper annotations, defensive checks, and clear documentation. Use @Nullable annotations for parameters and fields that can be null, add precondition checks with meaningful error messages for required non-null values, and document when and why values may be null.
For nullable parameters and fields, use @Nullable annotations with explanatory comments:
@Nullable
private final String mnemonic; // null if not yet known
public void maybeReportSubcommand(Spawn spawn, @Nullable String spawnRunner) {
// method implementation
}
For required non-null parameters, use defensive precondition checks that include the problematic value in error messages:
public ExecutionInfo(Map<String, String> requirements, String execGroup) {
this.executionInfo = ImmutableMap.copyOf(requirements);
this.execGroup = checkNotNull(execGroup, "execGroup cannot be null");
}
// Pass the input to checkNotNull for better error context
FileArtifactValue metadata = checkNotNull(metadataSupplier.getMetadata(input), input);
Document null behavior in javadoc, especially for return values:
/**
* Returns the action result from cache.
* @return the cached result, or null if not found in cache
*/
@Nullable
public abstract ActionResult actionResult();
This approach prevents null-related bugs by making null contracts explicit and providing clear failure points when null constraints are violated.
Keep build actions focused on their core responsibility and move complex logic to appropriate abstraction layers like builders or configuration components. Build actions should contain minimal action-specific branching and avoid tight coupling to implementation details.
This principle improves build system maintainability and reliability in CI/CD pipelines by:
For example, instead of adding conditional logic directly in a compile action:
// Avoid: Complex branching in action
if (featureConfiguration.isEnabled(CppRuleClasses.CPP_MODULES)) {
if (dotdFile != null) {
outputs.add(dotdFile);
}
}
Move the logic to the builder where it belongs:
// Prefer: Logic in builder, clean action
// Builder handles the conditional logic
// Action just processes what builder provides
Similarly, avoid introducing special artifacts or complex coupling that makes the build system “un-Starlarkifiable” or harder to maintain. When build actions stay focused and delegate complex decisions to appropriate layers, the entire CI/CD pipeline becomes more reliable and easier to troubleshoot.
Ensure that testing documentation, including changelogs, API docs, and guides, uses clear and precise language that doesn’t confuse developers. Avoid ambiguous statements that might mislead users who already understand the concepts, use proper technical terminology, and provide concrete examples that reflect real-world usage patterns.
For example, when documenting testing behavior changes:
When writing testing guides:
Always verify technical terms are properly capitalized (e.g., “WebKit” not “Webkit”) and that explanations help rather than confuse the intended audience.
When implementing configuration systems, ensure comprehensive validation, testing, and documentation. Key requirements:
Example:
#[derive(Serialize, Deserialize, Debug)]
pub struct Config {
// Explicitly document field purpose
/// Controls daemon behavior, defaults to false in CI
pub daemon: Option<bool>,
// Add validation methods
pub fn validate(&self) -> Result<(), Error> {
// Explicit validation logic
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_config_serialization() {
// Test both serialization and deserialization
let json = r#"{ "daemon": true }"#;
let config: Config = serde_json::from_str(json).unwrap();
assert_eq!(config.daemon, Some(true));
let serialized = serde_json::to_string(&config).unwrap();
assert_eq!(serialized, json);
}
}
---
## Optimize collection operations
<!-- source: Homebrew/brew | topic: Algorithms | language: Ruby | updated: 2025-07-01 -->
Use Ruby's built-in collection methods to write more efficient and readable code. This reduces algorithmic complexity and improves performance by leveraging optimized implementations instead of writing manual iterations or chaining multiple operations.
Specifically:
1. Use destructive methods with exclamation points when modifying collections in-place:
```ruby
# Instead of:
upgradeable = upgradeable.reject { |f| FormulaInstaller.installed.to_a.include?(f) }
# Prefer:
upgradeable.reject! { |f| FormulaInstaller.installed.include?(f) }
json[“old_tokens”] = (json[“old_tokens”] « old_token).uniq
json[“old_tokens”] = [old_token, *json[“old_tokens”]].compact.uniq
3. Use Symbol#to_proc syntax with methods like `map` and `filter_map` to create more concise code:
```ruby
# Instead of:
installed_formula_tap_names = Formula.installed.map { |f| f.tap.name }
.reject { |name| name == "homebrew/core" }.uniq
# Prefer:
installed_formula_tap_names = Formula.installed.filter_map(&:tap).uniq.reject(&:official?)
def non_core_taps Tap.installed.reject(&:core_tap?).reject(&:core_cask_tap?) end
def non_core_taps @non_core_taps ||= Tap.installed.reject(&:core_tap?).reject(&:core_cask_tap?) end
These approaches lead to faster algorithms, reduced memory usage, and more maintainable code.
---
## Test through public APIs
<!-- source: zed-industries/zed | topic: Testing | language: Rust | updated: 2025-07-01 -->
Write comprehensive tests that validate functionality through public interfaces rather than testing implementation details. Tests should cover diverse scenarios, handle platform-specific cases, and use appropriate assertions.
Key principles:
1. Test public contracts instead of private methods
2. Include diverse test cases (e.g., multibyte characters, edge cases)
3. Use platform-specific configurations when needed
4. Prefer visual/structural assertions over numeric ones
Example:
```rust
// Instead of testing private implementation:
#[test]
fn test_valid_url_ending() {
assert!(valid_url_ending("http://example.com"));
}
// Better - test through public API with comprehensive cases:
#[test]
fn test_url_regex() {
let urls = [
"http://example.com",
"http://example.com/(test)",
"http://ünicode.com",
"[http://example.com]"
];
for url in urls {
let matches = find_urls(url);
assert_eq!(matches[0], url.trim_matches(|c| c == '[' || c == ']'));
}
}
// Handle platform-specific cases:
#[cfg_attr(target_os = "windows", ignore)]
#[test]
fn test_file_operations() {
// Platform-specific test implementation
}
When implementing algorithms, be mindful of their computational complexity and choose appropriate data structures for operations.
HashSet over repeatedly checking Vec.contains().Itertools for common operations.// Instead of:
let mut models = BTreeMap::default(); // Causes unwanted sorting
// Use:
let mut models = Vec::new(); // Preserves insertion order when sorting isn't needed
// Inefficient O(N²) - iterating outlines twice:
for outline in fetched_outlines {
// ... then for each outline we iterate again
if outline_panel.has_outline_children(&outline_entry, cx) {
// ...
}
}
// Better: Process in a single pass with appropriate data structures
// Inefficient - unnecessarily clones data:
tasks.retain_mut(|(task_source_kind, target_task)| {
predicate(&(task_source_kind.clone(), target_task.clone()))
});
// Better - uses references:
tasks.retain_mut(|(task_source_kind, target_task)| {
predicate(&(task_source_kind, target_task))
});
// Instead of manual character loop:
let mut common_prefix_len = 0;
for (a, b) in old_text.chars().zip(new_text.chars()) {
if a == b {
common_prefix_len += a.len_utf8();
} else {
break;
}
}
// More expressive functional approach:
let common_prefix_len = old_text
.chars()
.zip(new_text.chars())
.take_while(|(a, b)| a == b)
.map(|(a, _)| a.len_utf8())
.sum::<usize>();
By consistently applying these principles, you’ll create more efficient, maintainable code that performs well even as input sizes grow.
Avoid abbreviations in variable, parameter, and method names to improve code readability and maintainability. Use descriptive identifiers that clearly indicate the purpose and content of what they represent.
Instead of:
// Abbreviated variable names
let spec = self.specialization;
let ctx = self.generic_context;
let ty = self.inferred_return_type();
let tvar = TypeVar(...);
Prefer:
// Descriptive variable names
let specialization = self.specialization;
let generic_context = self.generic_context;
let return_type = self.inferred_return_type();
let type_var = TypeVar(...);
Additionally:
infer_return_type() not inferred_return_ty()place_expr not just exprT_all instead of just TDescriptive names make code easier to understand at first glance and reduce the cognitive load required to comprehend complex logic.
Ensure render loop operations stay within frame time budget (typically 16.67ms for 60fps). Avoid expensive computations, traversals, and I/O operations during frame rendering. Instead, compute and cache results ahead of time or move heavy operations to background tasks.
Example of problematic code:
fn render_outline(&self, cx: &mut Context) {
// Bad: Expensive loop during rendering
for outline in self.outlines {
if self.has_outline_children(outline, cx) {
// ... rendering logic
}
}
}
Better approach:
fn render_outline(&self, cx: &mut Context) {
// Good: Use pre-computed results during render
for (outline, has_children) in &self.cached_outline_data {
if *has_children {
// ... rendering logic
}
}
}
// Update cache in background or on data changes
fn update_outline_cache(&mut self, cx: &mut Context) {
let mut cached_data = Vec::new();
for outline in self.outlines {
cached_data.push((outline, self.has_outline_children(outline, cx)));
}
self.cached_outline_data = cached_data;
}
Key guidelines:
Ensure configuration files and schemas adhere to their expected structure, location, and uniqueness constraints. When supporting multiple configuration file formats (e.g., both .json and .jsonc extensions), implement validation to prevent conflicting configurations:
// Good practice: Check for conflicting config files
function resolveTurboConfigPath(workspacePath: string) {
const turboJsonPath = path.join(workspacePath, "turbo.json");
const turboJsoncPath = path.join(workspacePath, "turbo.jsonc");
const turboJsonExists = fs.existsSync(turboJsonPath);
const turboJsoncExists = fs.existsSync(turboJsoncPath);
if (turboJsonExists && turboJsoncExists) {
throw new Error(`Found both turbo.json and turbo.jsonc in ${workspacePath}. Please use only one.`);
}
// Return appropriate config path...
}
When defining configuration schemas, ensure properties are placed at their correct hierarchical level and not incorrectly nested. Regularly verify that configuration documentation matches the actual implementation, especially after making changes that affect how users configure your tools.
When users report confusion about configuration usage, prioritize updating documentation and examples to reflect the current expected configuration format.
Design APIs that enforce constraints through type systems and declarative mechanisms rather than runtime checks. This makes invalid states unrepresentable by design and improves both API usability and reliability.
For example, when designing CLI arguments that shouldn’t be used together, prefer declarative constraints:
// Preferred: Declarative constraint
#[arg(long, conflicts_with = "script")]
pub group: Option<String>
// Avoid: Runtime validation
if let (Some(_), Some(_)) = (group, script) {
bail!("the argument '--group <GROUP>' cannot be used with '--script <SCRIPT>'")
}
Similarly, use appropriate types that enforce validity by construction rather than validation after parsing. This applies to enums for limited options, newtype patterns for validated values, and builder patterns with compile-time validation.
Ensure that code paths handling different deployment environments (installation prefixes, target directories, etc.) have proper test coverage. Without tests for these scenarios, it’s difficult to trust that the functionality works correctly across all supported environments.
For example, if your code handles different installation paths like:
def find_binary_path():
targets = [
# The scripts directory for the base prefix
sysconfig.get_path("scripts", vars={"base": sys.base_prefix}),
# Above the package root, from `pip install --prefix`
_join(_parents(_module_path(), 4), "bin"),
# Adjacent to the package root, from `pip install --target`
_join(_parents(_module_path(), 1), "bin"),
]
# ...
You should add tests that verify the function works correctly in each deployment scenario. Consider simulating these environments in your test setup:
This reduces the risk of deploying code that only works in the development environment but fails in production scenarios.
Only initialize configuration-dependent features, systems, or resources when the relevant settings, flags, or conditions are actually present or enabled. This prevents unnecessary resource allocation, avoids unwanted side effects like creating default contexts, and improves performance by deferring expensive operations until they’re needed.
Key patterns to follow:
Example of proper conditional initialization:
// Bad: Always initializes prefs regardless of need
if (auto* browser_context = GetDefaultBrowserContext())
prefs_ = browser_context->prefs();
// Good: Only initialize when actually needed
if (gin_helper::Dictionary restore_options;
options.Get(options::kWindowStateRestoreOptions, &restore_options)) {
// Only get prefs when stateId is present
restore_options.Get(options::kStateId, &window_state_id_);
if (!window_state_id_.empty()) {
prefs_ = GetApplicationPrefs();
}
}
Example with feature flags:
// Wrap feature-specific code with build flags
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
if (offscreen_use_shared_texture_) {
dict.Set("texture", tex);
}
#endif
This approach prevents creating unnecessary contexts, avoids performance overhead, and ensures features are only configured when they will actually be used.
Write code with clear structural organization that enhances readability and maintainability. Extract duplicated or complex logic into well-named functions, avoid deeply nested conditionals, and use proper type organization.
When identical code appears in multiple places, extract it to a function:
// Instead of repeating this code in multiple functions:
const count: usize = @intCast(self.nPages());
for (0..count) |position| {
const page = self.tab_view.getNthPage(@intCast(position));
// Complex logic here...
}
// Extract it to a dedicated function:
fn setPageIcons(self: *TabView) void {
const count: usize = @intCast(self.nPages());
for (0..count) |position| {
const page = self.tab_view.getNthPage(@intCast(position));
// Complex logic here...
}
}
For nested conditionals, prefer block expressions or separate helper functions:
// Instead of deeply nested conditionals:
if (self.window.config.gtk_tab_icons) {
if (position < 10) {
// Logic here
} else {
// Other logic
}
} else {
// Yet another logic
}
// Use block expressions or early returns:
const icon: ?*gio.Icon = icon: {
if (!self.window.config.gtk_tab_icons) break :icon null;
if (position >= 10) break :icon null;
// Logic here
break :icon result;
};
Group related types and enums in a single containing struct for better organization:
// Instead of:
pub const ColorOperationSource = enum(u16) { /* ... */ };
pub const ColorOperationList = enum(u16) { /* ... */ };
pub const ColorOperationKind = enum(u16) { /* ... */ };
// Use a containing struct:
pub const ColorOperation = struct {
pub const Source = enum(u16) { /* ... */ };
pub const List = enum(u16) { /* ... */ };
pub const Kind = enum(u16) { /* ... */ };
};
For public interfaces, consider separating functionality into distinct, purpose-specific functions rather than using boolean flags to modify behavior:
// Instead of:
pub fn init(self: *Window, app: *App, is_quick_terminal: bool) !void {
// Complex conditional logic based on is_quick_terminal
}
// Prefer:
pub fn init(self: *Window, app: *App) !void {
// Common initialization
}
pub fn initQuickTerminal(self: *Window, app: *App) !void {
// Quick terminal specific initialization
}
Design API authentication mechanisms with consistent patterns, clear documentation, and helpful error messages. When implementing authentication:
# Prefer using the base index URL for credential lookup
# Instead of:
credentials = keyring.get_credential(package_url, None)
# Use:
credentials = keyring.get_credential(index_url, None)
If you use `--token "$JFROG_TOKEN"` with JFrog, you will receive a
401 Unauthorized error as JFrog requires an empty username but
uv passes `__token__` as the username when `--token` is used.
When implementing workarounds for OS-level security restrictions, ensure they are explicitly temporary and include clear plans for proper long-term solutions. Avoid recommending users bypass security features through unofficial methods, and instead guide them toward sanctioned approaches when possible.
Security restrictions evolve over time, and workarounds that function today may break in future system updates. Code should detect the specific security context and implement fallbacks gracefully, while documenting the temporary nature of any bypasses.
Example approach:
// Temporary workaround for Ubuntu 24.04 AppArmor restrictions
// TODO: Remove when proper allowlisting mechanism is available
if (stderr.lines().anyMatch(line -> line.endsWith(": \"mount\": Permission denied"))) {
try {
runBinTrue(cmdEnv, linuxSandbox, /* wrapInBusybox= */ true);
return SupportLevel.SUPPORTED_VIA_BUSYBOX;
} catch (CommandException e2) {
// Provide guidance for sanctioned solutions rather than workarounds
cmdEnv.getReporter().handle(Event.warn(
"linux-sandbox failed due to security restrictions. " +
"Consider using sanctioned methods to configure permissions."));
}
}
The goal is to maintain functionality while respecting the intent of security measures and preparing for their proper implementation.
Organize code and documentation logically based on functionality and dependencies. Place files in directories that reflect their purpose rather than superficial characteristics. Structure documentation so prerequisite concepts appear before concepts that depend on them.
For example:
This organizational approach improves readability, makes the codebase more intuitive to navigate, and helps developers understand relationships between different components.
Make deliberate choices about error handling strategies based on the context. Decide between early returns with appropriate error reporting, panic mechanisms, or silent failures with diagnostics:
// Prefer this when the error is expected in normal operation
if !output.status.success() {
return Err(anyhow::anyhow!(
"Git checkout failed: {}",
String::from_utf8_lossy(&output.stderr)
));
}
// Use panic! over unreachable! when an invariant is violated
match definition.scope(db).node(db) {
NodeWithScopeKind::Class(_) => {
panic!("invalid definition kind for type variable")
}
// Valid cases...
}
// Return a sensible default and let type checking handle the error
if !is_callable(test_expr) {
return Truthiness::AlwaysFalse;
}
Always document functions that can panic and under what conditions. When handling results, be explicit about error propagation choices - consider whether errors should be logged, propagated, or transformed into different error types based on the needs of the caller.
Choose variable, function, and class names that accurately reflect their purpose while maintaining consistency with established patterns in the codebase. When the purpose or content of an entity changes, update its name accordingly. This applies to:
// After: More general name that matches its versatile purpose function getHash(input: string): string { … }
2. **Variable names**: Ensure names accurately reflect the actual content.
```javascript
// Before: Misleading name (contains ids, not urls)
const normalizedAcceptedUrls = new Set<string>()
// After: Name matches content
const resolvedAcceptedDeps = new Set<string>()
// After: Plural form indicating multiple modules public fileToModulesMap = new Map<string, ModuleRunnerNode[]>()
4. **Parameter names**: Choose names that avoid confusion with similar concepts.
```javascript
// Before: Potentially confusing parameter name
function glob(pattern: string, cwd: string): string[] { ... }
// After: More specific name that avoids confusion
function glob(pattern: string, base: string): string[] { ... }
// After: Follows the project’s hyphenated naming pattern { name: ‘ember-app’, // … }
Always prioritize clarity and accuracy in naming to improve code readability and reduce the likelihood of bugs or misunderstandings.
---
## Test edge cases
<!-- source: astral-sh/ruff | topic: Testing | language: Python | updated: 2025-06-27 -->
When writing tests, prioritize coverage of edge cases and non-standard code patterns to ensure robust functionality. Particularly for linting rules or code transformations, identify scenarios that might behave unexpectedly or require special handling.
Include tests for:
- Code with comments in various positions
- Unusual formatting or line continuations
- Nested object constructions
- Dependencies on multiple variables
- Different parameter passing styles (positional vs. keyword)
For example, when testing a rule that transforms string paths to Path objects:
```python
# Test with comments in different positions
func_name( # comment
"filename")
func_name( # comment
"filename",
#comment
)
# Test with line continuations
func_name \
\
( # comment
"filename",
)
# Test with nested objects
func_name(Path("filename").resolve())
# Test with dependencies on other variables
for x, y in some_pairs:
result.add((x, y))
Testing these edge cases early prevents subtle bugs from surfacing in production code and makes your code more maintainable over time.
Documentation should explain not just what APIs and features do, but when, why, and how to use them. Provide sufficient context for developers to understand the purpose, appropriate use cases, and practical implementation details.
Key practices:
WebContentsViews when the content finishes loading”)ScreenCaptureKit API”)Example of good contextual documentation:
// Instead of just describing the API
win.webContents.on('paint', (event, dirty, image) => {
// Handle paint event
})
// Provide context about different usage patterns
const win = new BrowserWindow({
webPreferences: {
offscreen: true,
offscreenUseSharedTexture: true
}
})
win.webContents.on('paint', async (e, dirty, image) => {
if (e.texture) {
// When using shared texture for better performance
await handleTextureAsync(e.texture.textureInfo)
e.texture.release() // Important: release when done
} else {
// When using traditional bitmap approach
handleBitmap(image.getBitmap())
}
})
This approach helps developers understand not just the mechanics of an API, but how to use it effectively in real applications.
Create intuitive API interfaces that abstract away implementation details while providing a consistent experience for consumers. Use appropriate parameter types that express intent and maintain established patterns across your codebase.
When designing function parameters:
// Before: Implementation-focused API
pub fn fetch(&self, remote_name: String, cx: &mut ModelContext<Self>) { /* ... */ }
// After: Intent-focused API with better parameter types
pub enum FetchTarget {
AllRemotes,
SpecificRemote(String)
}
pub fn fetch(&self, target: FetchTarget, cx: &mut ModelContext<Self>) { /* ... */ }
// Before: Platform-specific APIs with inconsistent signatures
fn set_dock_menu(&self, menu: Vec<MenuItem>, keymap: &Keymap) {}
fn update_jump_list(&self, entries: &[&Vec<String>]) -> Option<Vec<Vec<String>>> {}
// After: Unified interface hiding platform differences
fn update_recent_projects(&self, projects: Vec<PathBuf>) -> Result<()> {
// Platform-specific implementations inside
}
// Maintain consistent builder patterns where established
let branch_button = Button::new("project_branch_trigger", branch_name)
.color(Color::Muted)
.style(ButtonStyle::Subtle)
.when(settings.show_branch_icon, |button| {
button.with_icon(Icon::GitBranch)
});
Good interfaces reduce coupling between components, improve testability, and create more maintainable systems by allowing implementation details to evolve independently of the API contract.
Use version-specific TODO comments with a consistent format to ensure actionable items are properly tracked and easily searchable across the codebase. Include the target version in parentheses immediately after “TODO” to make it clear when the item should be addressed.
This practice helps prevent technical debt from accumulating by making it easy to find and address TODOs during version releases. Without version specificity, TODO comments often become stale and forgotten.
Format TODO comments like this:
// TODO(v22): Change default value of useLegacyTypescriptPlugin to false
// TODO(v23): Remove the legacy TypeScript plugin entirely
// TODO(v22) - remove this generator
This format enables developers to quickly search for TODO(v22) when preparing for version 22 releases, ensuring nothing gets missed during major version updates.
Ensure comprehensive test coverage by testing all behavioral variations, configuration options, and edge cases rather than just single scenarios. When adding new functionality, preserve existing tests and add new ones to cover both old and new behaviors.
For example, when modifying a function to support both synchronous and asynchronous behavior, maintain separate tests for each:
// Keep existing sync test
"foo-parser": {
preprocess: (text) => `preprocessed:${text}`,
// Add new async test
"foo-parser-async": {
preprocess: (text) => Promise.resolve(`preprocessed:${text}`),
Similarly, when implementing features with configuration options, test multiple settings rather than just defaults:
// Test different quoteProps options
{"quoteProps": "consistent"}
{"quoteProps": "as-needed"}
{"quoteProps": "preserve"}
This approach prevents regressions and ensures robust functionality across all supported use cases.
When specifying dependencies and version requirements in project configuration files, avoid adding unnecessary constraints that could limit future compatibility. Unless there’s a specific known incompatibility issue:
# Preferred
requires-python = ">=3.11"
# Avoid unless necessary
requires-python = ">=3.11,<3.13"
# Consider whether dependencies belong in [dependencies] or [dev-dependencies]
# Some dependencies like 'anyhow' should typically be avoided in library crates
This practice ensures your configurations remain flexible while still maintaining necessary compatibility requirements.
When handling null values in Rust, use idiomatic Option patterns instead of verbose nested conditionals. This improves code readability, safety, and reduces the chance of runtime errors.
Always prefer:
is_some_and() over map_or(false, |x| ...) when checking conditions on Option values:
```rust
// Instead of:
self.popover
.as_ref()
.map_or(false, |popover| popover.signature.len() > 1)// Use: self.popover .as_ref() .is_some_and(|popover| popover.signature.len() > 1)
2. The `?` operator for early returns instead of verbose `if let Some()` patterns:
```rust
// Instead of:
if let Some(editor) = Self::resolve_active_item_as_svg_editor(workspace, cx) {
if Self::is_svg_file(&editor, cx) {
// ... implementation ...
}
}
// Use:
let editor = Self::resolve_active_item_as_svg_editor(workspace, cx)?;
if Self::is_svg_file(&editor, cx) {
// ... implementation ...
}
.ok() to convert a Result to an Option when appropriate:
```rust
// Instead of:
let system_id = ids::get_or_create_id(&ids::eval_system_id_path())
.unwrap_or_else(|_| String::new());// Use: let system_id = ids::get_or_create_id(&ids::eval_system_id_path()).ok();
4. Safe alternatives to `.unwrap()` which can cause runtime panics:
```rust
// Instead of:
workspace.subscribe(&workspace.weak_handle().upgrade().unwrap(), |editor, ...
// Use:
if let Some(workspace) = workspace.weak_handle().upgrade() {
cx.subscribe(&workspace, |editor, ...
}
These patterns make your code more robust against null reference errors while keeping it concise and readable.
When documenting complex features or configuration options, structure your documentation with these four key elements:
For example, instead of:
/// When enabled (any value other than `off`), Ghostty replaces the `ssh` command
/// with a shell function to provide enhanced terminal compatibility and feature
/// propagation when connecting to remote hosts.
Prefer this structure:
/// * `term-only`
///
/// Automatically set the `TERM` environment variable to `xterm-256color` when
/// connecting to remote hosts using SSH.
///
/// By default, Ghostty identifies itself with the terminal type `xterm-ghostty`,
/// which could cause problems for remote machines where Ghostty's _terminfo files_
/// are not installed. Many programs rely on terminfo files to know what the
/// terminal is capable of, and may crash with "unknown terminal type" errors when
/// the terminfo files are absent or exhibit strange behavior.
///
/// When `term-only` is set, for remote connections Ghostty would instead identify
/// itself as `xterm-256color`, which is a compatibility mode understood in most
/// systems.
///
/// This option is best used when you need to connect to a wide variety of remote
/// devices, some of which you might not have access to.
Similarly, error messages should be specific and actionable. Instead of vague messages like “your compositor does not support the protocol”, provide specific guidance such as “your distro’s gtk4-layer-shell version is defective; update to 1.0.4 or later”.
Raw pointers are banned in new code unless absolutely necessary. Instead, use managed pointer types to prevent null pointer dereferences, dangling pointers, and memory safety issues.
Use the appropriate managed pointer type based on ownership semantics:
SP<T> (shared pointer) for shared ownershipUP<T> (unique pointer) for exclusive ownershipWP<T> (weak pointer) for non-owning referencesExample from the codebase:
// Bad - raw pointer prone to null dereferences
CExtWorkspaceHandleV1* workspace;
SSessionLockSurface* touchFocusLockSurface;
CXxColorManagementSurfaceV4* m_pCMSurface = nullptr;
// Good - managed pointers prevent null issues
SP<CExtWorkspaceHandleV1> workspace;
WP<SSessionLockSurface> touchFocusLockSurface;
WP<CXxColorManagementSurfaceV4> m_pCMSurface;
For protocol implementations, prefer UP<> for resource ownership while allowing WP<> references to it. This pattern ensures proper lifetime management and prevents accessing freed memory.
Documentation should include clear, actionable code examples that users can reliably follow. Avoid using ambiguous placeholders or variables that might be misinterpreted as literal code to copy-paste. When placeholder values must be used in examples, explicitly mark them and provide clear instructions for replacement.
For example, instead of:
eval "${HOMEBREW_PREFIX}/bin/brew shellenv)"
Which implies the variable is already set, use one of these approaches:
# Option 1: Use clear placeholder markers
eval "<Homebrew prefix path>/bin/brew shellenv)"
# Option 2: Include explicit instructions
# Replace /opt/homebrew with your installation directory
eval "/opt/homebrew/bin/brew shellenv)"
Similarly, when linking to API methods or classes in documentation, ensure the links are accurate and properly formatted. Check that URLs don’t use encoded characters unnecessarily, and test links to confirm they direct to the intended destination.
This practice helps prevent confusion, reduces support requests, and creates a better experience for developers following your documentation.
Implement robust null and undefined handling patterns to prevent runtime errors and maintain code reliability. Use optional chaining for safe property access, explicit null checks with early returns, and conditional property assignment to avoid unintended undefined values.
Key patterns to follow:
?.) when accessing properties that might be undefined: if (options?.throwIfNoEntry === true)if (!webContents) return null;Example implementation:
// Good: Optional chaining and explicit null check
const archive = getOrCreateArchive(asarPath);
if (!archive) {
if (options?.throwIfNoEntry === true) {
throw createError(AsarError.INVALID_ARCHIVE, { asarPath });
}
return null;
}
// Good: Conditional property assignment to preserve defaults
const urlLoaderOptions = {
priority: options.priority
};
if ('priorityIncremental' in options) {
urlLoaderOptions.priorityIncremental = options.priorityIncremental;
}
This approach prevents silent failures, maintains type safety, and ensures predictable behavior when dealing with nullable values.
When implementing algorithms for code analysis, type checking, or pattern matching, ensure they produce consistent and deterministic results for the same inputs. Edge cases should be explicitly handled rather than making assumptions.
Key practices:
Example of problematic code:
# Incorrect: Unconditionally reporting error without checking if a match was found
def check_overloads(call_site, overloads):
for overload in overloads:
if arity_matches(call_site, overload):
# Missing validation! We found a potential match but didn't verify it
pass
# Incorrectly assumes failure even when a match might exist
report_no_matching_overload(call_site)
Improved implementation:
# Correct: Explicitly track success and only report error when needed
def check_overloads(call_site, overloads):
potential_matches = []
for overload in overloads:
if arity_matches(call_site, overload):
potential_matches.append(overload)
# Only report error if truly no matches were found
if not potential_matches:
report_no_matching_overload(call_site)
else:
# Process potential matches further
validate_matches(call_site, potential_matches)
Non-deterministic algorithms can introduce subtle bugs that are difficult to reproduce and debug. By ensuring deterministic behavior and explicit validation of conditions, you can create more robust and maintainable code.
Choose specific, descriptive names for identifiers that accurately reflect their purpose and behavior. Avoid generic terms or ambiguous names that could lead to confusion. Names should be self-documenting and convey precise meaning.
Key guidelines:
Example - Improving name specificity:
// ❌ Ambiguous or generic names
class AiRelatedInformation { }
function isPath(string: string) { }
interface SearchOptions { }
// ✅ Specific, semantic names
class AiSearchSettingKeysProvider { }
function isPathLike(text: string) { }
interface RipgrepTextSearchOptions { }
This helps prevent confusion, makes code more self-documenting, and reduces the need for additional clarifying comments.
CI workflows should be precise, minimal, and predictable:
on: pull_request.paths (avoid overly broad selectors like **/*.js unless required). If the PR doesn’t touch dependency inputs, the lockfile validation workflow shouldn’t run.pnpm-lock.yaml unless the PR actually changes what would require regeneration; this reduces merge-conflict risk.permissions are set at the correct (job) level.author_name/author_email to the GitHub Actions bot identity.Example trigger narrowing:
on:
pull_request:
paths:
- 'pnpm-lock.yaml'
- '**/package.json'
# Avoid adding broad patterns like '**/*.js' unless lockfile validation is truly needed for those changes.
Configuration files require careful validation to ensure they work as intended and don’t introduce unintended side effects. This includes verifying ignore patterns don’t create parent-child conflicts, understanding rule severity implications, and confirming dependency changes are expected.
For ignore patterns, ensure re-inclusion rules don’t conflict with parent directory exclusions:
# Bad: Can't re-include files in ignored parent directories
/tests/format/**/*.*
!/tests/format/**/format.test.js
# Good: Re-include parent directories first
/tests/format/**/*.*
!/tests/format/**/*.*/
!/tests/format/**/format.test.js
For rule configurations, understand the difference between “error” and “warn” severity levels and use appropriate tooling flags like --max-warnings=0 to enforce standards consistently.
For dependency changes, use tools like yarn why to understand why specific versions exist and yarn-deduplicate to clean up duplicate dependencies before merging.
Always test configuration changes locally and verify they produce the expected behavior across different scenarios.
Ensure documentation follows consistent formatting standards to improve readability and maintainability. This includes proper indentation of code blocks for syntax highlighting, clear separation of examples with individual explanatory comments, and concise organization of related information.
Key formatting requirements:
Example of improved formatting:
-- Install "plugin1" and use greatest available version
'https://github.com/user/plugin1',
-- Same as above, but using full table syntax for additional options
{ source = 'https://github.com/user/plugin2' },
Rather than:
-- Install as "plugin1"/"plugin2" and use greatest available version
'https://github.com/user/plugin1',
{ source = 'https://github.com/user/plugin2' },
This approach prevents confusion about whether examples represent single or multiple operations and ensures each example’s purpose is immediately clear to readers.
When working with union types in Python, always verify that all components of the union have the attributes you’re trying to access or modify. Failure to do so can lead to runtime errors when the code attempts to access undefined attributes.
For attribute access on unions:
from typing import Union
class A:
pass # No 'x' attribute
class B:
x: int # Has 'x' attribute
# Unsafe pattern - might cause runtime errors:
def unsafe(obj: Union[A, B]):
obj.x = 42 # Error: possibly-unbound-attribute
# Safe pattern - check type first:
def safe(obj: Union[A, B]):
if isinstance(obj, B):
obj.x = 42 # Safe, we've verified this is type B
# Alternative safe pattern - use hasattr:
def also_safe(obj: Union[A, B]):
if hasattr(obj, "x"):
obj.x = 42 # Safe, we've verified attribute exists
Similarly, when using the del statement, track deleted variables carefully and avoid accessing them after deletion to prevent “unresolved-reference” errors.
When naming components, packages, or files that conflict with existing names in your system or related ecosystems, follow a systematic approach to ensure uniqueness while maintaining semantic clarity:
# Instead of just:
unison.rb
# Use:
panic-unison.rb
# For different implementations of the same concept:
appium (formula)
appium-desktop (cask)
# For application variants:
angband (formula)
angband-app (cask)
This approach ensures names remain unique, descriptive, and intuitive, making the codebase more maintainable and reducing confusion for developers working across related systems.
Avoid performing expensive operations (like module loading, event emissions, or resource allocation) until they are actually needed. This pattern significantly improves startup time and runtime performance by reducing unnecessary work.
Key strategies:
require calls from initialization code into the actual function implementationsExample of lazy require pattern:
-- Instead of eager loading at plugin initialization:
local foo = require("foo")
vim.api.nvim_create_user_command("MyCommand", function()
foo.do_something()
end, {})
-- Defer the require until command execution:
vim.api.nvim_create_user_command("MyCommand", function()
local foo = require("foo") -- Load only when needed
foo.do_something()
end, {})
This approach ensures that modules and their dependencies are only loaded when the functionality is actually used, rather than eagerly loading everything at startup. The same principle applies to other expensive operations like network calls, file I/O, or complex computations.
Replace panics, expects, and unwraps with graceful error handling that provides user feedback and allows the system to continue operating. Instead of crashing the application, log errors appropriately and return early or set status messages for the user.
For example, instead of:
let config = debugger.config.clone();
let result = self
.dap_servers
.start_client(Some(socket), &config.expect("No config found"));
Use:
let config = match debugger.config.clone() {
Some(config) => config,
None => {
log::error!("No config found for debugger");
return true;
}
};
let result = self.dap_servers.start_client(Some(socket), &config);
Similarly, replace panics with status line errors:
// Instead of: panic!("Expected non-empty argument roots.")
if roots.is_empty() {
cx.editor.set_error("Expected non-empty argument roots");
return;
}
This approach improves user experience by preventing crashes and providing meaningful feedback about what went wrong, while allowing the application to continue functioning.
Select the appropriate cache sharing approach based on your execution environment to maximize performance and efficiency. When working with containerized applications:
~/.cache/uv)Example for sharing cache in Docker containers:
# Docker container cache sharing
volumes:
- ./cache:/root/.cache/uv
Keep cache configurations simple by default and only add specialized invalidation patterns when necessary. For most cases, the default cache behavior is sufficient.
When implementing environment variable configuration:
NO_COLOR, FORCE_COLOR)NO_COLOR, FORCE_COLOR, CLICOLOR_FORCE)Example:
// Bad - No validation or documentation
if std::env::var_os("FORCE_COLOR").is_some() {
ColorChoice::Always
}
// Good - Validates non-empty value and documents behavior
/// Controls color output. When set to a non-empty value, forces color output
/// regardless of terminal capabilities.
/// Takes precedence over NO_COLOR and --color settings.
if let Some(force_color) = std::env::var_os("FORCE_COLOR") {
if !force_color.is_empty() {
ColorChoice::Always
}
}
Represent AI model information using structured data rather than hardcoded enumerations or conditionals. Store capabilities, limitations, and features as structured fields that can be queried at runtime. This approach simplifies adding new models, detecting feature support, and adapting to model updates without requiring extensive code changes.
For example, instead of:
fn supports_vision(&self) -> bool {
match self {
Self::Gpt4o | Self::Gpt4_1 | Self::Claude3_5Sonnet => true,
_ => false,
}
}
Use:
struct Model {
id: String,
name: String,
capabilities: ModelCapabilities,
// ...
}
struct ModelCapabilities {
// ...
supports: ModelSupportedFeatures,
}
struct ModelSupportedFeatures {
#[serde(default)]
vision: bool,
// ...
}
impl Model {
pub fn supports_vision(&self) -> bool {
self.capabilities.supports.vision
}
}
This data-driven approach is more maintainable when integrating new AI models and reduces the risk of errors when model capabilities change. It also enables more efficient filtering and selection of models based on required capabilities.
Always use Swift’s built-in mechanisms for safely handling optional values instead of force unwrapping or manual nil handling. Specifically:
if let, guard let) instead of checking for nil and force unwrapping:// Avoid this pattern
if savedWindowFrame != nil {
let originalFrame = savedWindowFrame! // Risky force unwrap
}
// Prefer this pattern
if let savedWindowFrame {
let originalFrame = savedWindowFrame // Safe access
}
flatMap or compactMap to handle optional collections elegantly:// Avoid this pattern
return controllers.reduce([]) { result, c in
result + (c.surfaceTree.root?.leaves() ?? [])
}
// Prefer this pattern
return controllers.flatMap {
$0.surfaceTree.root?.leaves() ?? []
}
@IBAction func toggleMaximize(_ sender: Any) {
guard let window = window else { return }
guard surfaceTree.contains(sender) else { return } // Check hierarchy membership
// Implementation...
}
These patterns make code more concise, readable, and less prone to runtime crashes due to unexpected nil values.
When documenting commands or tools that can be executed in different ways based on configuration settings (like global vs. local installation), always explicitly describe all alternatives with clear, consistent labeling. Include examples for each configuration option to ensure users can follow instructions regardless of their environment setup.
For example:
# With global installation
turbo dev
# Without global installation, use your package manager
npx turbo dev
yarn exec turbo dev
pnpm exec turbo dev
This approach makes documentation more inclusive and prevents confusion when users have different environment configurations. It’s especially important for tools that offer multiple execution paths depending on how they’re installed or configured.
Ensure all package manager commands in documentation and CI/CD scripts follow the correct syntax for the specific package manager being used, especially in monorepo environments. Package manager flags should be positioned correctly according to each tool’s specifications to prevent pipeline failures.
When documenting commands for monorepo tools like Turborepo:
Example:
# Incorrect command (flag placement issue)
pnpm test:interactive -F turborepo-tests-integration
# Correct command
pnpm --filter turborepo-tests-integration test:interactive
# For documentation, consider a more generic approach:
# Without global turbo, use your package manager:
npx turbo build # for npm
yarn dlx turbo build # for yarn
pnpm exec turbo build # for pnpm
Proper command syntax is critical for successful CI/CD pipelines, as incorrect commands will cause builds to fail and interrupt deployment workflows.
Minimize code nesting by using Swift features like guard statements and early returns instead of deeply nested if-else structures. When multiple code branches end with a return statement, avoid nesting with else clauses.
Instead of:
if index == count {
return try body(accumulated)
} else {
// More nested code here
}
Prefer:
if index == count {
return try body(accumulated)
}
// Continue with the flow without nesting
Or consider using guard statements for early returns:
guard case .split(let c) = node else { return }
// Now work with the unwrapped variable
This approach makes code more scannable, easier to follow, and less prone to the “pyramid of doom” issue that can happen with multiple levels of nesting.
Always ensure buffers, containers, and data structures are properly initialized before passing them to functions that will dereference them. This prevents null pointer dereferences and undefined behavior.
Key practices:
FUNC_ATTR_NONNULL_ALL and similar attributes to function parameters that must not be nullassert(argc > 0) rather than assert(argc >= 0) when zero values are not validos_getenv() that can return null, check the result before dereferencingExample from the codebase:
// Before: Potential null dereference
if (swap_exists_action != SEA_NONE) {
choice = (sea_choice_T)do_dialog(VIM_WARNING, _("VIM - ATTENTION"), msg.items, ...);
}
// After: Ensure buffer is initialized
kv_resize(*msg, IOSIZE); // Initialize buffer before use
if (swap_exists_action != SEA_NONE) {
choice = (sea_choice_T)do_dialog(VIM_WARNING, _("VIM - ATTENTION"), msg.items, ...);
}
This approach prevents static analysis tools from flagging potential null dereferences and ensures runtime safety by establishing clear contracts about what data must be valid before use.
Always define explicit error sets for functions that can fail, rather than using inferred error sets. This makes error handling more maintainable and helps catch missing error cases during development. The error set should be defined at the function level, even for simple APIs.
Example:
// Instead of:
pub fn init(alloc: Allocator, opts: rendererpkg.Options) !OpenGL {
// ...
}
// Do this:
const InitError = error{
OutOfMemory,
InvalidVersion,
DeviceNotFound,
};
pub fn init(alloc: Allocator, opts: rendererpkg.Options) InitError!OpenGL {
// ...
}
This approach:
Even for wrapper functions or simple APIs, defining the error set helps maintain consistency and makes future modifications safer by forcing explicit consideration of error cases.
Ensure all comments in the codebase provide value and clarity rather than creating confusion. Remove comments that are:
In test files, be particularly cautious with comments that could be misinterpreted about what’s being tested. For example, avoid trailing comments that might suggest a different behavior than what the test is actually checking.
Example of problematic comments:
# pylint: disable=unused-import # Not helpful if not using pylint
foo.__dict__.get("not__annotations__") # RUF061 # Misleading - suggests this should trigger a warning
Example of improved approach:
# Cases that should NOT trigger the violation
foo.__dict__.get("not__annotations__")
Regularly review and clean up comments when code changes make them obsolete. Comments should enhance understanding, not create confusion.
When designing configuration systems, provide both replacement and extension options for list-based settings to give users flexibility in how they modify default configurations.
For list-based configurations, consider implementing:
allow_abc_meta_bases)extend_abc_meta_bases)This approach allows users to either:
#[option(
default = r#"["typing.Protocol", "typing_extensions.Protocol"]"#,
value_type = "list[str]",
example = r#"allow-abc-meta-bases = ["my_package.SpecialBaseClass"]"#
)]
pub allow_abc_meta_bases: Vec<String>,
#[option(
default = r#"[]"#,
value_type = "list[str]",
example = r#"extend-abc-meta-bases = ["my_package.SpecialBaseClass"]"#
)]
pub extend_abc_meta_bases: Vec<String>,
When implementing the options, combine them at the settings level rather than requiring consumers to check both settings:
// In your settings structure
pub struct Settings {
// Combined at initialization time
pub allowed_bases: FxHashSet<String>,
}
// When constructing settings
let mut allowed_bases = options.allow_abc_meta_bases.into_iter().collect::<FxHashSet<_>>();
allowed_bases.extend(options.extend_abc_meta_bases.iter().cloned());
This pattern promotes cleaner code that consumes the settings, making it less error-prone and easier to maintain.
When implementing algorithms, prioritize reducing computational complexity before adding special cases or optimizing for specific scenarios. Key practices:
Example - Converting O(n²) to O(n):
// Poor: O(n²) complexity with multiple array operations
selections = selections.filter((s, idx, arr) => {
return arr.map(sel => sel.endLineNumber)
.indexOf(s.endLineNumber) === idx;
});
// Better: O(n) complexity with single pass
const seen = new Set();
const uniqueSelections = [];
for (const selection of selections) {
if (!seen.has(selection.endLineNumber)) {
seen.add(selection.endLineNumber);
uniqueSelections.push(selection);
}
}
When using Set operations, ensure object identity works as expected for your data type. For complex objects like URIs, implement custom equality comparisons or use appropriate key extraction.
Ensure code examples in documentation and comments are syntactically correct and properly marked with the appropriate language identifier. This maintains a professional appearance and prevents readers from copying incorrect code.
Key guidelines:
Example - INCORRECT:
function myPlugin() {
const state = new Map<Environment, { count: number }>()
return {
name: 'my-plugin',
buildStart() {
state.set(this.environment, { count: 0 })
// Missing comma here!
transform(code) {
// ...
}
}
}
Example - CORRECT:
function myPlugin() {
const state = new Map<Environment, { count: number }>()
return {
name: 'my-plugin',
buildStart() {
state.set(this.environment, { count: 0 })
}, // Proper comma after function
transform(code) {
// ...
}
}
}
Or alternatively with plain JS:
function myPlugin() {
const state = new Map()
return {
name: 'my-plugin',
buildStart() {
state.set(this.environment, { count: 0 })
},
transform(code) {
// ...
}
}
}
Always mark experimental and deprecated configuration options with appropriate stability indicators in documentation. Use _Experimental_ for features under active development and _Deprecated_ for features being phased out. This helps developers make informed decisions about which configuration options are safe for production use.
For experimental features, consider including additional context about stability expectations:
* `windowStateRestoreOptions` [WindowStateRestoreOptions](window-state-restore-options.md?inline) (optional) - Options for saving and restoring window state: position, size, maximized state, etc. _Experimental_
* `deprecatedPasteEnabled` boolean (optional) - Whether to enable the `paste` [execCommand](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand). Default is `false`. _Deprecated_
* `frozenIntrinsics` boolean (optional) - Experimental option for passing [`--frozen-intrinsics`](https://nodejs.org/api/cli.html#--frozen-intrinsics) to Node.js.
For command-line switches marked as experimental in Node.js docs, maintain consistency by flagging them appropriately in Electron documentation as well. This practice ensures developers understand the maturity and support level of configuration options they’re considering.
Handle nil values explicitly and consistently to improve code clarity and type safety. Follow these guidelines:
def process_data if data.present? # process data end end
def process_data return if data.blank? # process data end
2. Use .presence for nil/empty string handling:
```ruby
# Bad
name = input.empty? ? nil : input
# Good
name = input.presence
def fetch_config config = load_config config if config.valid? end
def fetch_config config = load_config raise Error, “Invalid config” unless config.valid? config end
4. Use proper type signatures for nullable values:
```ruby
# Bad
sig { returns(String) }
def optional_value
@value # might be nil!
end
# Good
sig { returns(T.nilable(String)) }
def optional_value
@value
end
This approach improves code readability, makes nil-handling intentions clear, and helps catch potential nil-related issues early through static analysis.
Ensure configuration handling is consistent and platform-agnostic by following these guidelines:
// Bad let sample_count = std::env::var(“ZED_SAMPLE_COUNT”).unwrap_or_default();
2. Implement proper default values using serde attributes:
```rust
#[derive(Deserialize)]
pub struct Config {
#[serde(default = "default_true")]
pub enabled: bool,
#[serde(default)]
pub custom_path: String,
}
// Bad let config_dir = PathBuf::from(“/usr/local/etc”);
4. Provide clear validation for configuration:
- Validate all required fields
- Include schema documentation
- Support cross-platform paths
- Handle missing values gracefully
5. Allow configuration overrides through multiple layers:
- Environment variables
- User configuration files
- System defaults
- Platform-specific defaults
This ensures configurations work consistently across different platforms while maintaining flexibility and robustness.
---
## Precise type narrowing
<!-- source: astral-sh/ruff | topic: Algorithms | language: Markdown | updated: 2025-06-17 -->
Implement sound type narrowing algorithms that balance precision with correctness. When narrowing types:
1. For direct assignments, narrow the type to the assigned value's type:
```python
x: int | None = None
x = 42
# x now has type Literal[42]
list, dict, etc.)
```python
obj.attr = “value” # obj.attr now has type Literal[“value”]
@property def x(self): return self._x @x.setter def x(self, val): self._x = abs(val) obj.x = -1 # obj.x should still be int, not Literal[-1]
3. Reset narrowed types when the base object is reassigned:
```python
c = C()
c.attr = "foo" # c.attr has type Literal["foo"]
c = C() # c.attr should revert to its declared type
def func(x: Any): if is_int(x): # x has type Any & int
Sound type narrowing algorithms prevent false negatives while maintaining precision, allowing for safer and more robust code.
---
## Use direct documentation style
<!-- source: astral-sh/uv | topic: Documentation | language: Markdown | updated: 2025-06-17 -->
Write documentation using direct, clear language that addresses the reader directly. Follow these style guidelines:
1. Use direct address instead of referring to "users" - write "You can configure..." rather than "Users can configure..."
2. Avoid words like "simply" that minimize complexity - recognize that what seems simple to documentation authors may not be obvious to all readers.
3. Maintain consistent formatting for technical elements (HTTP status codes, command options, etc.) throughout documentation.
4. Keep guides focused on common workflows with appropriate detail levels, saving complex explanations for reference documentation.
Example - Instead of:
When using the first-index strategy, uv will stop searching if it encounters a 401 Unauthorized
or 403 Forbidden response status code. Users can configure which error codes are ignored for an
index, using the ignored-error-codes setting.
Write:
When using the first-index strategy, uv will stop searching if an HTTP 401 Unauthorized
or HTTP 403 Forbidden status code is encountered. To ignore additional error codes for an index,
use the ignored-error-codes setting.
This style creates documentation that feels more approachable while maintaining technical accuracy.
---
## Structure test fixtures clearly
<!-- source: Homebrew/brew | topic: Testing | language: Ruby | updated: 2025-06-17 -->
Test fixtures should clearly separate input parameters from expected outputs to enhance readability and maintainability. For table-driven tests, use a consistent pattern that explicitly distinguishes between test inputs and expected results. This approach makes tests more understandable and easier to maintain over time.
A well-structured table-driven test might look like:
```ruby
tests = {
"generic tarball URL": {
params: {
url: "http://digit-labs.org/files/tools/synscan/releases/synscan-5.02.tar.gz",
},
expected: {
name: "synscan",
version: "5.02",
},
},
"with version override": {
params: {
url: "http://digit-labs.org/files/tools/synscan/releases/synscan-5.02.tar.gz",
version: "3.40",
},
expected: {
name: "synscan",
version: "3.40",
}
},
}
tests.each do |description, test|
it "processes #{description}" do
result = process_with(test[:params])
expect(result).to eq(test[:expected])
end
end
This structure makes it immediately clear what inputs are being provided and what outputs are expected, improving test readability and making failures easier to diagnose.
When destroying objects asynchronously to avoid crashes from observer notifications or other synchronous destruction issues, ensure proper cleanup ordering and add defensive null checks to handle race conditions.
Key practices:
Example from the discussions:
// Instead of synchronous destruction that crashes:
// managed_devtools_web_contents_.reset();
// Use async destruction:
embedder_message_dispatcher_.reset();
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
[](std::unique_ptr<content::WebContents> web_contents) {},
std::move(managed_devtools_web_contents_)));
managed_devtools_web_contents_ = nullptr;
// Add defensive checks in methods:
if (!GetDevToolsWebContents())
return;
This pattern prevents crashes from premature destruction while maintaining system stability during async cleanup operations.
When modifying configuration options, ensure changes are consistently applied across all relevant locations including default configuration files, documentation, example configs, and related codebases. Configuration inconsistencies create user confusion and maintenance burden.
This reviewer addresses the common issue where developers update configuration in one location but forget to synchronize changes elsewhere. For example, when updating brightness control settings, the change must be reflected in both the main config and the default config header file.
Example of proper consistency:
// In defaultConfig.hpp
bindel = ,XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+
// In example/hyprland.conf
bindel = ,XF86MonBrightnessUp, exec, brightnessctl -e4 -n2 set 5%+
Before merging configuration changes, verify:
This practice prevents user confusion from conflicting examples and reduces maintenance overhead from scattered, inconsistent configuration references.
Use CSS solutions instead of JavaScript state management for simple styling and interactions. This approach improves maintainability, reduces complexity, and follows web standards best practices.
Examples of when to apply this:
:hover pseudo-classes instead of onMouseEnter/onMouseLeave event handlersdisplay or visibility properties rather than React stateExample transformation:
// Instead of JavaScript state management:
const [isOpen, setIsOpen] = useState(false);
return (
<div onMouseEnter={() => setIsOpen(true)} onMouseLeave={() => setIsOpen(false)}>
{isOpen && <div className="dropdown-menu">...</div>}
</div>
);
// Use CSS-based solution:
return (
<div className="dropdown">
<div className="dropdown-menu">...</div>
</div>
);
/* CSS */
.dropdown:not(:hover) .dropdown-menu {
display: none;
}
This approach reduces JavaScript complexity, improves performance, and makes the code more maintainable by leveraging native browser capabilities.
Always ensure cleanup code executes and avoid creating dangling promises in error handling scenarios. Use try-catch-finally patterns for guaranteed cleanup, and avoid making error handlers async unless you properly handle promise rejections.
For test assertions and cleanup operations, collect data first, then perform assertions outside the error-prone section:
// Good: Assertions run even if errors occur
const lines = [];
let handle = null;
try {
handle = await fs.open(file);
for await (const line of handle.readLines()) {
lines.push(line);
}
} finally {
await handle?.close();
await fs.rm(file, { force: true });
}
expect(lines.length).to.equal(1);
expect(lines[0]).to.equal('before exit');
For async operations, use try-catch-finally instead of making error handlers async:
// Good: Proper cleanup with try-catch-finally
loadESM(async (esmLoader: any) => {
try {
await esmLoader.import(main, undefined, Object.create(null))
} catch (e) {
process.emit('uncaughtException', err);
} finally {
appCodeLoaded!();
}
});
// Avoid: Making error handlers async creates dangling promises
capturer._onerror = (error: string) => {
// Handle synchronously or use .then() for promises
winsOwnedByElectronProcess.then(() => {
stopRunning();
reject(error);
});
};
This pattern ensures that cleanup operations always execute and prevents unhandled promise rejections that can lead to application instability.
Always use safe patterns when working with optional, nullable, or potentially empty types. Avoid direct comparisons with optional values and ensure proper initialization of nullable members.
Key practices:
.value_or(default) instead of direct comparisons with optional types_richBlock{ nullptr })Example of unsafe vs safe optional handling:
// Unsafe - direct comparison with optional
if (modernValue == 1u) // optional<uint32_t> != uint32_t comparison
// Safe - use value_or for truthy check
if (modernValue.value_or(0) != 0)
// Unsafe - assuming non-null without check
theme.Pane().ActiveBorderColor() // crashes if Pane() returns null
// Safe - null check with ternary
const auto paneActiveBorderColor = theme.Pane() ? theme.Pane().ActiveBorderColor() : nullptr;
This prevents crashes from null dereferences, undefined behavior from uninitialized members, and logic errors from improper optional comparisons.
Use pytest.mark.parametrize to consolidate similar test cases instead of duplicating test code. This approach improves maintainability, reduces code duplication, and ensures comprehensive test coverage across different scenarios.
When you find yourself writing multiple test functions that follow the same pattern with different inputs or expected outputs, combine them into a single parameterized test. This makes it easier to add new test cases and ensures consistent testing logic.
Example of consolidating duplicate tests:
# Instead of multiple similar tests:
def test_git_ref_spec_resolve_branch():
refspec = GitRefSpec(branch="main")
refspec.resolve(mock_fetch_pack_result)
assert refspec.ref == b"refs/heads/main"
def test_git_ref_spec_resolve_tag():
refspec = GitRefSpec(revision="v1.0.0")
refspec.resolve(mock_fetch_pack_result)
assert refspec.ref == annotated_tag(b"refs/tags/v1.0.0")
# Use parameterization:
@pytest.mark.parametrize("input_type,input_value,expected_ref", [
("branch", "main", b"refs/heads/main"),
("revision", "v1.0.0", annotated_tag(b"refs/tags/v1.0.0")),
("revision", "abc", b"refs/heads/main"),
])
def test_git_ref_spec_resolve(input_type, input_value, expected_ref):
kwargs = {input_type: input_value}
refspec = GitRefSpec(**kwargs)
refspec.resolve(mock_fetch_pack_result)
assert refspec.ref == expected_ref
This approach is particularly valuable when testing different error conditions, input formats, or configuration options. It also makes it easier to identify gaps in test coverage and add new test cases systematically.
When implementing configuration changes that need to be applied at runtime, follow these practices:
// Don't do this:
if (COMMAND.contains("monitorv2")) {
g_pConfigManager->handleMonitorv2();
g_pConfigManager->m_wantsMonitorReload = true;
}
// Do this instead:
g_pEventLoopManager->doLater([this] {
g_pConfigManager->m_wantsMonitorReload = true;
});
// For dynamic config that changes via hyprctl:
static auto PDISABLELOGS = CConfigValue<Hyprlang::INT>("debug:disable_logs");
// Not this (copies value once):
Debug::coloredLogs = std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("debug:colored_stdout_logs"));
configStringToInt and similar utilities for consistent configuration parsing instead of implementing custom parsing logic.// Use existing utility:
PANIM->second.internalEnabled = configStringToInt(ARGS[1]);
// Instead of custom parsing:
if (ARGS[1] == "on" || ARGS[1] == "true" || ARGS[1] == "1")
PANIM->second.internalEnabled = true;
set flag rather than implementing custom existence checking.This approach ensures configuration changes are processed consistently, can be updated dynamically, and maintain proper state management throughout the application lifecycle.
When working with data structures, especially ropes and collections, avoid algorithms that result in quadratic time complexity when linear alternatives exist. Common patterns to watch for include repeated indexing operations and nested loops over related data sets.
Key anti-patterns:
(0..=cursor_char).rev().find(|&i| !is_word(text.char(i))) is O(W*log(N))code_actions_on_save.iter().any(|a| match &x.kind { ... }) can be O(M*N)Better approaches:
text.chars_at(cursor_char).take_while(is_word).count() is O(log(N)+W)let actions_set: HashSet<_> = code_actions_on_save.iter().collect() makes lookups O(1)partition_point instead of binary_search_by_key when you don’t need the exact matchExample transformation:
// Inefficient O(W*log(N)) - repeated rope indexing
let start = (0..=cursor_char)
.rev()
.find(|&i| !is_word(text.char(i)))
.map(|i| i + 1)
.unwrap_or(0);
// Efficient O(log(N)+W) - iterator-based
let start = cursor_char - text.chars_at(cursor_char)
.reversed()
.take_while(|&c| is_word(c))
.count();
Always consider the complexity of your algorithm, especially when dealing with text processing, search operations, or nested data access patterns.
Write documentation that matches both your audience’s expertise level and the language’s conventional formats. For technical documentation, use language-specific conventions (like Rust’s doc comments). For tutorials or learning materials, prefer step-by-step explanations that minimize cognitive load.
Example:
// Technical API documentation - uses language conventions
/// Processes the input string and returns a formatted result
///
/// # Arguments
/// * `input` - The string to process
pub fn process_string(input: &str) -> String { }
// Tutorial/Learning documentation - uses simpler, step-by-step format
// Step 1: First, create a new string variable
// Step 2: Add your text to the variable
// Step 3: Call the process_string function with your variable
Consider your audience’s familiarity with the codebase and technical concepts when choosing between detailed technical documentation and simplified, step-by-step explanations. Always follow the language’s documentation conventions while maintaining appropriate detail level for the target readers.
Use clear, descriptive names while avoiding redundant qualifiers. Choose full words over abbreviations unless the abbreviated form is widely recognized. When a type or context already implies certain qualities, avoid repeating them in the name.
Good examples:
// Good: Clear, descriptive names
let preferred = if cfg!(all(windows, target_arch = "aarch64")) { ... }
fn find_pyvenv_cfg_version_conflict(&self) -> Option<(Version, Version)> { ... }
// Bad: Unnecessary qualifiers, abbreviations
let maybe_index_url: Option<&Url> = ... // Use just 'index_url' - Option implies maybe
let auth_indexes: AuthIndexes = ... // Use just 'indexes' in auth context
let tool_py_req = ... // Use 'tool_python_request' instead
Maintain naming consistency with existing codebase patterns. If a particular name is used consistently throughout the codebase (e.g., ‘s’ for pluralization), follow that convention unless there’s a compelling reason to change it.
Use Rust’s structural patterns to write more idiomatic and maintainable code. This includes:
// Prefer if !condition { return } if !other_condition { return } // main logic
2. Leverage pattern matching and destructuring:
```rust
// Instead of
let response = response.body_mut().read_to_end(&mut body).await?;
if response.status().is_success() {
// handle success
}
// Prefer
let Some((buffer, buffer_position)) = self.buffer.read(cx)
.text_anchor_for_position(position, cx)
else { return };
// Prefer signature_help_task: None,
4. Utilize iterator combinators to flatten logic:
```rust
// Instead of
.get_diagnostics(server_id)
.map(|diag| {
diag.iter()
.filter(...)
.map(...)
.collect()
})
// Prefer
.get_diagnostics(server_id)
.into_iter()
.flat_map(...)
These patterns improve code readability, reduce complexity, and make the code more maintainable by leveraging Rust’s built-in features effectively.
Use GitHub Actions native features and follow best practices to create maintainable, secure, and reliable CI workflows:
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
# DO THIS - scope permissions per job
jobs:
build:
permissions:
contents: read
attestations: write
id-token: write
# INSTEAD OF THIS - overly broad permissions
permissions:
contents: read
attestations: write
id-token: write
These practices improve workflow reliability, security, and maintainability while making troubleshooting easier.
Always mask sensitive tokens, credentials, and secrets in CI/CD workflows to prevent accidental exposure in logs or build outputs. In GitHub Actions, use the ::add-mask:: command before outputting or storing sensitive values in environment variables.
Example:
- name: "Get AWS CodeArtifact token"
run: |
UV_TEST_AWS_TOKEN=$(aws codeartifact get-authorization-token \
--domain tests \
--domain-owner ${{ secrets.AWS_ACCOUNT_ID }} \
--region us-east-1 \
--query authorizationToken \
--output text)
echo "::add-mask::$UV_TEST_AWS_TOKEN"
echo "UV_TEST_AWS_TOKEN=$UV_TEST_AWS_TOKEN" >> $GITHUB_ENV
This practice should be applied consistently for all types of authentication tokens (AWS, GCP, API keys, etc.) to maintain security and prevent credential leakage. Even in private repositories, proper token masking is essential for security best practices and to prevent credentials from being visible in workflow logs that team members can access.
Error messages should provide clear, actionable information that helps users understand and resolve the problem. Each error should:
Example of improving error messages:
// Instead of:
#[error(transparent)]
ManagedPythonError(#[from] managed::Error),
// Prefer:
#[error("Failed to discover managed Python installations")]
ManagedPythonError(#[from] managed::Error),
// Even better with context and remedy:
#[error("Failed to authenticate with {url}")]
#[error("hint: Check your credentials or configure authentication using UV_INDEX_{index}_USERNAME")]
AuthenticationError { url: String, index: String }
When designing error handling:
Keep event handlers synchronous to prevent race conditions and timing issues. Async operations within event handlers can cause deadlocks, missed events, and unpredictable behavior.
Why this matters: Event handlers must execute synchronously to ensure proper event ordering and prevent race conditions. When async operations are introduced into event handlers, they can cause events to be missed, create deadlocks with message passing, or lead to cleanup operations happening at the wrong time.
Guidelines:
Example of problematic pattern:
// BAD: Async event handler can cause timing issues
private async _onPage(page: Page): Promise<void> {
this._pages.add(page);
this.emit(Events.BrowserContext.Page, page);
await this._mockingProxy?.instrumentPage(page); // This breaks synchronous event flow
}
// BAD: Immediate cleanup prevents event delivery
close() {
this._socket.close();
eventsHelper.removeEventListeners(this._eventListeners); // Client never receives 'close' event
}
Better approach:
// GOOD: Keep handler synchronous, defer async work
private _onPage(page: Page): void {
this._pages.add(page);
this.emit(Events.BrowserContext.Page, page);
// Schedule async work separately
this._instrumentPageAsync(page);
}
private async _instrumentPageAsync(page: Page) {
await this._mockingProxy?.instrumentPage(page);
}
This principle prevents deadlocks, ensures event ordering, and maintains predictable async behavior throughout the application.
Always validate system capabilities and existing configuration state before generating new configuration entries or profiles. This prevents unnecessary configuration generation, improves startup performance, and avoids presenting unusable options to users.
Check system prerequisites, existing installations, and user capabilities before creating configuration entries. For example, when generating profile installers, verify if the target software is already installed or if the installation mechanism is available.
Example from PowerShell profile generation:
PowershellCoreProfileGenerator powerShellGenerator{};
_executeGenerator(powerShellGenerator);
const auto isPowerShellInstalled = !powerShellGenerator.GetPowerShellInstances().empty();
if (!isPowerShellInstalled)
{
// Only generate the installer stub profile if PowerShell isn't installed.
PowershellInstallationProfileGenerator pwshInstallationGenerator{};
_executeGenerator(pwshInstallationGenerator);
}
This approach prevents generating configuration that would be immediately marked for deletion, reduces UI clutter by hiding irrelevant options, and avoids potential startup performance impacts from unnecessary configuration processing. Always consider whether configuration generation should be conditional based on system state rather than generating everything and cleaning up afterward.
Context managers must follow a crucial algorithmic constraint: each execution path must yield exactly once. Multiple yields in the same path lead to unpredictable behavior, while no yields prevent proper resource management.
When implementing context managers with @contextlib.contextmanager:
Example of correct implementation:
@contextlib.contextmanager
def valid_context_manager(condition):
# Setup code
try:
if condition:
yield "success"
return # Early return prevents reaching the next yield
yield "alternative"
finally:
# Cleanup code always executed
print("Cleaning up")
This pattern ensures the algorithm’s invariant of “yield exactly once” regardless of which execution path is taken, maintaining reliable resource acquisition and release.
Always mark variables, parameters, and methods as const when they don’t modify state. This improves code safety, enables compiler optimizations, and makes intent clearer to readers.
Apply const in these scenarios:
const auto* command_line = base::CommandLine::ForCurrentProcess();bool IsDetachedFrameHost(const content::RenderFrameHost* rfh)bool IsWirelessSerialPortOnly() const;const display::Screen* screen = display::Screen::GetScreen();Example transformation:
// Before
auto* command_line = base::CommandLine::ForCurrentProcess();
display::Screen* screen = display::Screen::GetScreen();
bool IsDetachedFrameHost(content::RenderFrameHost* rfh);
// After
const auto* command_line = base::CommandLine::ForCurrentProcess();
const display::Screen* screen = display::Screen::GetScreen();
bool IsDetachedFrameHost(const content::RenderFrameHost* rfh);
Const correctness prevents accidental modifications, enables the compiler to catch errors early, and serves as documentation of your code’s intent. When in doubt, start with const and remove it only if modification is necessary.
Prefer code structures that minimize nesting levels and improve readability through early returns, pattern matching, and avoiding deeply nested assignments.
Use early returns and let-else patterns to reduce nesting:
// Instead of nested if-let
if let Some(doc) = doc {
if let Some(version) = document_version {
if version != doc.version() {
log::info!("Version mismatch");
return;
}
}
// process doc
}
// Prefer early returns and let-else
let Some(doc) = self
.documents
.values_mut()
.find(|doc| doc.uri().is_some_and(|u| u == uri))
else {
return;
};
if let Some(version) = document_version {
if version != doc.version() {
log::info!("Version mismatch");
return;
}
}
// process doc
Use match statements instead of nested conditionals when appropriate, and avoid let blocks that increase indentation unnecessarily. Don’t create deeply nested assignments as they are hard to read and don’t fit with the codebase style. When possible, use mutable variables in the same scope rather than introducing additional nesting levels.
Error messages should be clear, accurate, and contextually appropriate to help users understand what went wrong and how to fix it. Use complete, descriptive terms instead of abbreviations or technical jargon that may confuse users. Ensure error messages accurately reflect the actual capabilities and constraints of the system rather than copying generic messages that may not apply.
Key principles:
Example from the discussions:
<!-- Better: Clear and complete terminology -->
<value>An invalid regular expression was found.</value>
<!-- Avoid: Abbreviated or potentially misleading terms -->
<value>An invalid regex was found.</value>
When encountering unhandled cases, consider using explicit error detection (like assertions) rather than returning empty or default values that mask the underlying problem.
Use strong typing and early validation to handle optional values and prevent null-related issues. Prefer enums and specific types over strings when dealing with optional data, and validate optional values as early as possible in the data flow.
Key practices:
Example:
// Instead of
struct Config {
kind: String, // Could be "realm" or "index"
value: Option<String>
}
// Prefer
enum ConfigKind {
Realm(String),
Index(String)
}
struct Config {
kind: ConfigKind,
value: Option<String>
}
// Use bool::then for cleaner optional handling
let value = condition.then(|| compute_value());
// Validate optional data early
fn get_project_version(doc: &mut Document) -> Result<Version, Error> {
let project = doc.get("project")
.ok_or(Error::MissingProject)?;
let version = project
.get("version")
.and_then(Item::as_value)
.and_then(Value::as_str)
.ok_or(Error::MissingVersion)?;
Version::from_str(version)
}
---
## Follow established naming conventions
<!-- source: astral-sh/uv | topic: Naming Conventions | language: Markdown | updated: 2025-06-11 -->
Adhere to established naming conventions for files, variables, functions, and configuration options to maintain consistency and clarity throughout the codebase and documentation.
- Use standardized capitalization for common files (`README.md` instead of `Readme.md`, `LICENSE` without file extension)
- Maintain consistency when referring to environment variables (use either `$HOME` or `~` throughout, don't mix styles)
- Avoid using special name patterns (like dunders `__name__`) for regular functions to prevent confusion
- Choose names that clearly communicate purpose and scope
```python
# Incorrect: Using dunder name for regular function
def __main__():
process_data()
# Correct: Use standard naming for regular functions
def main():
process_data()
In documentation, maintain consistent reference style:
# Inconsistent
- `$XDG_CACHE_HOME/uv` or `~/.cache/uv` on Unix systems
# Consistent
- `$XDG_CACHE_HOME/uv` or `$HOME/.cache/uv` on Unix systems
Choose identifier names that clearly convey their purpose without requiring users to understand implementation details. If reviewers struggle to understand what a name means, it likely needs improvement.
When naming functions or settings:
Examples:
// Less clear
"line_number_base_width": 4
// Better - describes what it actually means
"min_line_number_digits": 4
// Unclear boolean (what does "true" actually mean?)
"focus_skip_active_file": true
// Better as an enum
enum AutoFocus {
First,
SkipActive
}
// Unnecessarily verbose
"workspace::IncreaseOpenDocksSizeByOffset"
// Better - removes redundancy while preserving meaning
"workspace::IncreaseDocksSize"
When handling events in web applications, especially those involving network-triggered UI updates or real-time data streams, prefer event delegation over individual element listeners for better performance and maintainability. Use container-level event listeners and check the event target rather than attaching listeners to each individual element.
This approach is particularly important when dealing with dynamic content that may be updated based on network responses, websocket messages, or API calls, as it ensures event handlers remain functional even when DOM elements are added or removed dynamically.
Example:
// Preferred: Event delegation
gBrowser.tabContainer.addEventListener('dblclick', (event) => {
if (event.target.matches('.tab-label')) {
// Handle the event
}
});
// Avoid: Individual listeners on each element
tabs.forEach(tab => {
tab.addEventListener('dblclick', handler);
});
This pattern reduces memory overhead and ensures consistent behavior when UI elements are dynamically updated from network data sources.
Design APIs to be simple and idiomatic to JavaScript/TypeScript while maintaining proper encapsulation. Avoid complex type unions, forced undefined parameters, or implementation details leaking through interfaces.
Key principles:
Example - Instead of:
interface RequestInitiator {
kind: InitiatorKind.Extension;
extensionId: string;
} | {
kind: InitiatorKind.Internal;
reason: string;
}
function decode(content: Uint8Array, options: { uri: Uri | undefined }): Promise<string>
Prefer:
class RequestInitiator {
constructor(
readonly kind: InitiatorKind,
readonly identifier: string
) {}
}
function decode(content: Uint8Array, options?: { uri?: Uri }): Promise<string>
When implementing search or traversal algorithms, use short-circuit evaluation strategically to avoid unnecessary computation while ensuring correctness. Short-circuiting is beneficial when the first match is sufficient, but can lead to incorrect results when complete information is needed.
For example, when implementing a search function:
// Good: Use short-circuit when first match is sufficient
fn find_python_installation(installations: &[Installation]) -> Option<&Installation> {
installations.iter().find(|installation|
request.matches_installation(installation))
}
// Good: Use closure to make short-circuit logic clearer
let (db, actual_rev, maybe_task) = || -> Result<(GitDatabase, GitOid, Option<usize>)> {
// Short-circuit early if we already have the commit
if let (Some(rev), Some(db)) = (self.git.precise(), &maybe_db) {
if db.contains(rev) {
debug!("Using existing Git source `{}`", self.git.repository());
return Ok((maybe_db.unwrap(), rev, None));
}
}
// Continue with fetching otherwise...
}();
// Bad: Using short-circuit when complete information is needed
// @any isn't sorted by version during discovery because we short-circuit
// when we find an interpreter that meets the request
// @latest needs to scan ALL Python interpreters to select the latest version
Consider the full requirements before deciding on a traversal strategy. When implementing algorithms that search or process collections:
.find()) when the first match is sufficient.filter() + .max_by_key()) when you need to examine all elementsWhen identifying test patterns in code, use specific equality predicates (#eq?) instead of list inclusion predicates (#any-of?) when matching against a single value. This improves clarity and can avoid potential false positives in test detection.
For example, when matching the “each” method for parameterized tests:
// Prefer this:
(#eq? @_property "each")
// Instead of this when there's only one value:
(#any-of? @_property "each")
This practice ensures more precise test pattern recognition, especially important for parameterized tests where accurate detection affects test execution and reporting.
When setting file permissions through system calls like chmod, always use explicit octal notation (with the 0o prefix) rather than decimal integers. Decimal integers in permission contexts can lead to unintended access rights, creating security vulnerabilities through incorrect file permissions.
For example, instead of:
os.chmod("foo", 644) # Incorrect - decimal integer
Use:
os.chmod("foo", 0o644) # Correct - explicit octal notation
The decimal value 644 is not equivalent to the octal value 0o644, and this mismatch can lead to improper permission settings that may expose sensitive files to unauthorized access. Always verify permission values in security-sensitive operations.
Use consistent and descriptive naming conventions across the codebase:
Example:
# Instead of:
[editor.bufferline]
behaviour = "hidden"
matches_couter_limit = 100
# Prefer:
[editor.bufferline]
show = "never"
max-matches = 100
# Group related commands with semantic prefixes:
:align-text-left
:align-text-center
:align-text-right
This convention ensures consistency, improves code readability, and makes configuration more intuitive for users. Descriptive names make the purpose immediately clear, while consistent casing helps distinguish between different types of identifiers.
Always pin GitHub Actions to specific commit hashes rather than version tags (like @v4). Using version tags is a security vulnerability as the tag owner could change what commit the tag points to, potentially introducing malicious code into your workflow. This is a common supply chain security best practice.
Example:
# INSECURE - Using version tag
steps:
- name: Checkout Homebrew
uses: actions/checkout@v4
# SECURE - Using commit hash
steps:
- name: Checkout Homebrew
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
Including the version as a comment after the hash helps with maintainability while preserving security.
When documenting environment variables and configuration options, explicitly list all supported value formats rather than using vague descriptions. Use individual backticks around each supported value for clear formatting.
Avoid vague descriptions like “If a number is specified, it will also be used as the terminal width.” Instead, be comprehensive and specific about what formats are accepted.
Example:
| `PLAYWRIGHT_FORCE_TTY` | | Whether to produce output suitable for a live terminal. Supports `true`, `1`, `false`, `0`, `[WIDTH]`, and `[WIDTH]x[HEIGHT]`. `[WIDTH]` and `[WIDTH]x[HEIGHT]` specifies the TTY dimensions. | `true` when terminal is in TTY mode, `false` otherwise.
This approach helps users understand exactly what values they can provide and reduces configuration errors by eliminating ambiguity about supported formats.
When working with React in Vite projects, be precise about which transformation tools (Babel, SWC, Oxc, esbuild) handle specific aspects of React code processing. Different plugins use different tool combinations for JSX/TSX transformation versus React fast-refresh, and these can vary between development and build environments.
For example, when documenting or selecting a React plugin:
// Document precisely which tools handle which transformations
// @vitejs/plugin-react (without plugins)
// - dev: Babel (fast-refresh) + esbuild/Oxc (JSX)
// - build: esbuild/Oxc (JSX)
// @vitejs/plugin-react-swc (without plugins)
// - dev: SWC (fast-refresh + JSX)
// - build: esbuild/Oxc (JSX)
// @vitejs/plugin-react-oxc
// - dev: Oxc (fast-refresh + JSX)
// - build: Oxc (JSX)
This distinction is particularly important when migrating between plugins or when performance optimization is needed. Always verify compatibility with your project’s requirements, especially when using custom Babel or SWC configurations.
When designing APIs, prioritize explicit parameter identification over implicit context. APIs with clear, unambiguous parameters improve implementation, maintenance, and usage. Whenever a function could operate on multiple resources or have ambiguous behavior, include explicit parameters to clarify the intent.
Example of problematic API:
func language-server-workspace-configuration(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
// Ambiguous - which language server will receive this configuration?
func additional-language-server-workspace-configuration(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
Improved API:
func language-server-workspace-configuration(language-server-id: string, worktree: borrow<worktree>) -> result<option<string>, string>;
// Explicit - clearly identifies both the source and target language servers
func additional-language-server-workspace-configuration(
source-language-server-id: string,
target-language-server-id: string,
worktree: borrow<worktree>
) -> result<option<string>, string>;
Similarly, when designing RPC calls, ensure parameters are placed on the appropriate side of the interface. Parameters that can only be reasonably handled by the client (like UI focus control or selection) should not be included in server-side RPC parameters but should instead be handled in client-side logic or returned as part of the response.
Use structured environment variable handling with explicit validation instead of directly accessing ENV hash. Implement proper parsing for boolean values, default values, and type conversion. Consider making paths user-specific when creating temporary configurations.
For boolean environment variables, handle falsy values properly:
# Instead of this:
if ENV["HOMEBREW_SOME_FLAG"].present?
# Do something
end
# Do this:
if Homebrew::EnvConfig.some_flag?
# Do something
end
# When implementing environment variable handlers:
def env_method_name(env, hash)
if hash[:boolean]
define_method(method_name) do
env_value = ENV.fetch(env, nil)
falsy_values = %w[false no off nil 0]
if falsy_values.include?(env_value&.downcase)
false
else
ENV[env].present?
end
end
end
end
For configuration paths that may be shared across users, add user-specific identifiers:
# Instead of this:
zdotdir = Pathname.new(HOMEBREW_TEMP/"brew-zsh-prompt")
# Do this:
zdotdir = Pathname.new(HOMEBREW_TEMP/"brew-zsh-prompt-#{Process.euid}")
This approach provides consistent interpretation of configuration values, reduces bugs from unexpected environment variable content, and prevents permission issues with shared configuration paths.
When processing user input that will be used in shell commands, implement shell-specific escaping mechanisms to prevent command injection vulnerabilities. Different shells (bash, PowerShell, zsh, fish) have different escaping requirements that must be handled appropriately.
For example, instead of using a generic approach like:
// Unsafe - generic character removal
const bannedChars = /[\`\$\|\&\>\~\#\!\^\*\;\<\"\']/g;
newPath = newPath.replace(bannedChars, '');
Implement shell-specific escaping:
// Safe - proper shell-specific escaping
if (shellType === 'bash' || shellType === 'zsh') {
// POSIX-compliant escaping for single quotes
if (path.includes("'")) {
path = path.replace(/'/g, "'\\''");
}
} else if (shellType === 'fish') {
// Fish uses backslash escaping
if (path.includes("'")) {
path = path.replace(/'/g, "\\'");
}
} else if (shellType === 'powershell') {
// PowerShell uses doubled single quotes
if (path.includes("'")) {
path = path.replace(/'/g, "''");
}
}
This approach prevents security vulnerabilities by ensuring that user input cannot break out of string contexts to execute arbitrary commands.
Always sanitize input data before using it in sensitive operations to prevent injection vulnerabilities. This applies to shell commands, file operations, and URL handling.
For shell commands:
# VULNERABLE: Direct interpolation of variables into command
full_command = `#{HOMEBREW_BREW_FILE} #{brew_command} #{argument}`
# SECURE: Escape each argument properly
require 'shellwords'
full_command = [HOMEBREW_BREW_FILE, brew_command, argument].compact
.map { |arg| Shellwords.escape(arg) }
For file operations:
# VULNERABLE: Using IO.read/Kernel.open with non-constant values
content = IO.read(filepath)
# SECURE: Use File.read instead
content = File.read(filepath)
For URL operations:
# VULNERABLE: Using URI.open with non-constant values
response = URI.open(generated_url).read
# SECURE: Use URI().open instead
response = URI(generated_url).open.read
These patterns help prevent several classes of security vulnerabilities, including command injection, arbitrary file access, and server-side request forgery. Always assume input data could be malicious and handle it accordingly.
Documentation should use direct, precise language that accurately describes components and their behavior. Maintain consistent grammatical structure throughout related documentation sections for improved readability.
For command-line options and parameters:
Example improvements:
- /// Whether to prefer uv-managed or system Python installations.
+ /// Disable use of uv-managed Python distributions.
+ ///
+ /// Instead, uv will search for a suitable Python installation on the system.
- /// Only print the final value
+ /// Only show the version
+ ///
+ /// By default, uv will show the project name before the version.
- /// The directory to store the Python installation in.
+ /// The directory Python installations are stored in.
- /// Upgrades will not remove lower installed patch versions.
+ /// During an upgrade, uv will not uninstall outdated patch versions.
For grammatical consistency, maintain the same tense within related sections, especially in enums where options are presented together. This improves scanning and comprehension of documentation.
Always validate function parameters and configuration options at the beginning of functions, providing specific and actionable error messages that guide users toward correct usage. This prevents downstream errors and improves developer experience.
Key practices:
Example:
static validateNumber(value: string, options: { min?: number, max?: number }): string {
if (/[^0-9]/.test(value))
throw new InvalidArgumentError('Not a number.');
const parsed = parseInt(value, 10);
if (isNaN(parsed))
throw new InvalidArgumentError('Not a number.');
if (options.min !== undefined && parsed < options.min)
throw new InvalidArgumentError(`Expected a number greater than ${options.min}.`);
if (options.max !== undefined && parsed > options.max)
throw new InvalidArgumentError(`Expected a number less than ${options.max}.`);
return value;
}
// Validate enum values
if (!['begin', 'end'].includes(options.debug))
throw new Error(`Unsupported debug mode "${options.debug}", must be one of "begin" or "end"`);
// Defensive checks for edge cases
if (!options.expectedText)
throw new Error('expectedText is required for class validation');
This approach catches errors early, provides clear guidance to developers, and prevents cascading failures deeper in the system.
When you find yourself writing similar code patterns multiple times, extract them into reusable methods, constants, or leverage existing helpers. This improves maintainability and reduces the chance of inconsistencies.
Examples of what to extract:
// Extract to: private _enqueueFrames(count: number, buffer: Buffer) { for (let i = 0; i < count; ++i) this._frameQueue.push(buffer); }
2. **Magic values used multiple times** - Use constants:
```typescript
// Instead of repeating colors:
const color = elements.length > 1 ? '#f6b26b7f' : '#6fa8dc7f';
// Use constants:
const HIGHLIGHT_COLOR_MULTIPLE = '#f6b26b7f';
const HIGHLIGHT_COLOR_SINGLE = '#6fa8dc7f';
// Instead of custom implementation, use existing helper:
const callLocation = wrapFunctionWithLocation((location: Location, ...args) =>
this._modifier('skip', location, ...args)
);
// Instead of retrieving from map twice:
const data = this._dataByTestId.get(params.testId);
this._updateTest(data); // Pass the data directly
Avoid redundant memory allocations and copies when simpler alternatives exist. This includes:
Example - Instead of:
const ext_lower = try std.ascii.allocLowerString(alloc, ext);
defer alloc.free(ext_lower);
if (std.mem.eql(u8, ext_lower, ".png")) {
Prefer:
if (std.ascii.eqlIgnoreCase(ext, ".png")) {
This guidance helps reduce memory pressure and improve performance by eliminating unnecessary allocations and copies. When working with data structures that handle their own memory management, verify if they copy inputs before performing manual duplication.
Names should clearly and accurately reflect the purpose of variables, methods, and other identifiers. Follow these principles:
Example 1: Instead of:
var macosHidden: Bool
Use:
var isAppIconHiddenFromMacOS: Bool
Example 2: When a function’s responsibility expands:
// Before: only hides elements
func hideCustomTabBarViews() {
// hide some elements
}
// After: both hides and shows elements
func resetCustomTabBarViews() {
// hide some elements
// show other elements
}
Example 3: For notification naming, follow consistent patterns:
// Avoid inconsistent patterns
static let ghosttyToggleMaximize = Notification.Name(...)
// Follow "[Subject] [Event (past participle)]" pattern
static let ghosttyFullscreenDidToggle = Notification.Name(...)
Ensure configuration files are precise and stable to prevent unexpected build failures and runtime issues. This includes:
Use correct syntax in configuration files Validate JSON files for syntax errors like extra commas, which can cause cryptic error messages during builds.
// Incorrect
{
"$schema": "https://turborepo.com/schema.json",,
"ui": "tui"
}
// Correct
{
"$schema": "https://turborepo.com/schema.json",
"ui": "tui"
}
Specify exact versions for critical dependencies
Use exact versions instead of ranges (^ or ~) for dependencies when stability is critical, especially in test fixtures or shared packages.
// Less stable (allows minor updates)
"dependencies": {
"@types/d3-scale": "^4.0.2"
}
// More stable (locks exact version)
"dependencies": {
"@types/d3-scale": "4.0.2"
}
Explicitly specify package manager
Include the packageManager field in package.json to ensure consistent behavior across environments, especially when using version wildcards (*).
{
"name": "monorepo",
"packageManager": "pnpm@8.14.0",
"dependencies": {
"util": "*"
}
}
Establish clear sources of truth
Define which configuration files are authoritative for specific settings. For example, make package.json’s engines field the definitive source for Node.js version requirements.
"engines": {
"node": "22.x"
}
These practices reduce configuration drift, prevent unexpected behavior, and help maintain consistency across environments and team members.
Applications should gracefully handle different network connectivity states and provide appropriate feedback to users. Follow these guidelines:
Example for offline handling:
if network_settings.connectivity.is_offline() {
writeln!(
printer.stderr(),
"{}",
format_args!(
"{}{} Operation is not possible because network connectivity is disabled (i.e., with `--offline`)",
// formatting details
)
)?;
return Ok(ExitStatus::Failure);
}
Example for checking cache before network request:
// Check if we already have the resource locally before making a network request
if let (Some(rev), Some(db)) = (self.git.precise(), &maybe_db) {
if db.contains(rev) {
debug!("Using existing Git source `{}`", self.git.repository());
return Ok((maybe_db.unwrap(), rev, None));
}
}
// Only make network request if needed
// Handle different status codes appropriately
let decision = status_code_strategy.handle_status_code(status_code, index, capabilities);
Always verify pointers are valid before dereferencing to prevent crashes and undefined behavior. This applies to regular pointers, weak pointers, and return values from C functions that may return null.
Use implicit bool conversion instead of explicit null comparisons for cleaner code:
// Preferred
if (ptr) {
ptr->doSomething();
}
// Avoid
if (ptr != nullptr) {
ptr->doSomething();
}
For weak pointers, use the appropriate check method:
operator bool or .expired() when you only need to test validity.lock() only when you need the actual shared pointerApply guard patterns with early returns to reduce nesting:
if (!ptr)
return;
ptr->doSomething();
Pay special attention to C function returns that may be null:
const char* env = getenv("VAR_NAME");
if (!env)
return defaultValue;
Critical areas requiring null checks include: pointer dereferences in event handlers, accessing monitor/window objects that may be destroyed, and any pointer obtained from external APIs or lookups.
Maintain clean code organization by separating concerns into appropriate classes and files. Extract large functions into smaller, focused methods, and avoid creating monolithic patches that become difficult to maintain.
Key principles:
ZenDOMOperatedFeature and moving constructor logic into init() methodsExample of good organization:
// Instead of adding methods directly to an existing large class
class ZenSplitViewLinkDrop {
constructor(zenViewSplitter) {
this.#zenViewSplitter = zenViewSplitter;
}
init() {
// Initialize functionality
}
}
// Instead of large patches, extract to functions
gZenCompactModeManager.flashSidebarIfAllowed(aInstant);
// Instead of inline patches, use event listeners
popupElement.addEventListener('popupshowing', this.updateContextMenu.bind(this));
This approach improves maintainability, reduces conflicts, and makes code easier to understand and modify.
Always add clear comments explaining non-obvious code decisions such as magic numbers, arbitrary values, truncation limits, or special case handling. Convert magic numbers to named constants with explanatory comments when appropriate. This documentation helps future developers understand the reasoning behind code decisions and makes maintenance easier.
For magic numbers in code:
# Read enough bytes to detect HTML doctype while limiting file I/O
if File.read(filepath, 100).strip.downcase.start_with?(html_doctype_prefix)
For truncation limits:
# Maximum length of PR body is 65,536 characters so let's truncate release notes to half of that
body = github_release_data["body"].truncate(32_768)
For complex logic:
# These formulae must build on Intel macOS because they're required for CLT installation
NEW_INTEL_MACOS_MUST_BUILD_FORMULAE = %w[pkg-config pkgconf].freeze
Code without explanatory comments creates a burden for maintainers, forcing them to reverse-engineer the original author’s intent. Well-documented decisions reduce the cognitive load for future developers and decrease the likelihood of introducing bugs during modifications.
When writing tests, consider both thoroughness and execution time. For operations with significant overhead (like Python installations, downloads, or filesystem operations), it’s acceptable to consolidate multiple assertions into a single test.
// Instead of separate tests for each scenario:
#[test]
fn install_transparent_patch_upgrade_uv_venv() {
// Setup context only once
let context = TestContext::new_with_versions(&["3.13"]);
// Test installing a lower patch version
uv_snapshot!(context.filters(), context.python_install().arg("3.12.9"), /* ... */);
// Create a virtual environment with same context
uv_snapshot!(context.filters(), context.venv().arg("-p").arg("3.12"), /* ... */);
// Test version verification with same context
uv_snapshot!(context.filters(), context.run().arg("python").arg("--version"), /* ... */);
// Test installing a higher patch version without recreating the environment
uv_snapshot!(context.filters(), context.python_install().arg("3.12.10"), /* ... */);
}
When using snapshot testing, be conscious of brittleness. Try to make snapshots robust against implementation details while capturing essential behavior. For variable outputs, use focused filtering rather than replacing the entire expected output, or consider conditional snapshots for significantly different cases.
Prefer specific assertions (like .assert().success()) over empty snapshots when testing specific properties, as they provide better failure messages and are less likely to break on minor implementation changes.
APIs should maintain consistent behavior and avoid tight coupling to implementation details or environmental dependencies. Don’t make API methods conditionally available based on state, and avoid exposing filesystem paths or other environment-specific concerns in component interfaces.
Instead of conditional API availability:
// Avoid: API becomes undefined based on conditions
{onCancel ? (
<button onClick={onCancel}>Cancel</button>
) : null}
Use explicit state checks:
// Prefer: Explicit state checking with consistent API
{conversation.isSending() ? (
<button onClick={onCancel}>Cancel</button>
) : null}
Instead of tight coupling to filesystem:
// Avoid: Component knows about rootDir and filesystem
const TestResultView = ({ test, result, rootDir }) => {
// Component fetches files using rootDir
}
Decouple by pre-fetching data:
// Prefer: Include data explicitly, making component portable
const TestResultView = ({ test, result, preloadedSources }) => {
// Component works with provided data, no filesystem knowledge
}
This approach makes APIs more predictable, testable, and portable across different environments.
Always provide clear justification when modifying dependency configurations, including version updates, dependency types, or new additions. Consider the impact on stability, compatibility, and end users before making changes.
For version updates, avoid unnecessary churn by sticking with working versions unless there’s a compelling reason to upgrade (security fixes, required features, bug fixes). For dependency types, choose between regular dependencies, devDependencies, and peerDependencies based on actual usage patterns and user compatibility needs.
Example considerations:
Document the reasoning behind dependency configuration decisions to help future maintainers understand the trade-offs made.
Always redact sensitive credentials in URLs before logging, displaying in error messages, or serializing to prevent accidental exposure of authentication information. Use dedicated wrapper types like LogSafeUrl that automatically handle credential redaction when displaying URLs:
// INSECURE: Directly logging a URL with potential credentials
log::debug!("Processing URL: {}", url);
// SECURE: Using a wrapper that handles credential redaction
log::debug!("Processing URL: {}", LogSafeUrl::from(url));
Be consistent in your approach to credential redaction:
Apply redaction as early as possible in the code path to minimize the risk that future changes might accidentally expose credentials. When implementing redaction logic, clearly document which approach is used in different contexts to maintain security throughout the application.
When handling Option types that require early returns on None values, prefer the let-else pattern over verbose match statements or if-let constructs. This pattern improves code readability, reduces nesting, and makes the control flow more explicit.
The let-else pattern allows you to destructure an Option and immediately return or continue execution if the value is None, keeping the happy path at the main indentation level.
Prefer this:
let Some(context) = context else {
return;
};
let Some(capabilities) = self.capabilities.get() else {
return false;
};
let Some(last) = values_rev.peek() else {
return;
};
Instead of this:
if context.is_none() {
return;
}
let context = context.as_deref().expect("context has value");
match self.capabilities.get() {
Some(capabilities) => capabilities,
None => return false,
};
let last = match values_rev.peek() {
Some(last) => last,
None => return,
};
This pattern is particularly effective for guard clauses and input validation, where you want to handle the None case immediately and continue with the Some value. It reduces cognitive load by eliminating nested scopes and makes the error handling path explicit and concise.
Always validate configuration values and provide clear, actionable error messages when validation fails. Handle invalid values gracefully by either ignoring them or providing sensible defaults, and validate that configuration options are used in the correct context.
Key practices:
if (tabWidth === 0) { /* ignore invalid value */ }"--cache-strategy cannot be used without --cache"if (ignoreFilePaths.length === 0 && !withNodeModules) { ignoreFilePaths = [undefined]; }This prevents runtime crashes, improves user experience, and makes configuration errors easier to debug and fix.
Code should be readable and consistent: avoid inline “magic” expressions, prefer named values/helpers, and use uniform style primitives.
Apply:
const lastEdgeIndex = yy.getEdges().length - 1;
$$ = $LINKSTYLE;
yy.updateLink([lastEdgeIndex], $stylesOpt);
gap-* instead of mixing mr-*, mb-*):
<li v-for="{ iconUrl, featureName } in column" :key="featureName" class="flex gap-2 items-center">
<img :src="iconUrl" :alt="featureName" class="inline-block h-5 w-5" />
<span>{{ featureName }}</span>
</li>
"${args[@]}" for pass-through arguments).In Vue SFCs, keep templates declarative and driven by explicit data.
Rules
<script setup>: define typed constants/arrays in the script rather than building or embedding data via template expressions.v-for positional logic (index) for styling/behavior: instead, add an explicit property on each item (e.g., highlighted: true) and base :class/conditional rendering on that.Example (data-driven, no index)
<script setup lang="ts">
import { ref } from 'vue';
interface Feature { iconUrl: string; featureName: string; }
interface Column {
title: string;
description: string;
redirectUrl: string;
highlighted?: boolean;
features: Feature[];
}
const editorColumns: Column[] = [
{
title: 'Playground',
description: 'Basic features, no login',
redirectUrl: 'https://www.mermaidchart.com/play',
features: [
{ iconUrl: '/icons/icon-public.svg', featureName: 'Diagram stored in URL' },
{ iconUrl: '/icons/icon-terminal.svg', featureName: 'Code editor' },
{ iconUrl: '/icons/icon-whiteboard.svg', featureName: 'Whiteboard' },
],
},
{
title: 'Free',
description: 'Advanced features, free account',
redirectUrl: 'https://www.mermaidchart.com/app/sign-up',
highlighted: true,
features: [
{ iconUrl: '/icons/icon-folder.svg', featureName: 'Storage' },
{ iconUrl: '/icons/icon-terminal.svg', featureName: 'Code editor' },
],
},
];
const isVisible = ref(false);
</script>
<template>
<div v-if="isVisible" @click.self="isVisible = false">
<div class="flex gap-4">
<div
v-for="col in editorColumns"
:key="col.title"
class="w-80 p-6 m-6 shadow-sm"
:class="col.highlighted ? 'bg-white' : 'bg-[#dceef1]'"
>
<h3>{{ col.title }}</h3>
<p>{{ col.description }}</p>
</div>
</div>
</div>
</template>
This improves maintainability (template changes don’t silently break styling order) and makes behavior more testable and reviewable.
When an endpoint or syntax is already used as a contract (e.g., chart grammar shared across features, or a stateful editor URL), avoid creating parallel interfaces or polluting the contract with unrelated concerns.
Apply this as:
Example (clean stateful editor URL):
// Bad: pollutes a stateful URL used by the editor
const liveUrl =
'https://mermaid.live/edit?utm_source=mermaid_js&utm_medium=editor_selection&utm_campaign=open_source';
// Good: keep only the contract URL; send analytics separately
const liveUrl = 'https://mermaid.live/edit';
Avoid directly linking UI/static assets (e.g., icons, images) to external domains. Keep them inside the repository and reference them via local paths so builds don’t depend on third-party availability, reduce tracking/privacy exposure, and minimize supply-chain risk.
Example (local assets instead of remote URLs):
// Instead of:
// iconUrl: 'https://static.mermaidchart.dev/assets/icon-public.svg'
import iconPublic from '@/assets/icons/icon-public.svg';
import iconTerminal from '@/assets/icons/icon-terminal.svg';
import iconWhiteboard from '@/assets/icons/icon-whiteboard.svg';
interface Feature {
iconUrl: string;
featureName: string;
}
const featureColumns = ref<Feature[][]>([
[
{ iconUrl: iconPublic, featureName: 'Diagram stored in URL' },
{ iconUrl: iconTerminal, featureName: 'Code editor' },
{ iconUrl: iconWhiteboard, featureName: 'Whiteboard' },
],
]);
Apply this rule to all static resources used in the UI (icons, SVGs, logos, fonts) unless there is an explicit, approved exception with documented risk acceptance.
Ensure consistent formatting and precise terminology when documenting security-related concepts, access controls, and system boundaries. Inconsistent or imprecise language in security documentation can lead to misunderstandings about permissions, access patterns, and security mechanisms.
Key practices:
read-write tokens, read-only tokens)Example:
// Inconsistent - avoid
Read-write tokens allow access to the shared primary cache.
// Consistent - preferred
The `read-write` tokens allow full write access to your shared global cache.
This practice is critical for security documentation where imprecise language can lead to incorrect implementations or security vulnerabilities.
Avoid duplicating workflow steps across multiple CI/CD pipelines by extracting common functionality into reusable actions. This improves maintainability, reduces inconsistencies, and ensures proper cross-platform compatibility when needed.
When you find yourself copying similar workflow steps across multiple pipeline files, create a composite action instead. Pay special attention to cross-platform scenarios where caching or other features may require specific configuration.
Example of extracting a common dependency installation step:
# Before: Duplicated across multiple workflows
- name: Get yarn cache directory path
# ... repeated setup code
# After: Extract to .github/actions/install-dependencies/action.yml
- name: Install Dependencies
uses: ./.github/actions/install-dependencies
with:
enable-cross-platform-cache: true
For cross-platform workflows, ensure proper configuration like enableCrossOsArchive: true when caching between different operating systems. This prevents cache restoration failures when artifacts are saved on one platform and restored on another.
When documenting caching systems, clearly specify cache isolation boundaries and access scopes to prevent confusion about cache behavior. Distinguish between global shared caches and isolated caches, and explain how different access levels affect cache storage and retrieval patterns.
For example, when describing read-only access tokens:
The `read-only` access tokens can only read from the global remote cache. Task results produced with this type of access token will be stored in an isolated remote cache accessible _only_ by that specific branch in a CI context, and cannot influence the global shared cache. The isolated remote cache is accessible to all machines or agents in the same CI execution, enabling cache sharing during distributed task execution.
This approach helps developers understand:
Validate Unicode characters and detect potential homoglyph attacks where visually similar characters from different scripts could be used maliciously. Avoid overly broad patterns that automatically allow non-ASCII characters without proper validation, as these can hide security vulnerabilities.
When processing text input or configuration patterns, be cautious of Unicode characters that could be used to bypass security measures. For example, a Cyrillic ‘а’ (U+0430) looks identical to Latin ‘a’ (U+0061) but could be used to create deceptive URLs, variable names, or bypass filtering rules.
Instead of using broad Unicode acceptance patterns like:
[a-zA-Z]*[ÀÁÂÃÄÅÆČÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæčçèéêëìíîïðñòóôõöøùúûüýÿ][a-zA-Z]{3}[a-zA-Z]*
Consider explicitly allowlisting known legitimate Unicode words or implementing homoglyph detection to identify suspicious character substitutions. This prevents cases where malicious characters like é instead of , could be hidden by overly permissive patterns, as such substitutions have been used in real-world attacks.
Break down complex code structures into simpler, more readable forms to improve maintainability and reduce cognitive load. This involves several key practices:
Extract duplicate code into helper methods:
// Instead of duplicating logic:
if (write) {
new CommandBuilder()
.setWorkingDir(env.getWorkspace())
.addArg(modTidyValue.buildozer().getPathString())
.addArg("-f")
.addArg("-")
} else {
new CommandBuilder()
.setWorkingDir(env.getWorkspace())
.addArg(modTidyValue.buildozer().getPathString())
.addArg("-f")
.addArg("-")
}
// Extract common construction:
private CommandBuilder createBaseBuilder() {
return new CommandBuilder()
.setWorkingDir(env.getWorkspace())
.addArg(modTidyValue.buildozer().getPathString())
.addArg("-f")
.addArg("-");
}
Use early returns to reduce nesting:
// Instead of nested conditions:
if (artifact instanceof DerivedArtifact) {
return true;
} else if (artifact instanceof BasicActionInput || artifact instanceof VirtualActionInput) {
return isOutputPath(artifact, outputRoot);
} else {
return false;
}
// Use early returns:
if (artifact instanceof DerivedArtifact) {
return true;
}
if (artifact instanceof BasicActionInput || artifact instanceof VirtualActionInput) {
return isOutputPath(artifact, outputRoot);
}
return false;
Prefer switch expressions over if-else chains:
// Instead of if-else:
Mode mode;
if (testCase.getStatus() == Status.PASSED) {
mode = Mode.INFO;
} else {
mode = Mode.ERROR;
}
// Use switch expression:
Mode mode = switch (testCase.getStatus()) {
case PASSED -> Mode.INFO;
default -> Mode.ERROR;
};
Make implicit operations explicit for clarity:
// Instead of implicit this:
equals(platformValue)
// Be explicit:
this.equals(platformValue)
Break large methods into focused smaller methods when they handle multiple distinct responsibilities, and extract string literals into constants when they appear in multiple places or carry semantic meaning.
Properly manage executor service lifecycle to prevent resource leaks, deadlocks, and orphaned threads that can cause system inconsistencies.
Key practices:
invokeAny() over low-level submit().get() with manual cancellationPhaser instead of combining multiple lower-level mechanismsExample of proper executor management:
try (var executor = Executors.newSingleThreadExecutor(threadFactory)) {
// Submit tasks and get results within the try block
var future = executor.submit(callable);
return future.get(timeout, TimeUnit.SECONDS);
} // Executor automatically shuts down here
For cancellation scenarios, prefer structured approaches:
// Instead of manual future cancellation
var future = executor.submit(task);
future.cancel(true);
// Use invokeAny for timeout/cancellation semantics
return executor.invokeAny(List.of(task), timeout, TimeUnit.SECONDS);
This prevents common issues like deadlocks when futures are never scheduled, ensures proper resource cleanup, and avoids race conditions from orphaned threads modifying shared state after new operations have begun.
Choose specific, purpose-revealing names that clearly communicate intent rather than generic, abbreviated, or ambiguous terms. Names should describe what something does or represents, not what it doesn’t do.
Examples of improvements:
script_engine instead of generic engine to clarify the file’s purposeworkspace_diagnostics instead of abbreviated w_diagnostics for clarityshush instead of noop when the function has side effects (not truly a no-op)variables::expand() instead of expand_args() to be clearer about what it operates onApply this by:
engine, handler, manager without qualifying contextThis principle improves code readability and reduces the cognitive load for developers trying to understand unfamiliar code.
URLs in code should exclusively use ASCII characters for maximum security and compatibility. This prevents potential security vulnerabilities like homograph attacks and ensures consistent behavior across systems.
For domain names with non-ASCII characters:
xn-- prefixed domains)For path and query components:
When validating URLs, include checks to ensure they contain only ASCII characters. Provide clear error messages to guide users toward the proper encoding.
Example:
# Incorrect: URLs with non-ASCII characters
url = "https://🫠.sh/foo/bar"
url = "https://ßrew.sh/foo/bar"
# Correct: Use ASCII representations
url = "https://xn--sh-9ij.sh/foo/bar" # Punycode for domain
url = "https://brew.sh/foo%E4%B8%AD%E6%96%87/bar" # URL encoding for path
# For validation, use a regex to detect non-ASCII characters
ascii_pattern = /[^\p{ASCII}]+/
if url.match?(ascii_pattern)
puts "Please use the ASCII (Punycode, URL encoded) version of #{url}."
end
Configuration options should be designed with clarity, consistency, and user experience as primary concerns. This includes several key practices:
Clear and specific help text: Flag descriptions should explicitly explain their purpose and scope to avoid user confusion. For example, instead of generic descriptions, be specific about when and how the flag is used.
Intuitive syntax with units: When accepting time or quantity values, include units in the syntax for clarity. Use formats like 30s, 5m, 1h instead of raw numbers, and document the expected format.
Consistent behavioral patterns: Maintain consistent conventions across similar flags. For example, if 0 disables functionality in some flags, apply this pattern consistently across related options. If 0 means “run immediately” for some flags, use the same convention for similar flags to reduce user confusion.
Validation with helpful errors: Prefer clear error messages over warnings for invalid configuration values. This reduces warning spam and makes it easier to evolve behavior later. Provide actionable feedback when validation fails.
Proper option organization: Place configuration options in appropriate option classes that reflect their actual usage and dependencies, rather than generic catch-all classes.
Example of good configuration design:
@Option(
name = "timeout",
converter = DurationConverter.class,
help = "Timeout for action execution. Use format like '30s', '5m', or '1h'. " +
"Set to 0 to disable timeout.")
public Duration timeout;
This approach ensures configuration options are self-documenting, behave predictably, and provide a better developer experience.
Maintain consistent documentation style by following these guidelines:
<kbd> tags: <kbd>i</kbd>Example:
# Configuration
| Key | Description | Default |
| -------------- | ---------------------------- | ------- |
| `auto-format` | Enable auto-formatting | `false` |
Press <kbd>i</kbd> to enter **Insert** mode.
---
## Measure performance impacts
<!-- source: prettier/prettier | topic: Performance Optimization | language: JavaScript | updated: 2025-05-18 -->
Always benchmark and measure actual performance impacts before making optimization decisions, rather than relying on assumptions. Performance characteristics can vary significantly across different runtimes, data sizes, and usage patterns.
When optimizing code:
- Conduct micro-benchmarks for critical paths to compare alternatives
- Consider runtime-specific performance characteristics (e.g., "Array#at is slow on Node.js v16 and v18")
- Measure real-world performance improvements and adjust expectations accordingly
- Balance trade-offs between code clarity and performance based on actual data
Example from codebase:
```javascript
// Micro benchmarking showed trim().length was faster than regex
// Choose based on measurement, not assumption
const keepTypeCast = text.slice(locEnd(previousComment), locStart(node)).trim().length === 0;
// vs
const keepTypeCast = !/\S/.test(text.slice(locEnd(previousComment), locStart(node)));
For performance-critical code, document the reasoning behind optimization choices and include performance test cases that can detect regressions. When performance improves significantly (e.g., 10x faster), update test expectations to catch future performance degradations.
When writing build and deployment documentation, avoid hard-coding specific version numbers, toolchain assumptions, or environment-specific details that will become outdated or may not apply to all users. Instead, use generic language that describes the underlying requirement or constraint.
For example, instead of specifying exact versions like “Ubuntu 22.04” or “libc6 (>= 2.34)”, explain the general compatibility concern: “The CI may use a libc version greater than what your Ubuntu/Debian/Mint version requires.” Similarly, avoid assuming specific toolchain managers like rustup when providing build commands - not all users will have the same setup.
This approach ensures documentation remains accurate and useful over time, reduces maintenance burden, and provides better user experience across different development environments.
Example of brittle documentation:
# Assumes rustup is available
cargo +stable install --path helix-term --locked
Better approach:
# Works with any cargo installation
cargo install --path helix-term --locked
Documentation should include concrete, realistic examples that demonstrate practical usage rather than abstract concepts. This helps readers better understand the functionality and improves documentation accessibility for all skill levels.
Examples should:
Good example:
# Explaining a git blame command
:echo %sh{git blame -L %{cursor_line},+1 %{buffer_name}}
# Explaining variables
Set a format string for `format` to customize the blame message.
Variables are text placeholders wrapped in curly braces (`{variable}`).
Instead of just describing features abstractly, this approach shows actual usage patterns that readers can relate to and adapt for their needs. When technical terms are necessary, include brief explanations to make the documentation accessible to a wider audience.
CI workflows should use the most current versions of dependencies and ensure all required tools are available. Avoid testing against potentially stale submodules or bundled dependencies by checking out the target repository directly. Use self-installing tools and hooks that handle their own installation to prevent failures due to missing dependencies.
For repository dependencies, checkout the actual target repository rather than a repo containing it as a submodule:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
repository: astral-sh/ruff # Target repo, not the repo with submodule
For tool dependencies, prefer pre-commit hooks or actions that handle installation automatically:
- repo: https://github.com/astral-sh/uv-pre-commit # Self-installing hook
This approach ensures CI tests run against the latest code and don’t fail due to missing tools, improving reliability and reducing maintenance overhead.
When implementing new functionality or modifying existing code, always add corresponding tests that comprehensively cover the changes. This includes testing the main functionality, edge cases, error conditions, and different execution paths.
Key practices to follow:
Add tests for new functionality: Every new feature, method, or code path should have dedicated test coverage. As noted in one discussion: “The change affects the logic in RecursiveFileSystemTraversalFunction, I would still recommend adding a test case for that.”
Cover multiple scenarios: Use parameterized tests or multiple test methods to cover different input combinations, configurations, and edge cases. Consider testing both positive and negative cases.
Test different code paths: When code has multiple execution branches (like different strategies or conditional logic), ensure each path is tested. For example: “Can you also parameterize these tests for ctx.actions.write_file and ctx.actions.expand_template?”
Include edge cases and error conditions: Don’t just test the happy path. Test boundary conditions, invalid inputs, and error scenarios. As suggested: “Some more ideas for test cases: A regex with an alternation matching two different test strings, test strings containing metacharacters…”
Verify transformations explicitly: When testing data transformations or conversions, test both the input and output explicitly to ensure both halves of the operation work correctly.
Example of comprehensive test coverage:
@Test
public void build_changedSourceDirectory_rebuildsTarget(@TestParameter Change change) {
// Setup initial state
setupInitialBuild();
// Apply the change
change.apply(getWorkspace().getRelative("pkg/dir"));
// Verify the expected behavior
buildTarget("//foo:a");
assertContainsEvent(events.collector(), "Executing genrule //pkg:a");
}
This approach ensures that code changes are properly validated and reduces the risk of regressions in production.
Prefer optional chaining (?.) and nullish coalescing (??) operators over verbose null checks and ternary expressions. These modern JavaScript operators provide cleaner, more readable code while preventing runtime errors from null or undefined values.
Instead of explicit null checks:
// Avoid
const annotations = item.testCase ? [...item.testCase.annotations, ...item.testCase.results.flatMap(r => r.annotations)] : [];
// Prefer
const annotations = item.testCase?.results[0] ? [...item.testCase.annotations, ...item.testCase.results[0].annotations] : [];
For array access and method calls, use optional chaining with nullish coalescing:
// Avoid
annotations.push(...test.results[selectedResultIndex].annotations);
// Prefer
annotations.push(...test.results[selectedResultIndex]?.annotations ?? []);
This approach reduces boilerplate code, improves readability, and provides built-in null safety without sacrificing functionality.
High-quality code documentation improves maintainability and helps other developers understand your intentions. Follow these practices:
/** @internal */
hostname: Hostname
/**
* @deprecated Use `createIdResolver` from `vite` instead.
*/
@imports.
*aliasOnly option is also not being used anymore.createIdResolver(environment.config) instead.
*/
```// only limit to these extensions because:
// - for the `@import`/`@use`s written in file loaded by `load` function,
// the `canonicalize` function of that `importer` is called first
// - the `load` function of an importer is only called for the importer
// that returned a non-null result from its `canonicalize` function
(resolved.endsWith('.css') || resolved.endsWith('.scss') || resolved.endsWith('.sass'))
Use consistent spacing values that follow a standardized grid system, typically multiples of 4px or 8px, rather than arbitrary values. This ensures visual consistency across the UI and makes the design system more maintainable.
Avoid arbitrary spacing values like 2px, 3px, or 6px. Instead, stick to grid-based values:
/* Avoid arbitrary values */
.status-passed {
gap: 2px; /* ❌ */
}
.status-failed {
gap: 3px; /* ❌ */
}
.container {
gap: 6px; /* ❌ */
}
/* Use consistent grid values */
.status-passed,
.status-failed {
gap: 4px; /* ✅ or 8px */
}
.container {
gap: 8px; /* ✅ */
}
When spacing feels off visually, resist the temptation to use custom values for individual cases. Instead, evaluate whether the grid system needs adjustment or if the visual issue can be solved through other means like proper alignment or typography adjustments. This maintains design system integrity and prevents CSS from becoming inconsistent and hard to maintain.
When building URL-like strings that will be embedded into SVG attributes (e.g., marker-end="url(...)"), do not rely on upstream HTML escaping. Apply context-specific escaping/encoding for the exact attribute syntax, ensuring correct escaping order (notably escape backslashes first) and covering all unsafe characters—not just parentheses.
Example pattern:
function escapeForSvgUrlAttribute(input) {
// Escape order matters: backslash must be escaped before other replacements.
return input
.replace(/\\/g, '\\\\') // backslash first
.replace(/['"\s]/g, encodeURIComponent) // also handle quotes/whitespace
.replace(/[()]/g, (m) => '\\' + m); // e.g., parentheses
}
const url = `http://localhost:9000/flowchart.html?hi=${escapeForSvgUrlAttribute(s)}`;
markerEnd = `url(${url}#id)`;
Also ensure the stricter escaping is applied in the sensitive code path(s) (e.g., only the branch where the absolute marker URL is constructed), since that’s where malformed/incorrect url(...) expressions can break rendering and undermine safety assumptions.
When adding or modifying configuration parameters, especially in JSON settings files, ensure they are clearly documented with comments that explain:
Use descriptive names rather than cryptic ones, and consider uncommenting default values to make them explicit to users. This improves maintainability and helps prevent confusion.
Example:
"inline": {
// Whether to show diagnostics inline or not
"enabled": false,
// The delay in milliseconds to show inline diagnostics after the
// last buffer update.
"delay_ms": 0,
// The amount of padding between the end of the source line and the start
// of the inline diagnostic in units of columns.
"padding": 6
}
For context names, prefer clear, concise descriptors that convey meaning rather than listing all conditions explicitly:
// Instead of:
"context": "Editor && showing_multiple_signature_help && !showing_completions"
// Prefer:
"context": "Editor && can_scroll_signature_help"
Design APIs with simple, direct interfaces rather than complex parameter passing patterns or unnecessary indirection. Use appropriate parameter types (e.g., PathFragment instead of String, ImmutableMap instead of BiFunction) and avoid expanding API surface area when existing patterns can be reused.
Key principles:
RunfilesSupport.withExecutableAndArgs()PathFragment) rather than generic ones (String) for better type safetyBiFunction<ImmutableMap<String, String>, String, ImmutableMap<String, String>> with direct parameter passingExample:
// Avoid complex function parameters
public CppModuleMapAction(
// ... other params
BiFunction<ImmutableMap<String, String>, String, ImmutableMap<String, String>> modifyExecutionInfo) {
// Prefer direct parameter passing
public CppModuleMapAction(
// ... other params
ImmutableMap<String, String> executionInfo) {
This approach makes APIs more predictable, easier to test, and reduces the cognitive load on API consumers while maintaining clear contracts between components.
When documenting error handling mechanisms, always provide complete context about how they work, including any limitations, edge cases, and alternative approaches. This prevents developers from making incorrect assumptions about behavior.
For example, when documenting warning suppression flags, clarify that suppression only affects default handlers while programmatic handling remains available:
// Even with --no-warnings, apps can still handle warnings
process.on('warning', (warning) => {
// Custom warning handling logic
});
Similarly, when documenting error handling behavior changes, ensure code examples accurately reflect the actual behavior and mention any known limitations:
// Note: process.exit() may not synchronously crash utility processes
process.on('unhandledRejection', () => {
process.exit(1); // May have timing issues in utility processes
});
This approach helps developers understand the full scope of error handling mechanisms and make informed implementation decisions.
Implement systematic cleanup mechanisms that handle process termination signals without generating excessive error output. Use a generic disposable pattern to manage resources that need cleanup during exit, SIGINT, or other termination scenarios.
Create a centralized list of disposables (child processes, contexts, file handles) that can be properly disposed of during shutdown. This prevents error flooding in the terminal and ensures resources are cleaned up systematically.
Example implementation:
const disposables = [];
// Register disposables
disposables.push(() => child.kill());
disposables.push(() => context.dispose());
// Handle termination signals
process.on('SIGINT', () => {
disposables.forEach(dispose => dispose());
cleanup();
});
process.on('exit', () => {
disposables.forEach(dispose => dispose());
});
This approach prevents the terminal flooding with error messages like “exited with code null, signal SIGINT” while ensuring all resources are properly cleaned up during process termination.
Create APIs that are both easy to use correctly and hard to use incorrectly. Focus on:
// Instead of:
let catalog_name = specifier.strip_prefix("catalog:").unwrap_or("default");
// Prefer:
if let Some(catalog_name) = specifier.strip_prefix("catalog:") {
if let Some(catalogs) = &self.catalogs {
// Use catalog_name directly
}
}
// Instead of:
fn token(mut self, value: String) -> Self {
self.output.token = Some(value);
self
}
// Prefer:
fn token(mut self, value: &str) -> Self {
self.output.token = Some(value.into());
self
}
// Instead of:
Result<TurboJson, Error>
// Consider:
Result<Option<TurboJson>, Error>
// Instead of:
fn view(app: &mut App<Box<dyn io::Write + Send>>, f: &mut Frame, rows: u16, cols: u16)
// Prefer:
fn view<W>(app: &mut App<W>, f: &mut Frame, rows: u16, cols: u16)
// Instead of manually implementing Serialize:
impl<'a> Serialize for RepositoryDetails<'a> { ... }
// Prefer using serde attributes:
#[serde(into)]
// With a From implementation to handle the conversion
These practices lead to APIs that are more intuitive, safer, and require less documentation to use properly.
When adding new configuration settings, follow these naming conventions to maintain consistency and clarity:
typescript.maximumHoverLength and javascript.maximumHoverLength settings, create a single js/ts.hover.maximumLength with resource scope:"js/ts.hover.maximumLength": {
"type": "number",
"default": 500,
"description": "Controls the maximum length of hover content",
"scope": "resource"
}
This approach allows for language-specific configuration while reducing configuration sprawl.
experimental (e.g., typescript.experimental.useTsgo instead of typescript.useTsgo)"typescript.experimental.useTsgo": {
"type": "boolean",
"default": false,
"description": "Controls whether to use TsGo for TypeScript processing",
"tags": ["experimental"]
}
These conventions improve discoverability, communicate the stability status of features, and help maintain a cleaner configuration surface for users.
Ensure documentation is clear, precise, and consistently formatted. Key practices include:
// Instead of:
Please provide the minimum configuration needed.
// Use:
Please provide the minimum configuration needed to reproduce this issue. If you can still reproduce the issue with one of the lines removed, do not include that line.
// Instead of:
Screenshot of the terminal inspector's logged keystrokes
// Use:
Screenshot of logged keystrokes from the terminal inspector's "Keyboard" tab
#### `tmux.conf` (tmux 3.5a)
set -g default-terminal “tmux-256color” set-option -sa terminal-overrides “,xterm*:Tc”
// Instead of:
Provide any captured Ghostty logs.
// Use:
Provide any captured Ghostty logs. On Linux, this can be found by running `ghostty` from the command-line; on macOS, this can be found via [specific instructions].
Organize configuration settings hierarchically by grouping related settings under meaningful namespaces rather than creating numerous top-level settings. This improves maintainability, discoverability, and reduces configuration sprawl as your application grows.
When adding a new setting, consider:
For example, instead of:
{
"show_user_picture": true,
"show_onboarding_banner": true,
"show_status_bar": true
}
Prefer:
{
"titlebar": {
"show_user_picture": true,
"show_onboarding_banner": true
},
"status_bar": {
"visible": true
}
}
This approach keeps configuration maintainable as features expand and makes settings easier to locate and understand in context. It also facilitates future extensions without cluttering the root configuration space.
Optimize performance by minimizing unnecessary memory allocations and system calls. Key practices:
// Use when possible let s = some_str.into(); // Or let s = Cow::Borrowed(some_str);
2. Pre-allocate collections when size is known:
```rust
// Instead of
let mut vec = Vec::new();
items.iter().for_each(|i| vec.push(i));
// Use
let mut vec = Vec::with_capacity(items.len());
items.iter().for_each(|i| vec.push(i));
// Use
static TIME_CACHE: LazyLock
4. Return iterators instead of collecting into vectors when possible:
```rust
// Instead of
pub fn items(&self) -> Vec<Item> {
self.items.iter().map(|i| i.clone()).collect()
}
// Use
pub fn items(&self) -> impl Iterator<Item = Item> + '_ {
self.items.iter().cloned()
}
// Cache the information once let is_dir = entry.file_type() .is_ok_and(|ft| ft.is_dir());
---
## Clear error recovery paths
<!-- source: Homebrew/brew | topic: Error Handling | language: Ruby | updated: 2025-05-03 -->
Implement error handling that provides both clear recovery paths for users and graceful degradation for the system. This includes:
1. Clear, actionable error messages that guide users to resolution
2. Graceful fallbacks when operations fail
3. Retry mechanisms for transient failures
4. Early returns to simplify error flows
Example:
```ruby
def handle_api_request
return unless result.status.success?
begin
json = JSON.parse(result.stdout)
rescue JSON::ParserError
nil
end
rescue AuthenticationError => e
message = case credentials_type
when :github_cli_token
"Your GitHub CLI login session may be invalid.\n" \
"Refresh it with: gh auth login"
else
"Token may be invalid or expired.\n" \
"Check: https://github.com/settings/tokens"
end
raise UserError.new(message)
rescue TemporaryFailure => e
@retry_count ||= 0
raise if @retry_count >= MAX_RETRIES
sleep_time = 2 ** @retry_count
@retry_count += 1
retry
end
This approach ensures systems degrade gracefully while providing users clear paths to resolve issues.
Write code that prioritizes clarity and simplicity over cleverness. This improves maintainability and reduces cognitive load for other developers.
Key practices:
/ operator and or for conditional assignmentExample of improvements:
# Instead of negative conditional with empty block
if not condition:
pass
else:
do_something()
# Prefer positive conditional
if condition:
do_something()
# Instead of inline complex condition
if not username and not password:
return None
# Extract to named variable for clarity
has_credentials = username or password
if not has_credentials:
return None
# Instead of nameless boolean parameter
return self._handle_install(True)
# Use explicit parameter name
return self._handle_install(with_synchronization=True)
The goal is code that can be understood at a glance without requiring mental gymnastics to parse complex logic or unclear intentions.
Properly propagate errors to callers with sufficient context rather than handling them prematurely or hiding them. Let the caller decide how to handle errors when they have the appropriate context.
Do:
? operator to bubble up errors to callers#[from] for clean error conversion// Good: Propagate error with context
pub async fn run(base: CommandBase) -> Result<(), Error> {
match info::run(base).await {
Ok(()) => Ok(()),
Err(e) => Err(Error::Info(e)) // With #[from] annotation on Error::Info
}
}
// Good: Preserve error details
let exe_path = std::env::current_exe().map_or_else(
|e| format!("Cannot determine current binary: {e}"),
|p| p.display().to_string()
);
// Good: Use methods that include context in errors
preferences_file.ensure_dir()?; // Path information included in error
Don’t:
.unwrap() or .expect() in production code paths unless failure is truly impossible// Bad: Lossy conversion causing silent failures
let stdout = String::from_utf8_lossy(&stdout);
// Bad: Using unwrap which hides error context
let anchored_to_turbo_root_file_path = self
.reanchor_path_from_git_root_to_turbo_root(turbo_root, path)
.unwrap();
Only handle errors locally when you have sufficient context to make the right decision; otherwise, propagate them with as much information as possible.
Always specify explicit Node.js version requirements in configuration files to ensure compatibility with language features and APIs. When updating supported versions, verify feature compatibility and document reasoning behind version constraints.
For example, when using ESM modules with require:
// In eslint.config.js or other config files
settings: {
node: {
// Specify exact version ranges that support needed features
version: '^20.19.0 || ^22.12.0+', // Required for require(ESM) support
},
}
When changing version requirements, consider:
Explicitly defined version requirements help prevent unexpected lint errors, runtime issues, and improve developer experience by documenting version-specific feature availability.
Avoid duplicating logic, patterns, or data across the codebase. When similar code appears in multiple places, extract it into reusable functions or methods.
Examples:
let turbo_json_exists = turbo_json_path.exists(); let turbo_jsonc_exists = turbo_jsonc_path.exists();
// Extract to a helper function: fn root_turbo_json_path(repo_root: &AbsoluteSystemPath) -> (AbsoluteSystemPathBuf, bool) { // Implementation that can be reused }
2. Remove redundant initialization:
```rust
// Instead of:
enabled: remote_cache_opts.enabled,
no_update_notifier: None, // Remote cache options don't include this
..Self::default() // This already handles no_update_notifier
// Just use:
enabled: remote_cache_opts.enabled,
..Self::default()
// Use borrowing: let repo_root = &self.repo_root;
4. Break large complex methods into smaller ones with clear responsibilities:
```rust
// Instead of embedding this logic in a larger function:
let conflict = {
let own_invalidator = get_invalidator();
let mut authorative_write_map = self.authorative_write_map.lock().unwrap();
// ... 30+ lines of conflict resolution logic
};
// Extract to a dedicated method:
fn check_write_conflict(&self, path: &Path) -> Result<(), Error> {
// Extracted conflict resolution logic
}
Following these practices improves maintainability, reduces the chances of inconsistencies, and makes the codebase easier to test and understand.
Always verify that tests cover all relevant scenarios, edge cases, and conditions rather than just the happy path. When reviewing or writing tests, actively look for missing test cases and suggest additional coverage.
Key areas to examine:
Example from the discussions:
// Instead of just testing the basic case
it('window opened with innerWidth option has the same innerWidth', async () => {
// ... basic test
});
// Also test against related functionality
it('should also test against win.getContentSize()', async () => {
// ... additional coverage
});
// And test edge cases
it('emits the resize event for single-pixel size changes', async () => {
const [width, height] = w.getSize();
const size = [width + 1, height - 1]; // Test both + and - changes
});
When you encounter a test that seems to work “incidentally” or only covers one scenario, ask: “What other conditions should this handle?” and “Are we missing any important edge cases?”
When writing tests for configuration-dependent functionality, implement environment detection and conditional logic to handle platform-specific differences. Tests should detect system capabilities and adjust expectations accordingly rather than assuming uniform behavior across all environments.
Key practices:
Example from cross-platform path handling:
if is_windows; then
expected_path=$(echo "$bazelrc" | sed 's/^C:/c:/; s/\//\\\\/g')
else
expected_path="$bazelrc"
fi
expect_log "source: \"$expected_path\""
Example from compiler feature detection:
# Check if __builtin_FILE is supported and skip test if not supported
if ! compiler_supports_builtin_file; then
echo "Skipping test: __builtin_FILE not supported"
return
fi
This approach ensures tests are robust across different execution environments while maintaining meaningful validation of configuration behavior.
When implementing caching in build systems, carefully configure cache sharing behavior based on your concurrency requirements. Improper sharing settings can lead to build failures when multiple processes attempt to access the same cache simultaneously.
For Docker BuildKit cache mounts:
sharing=shared (default) for caches with internal locking mechanisms or read-only access patternssharing=locked when cache contents cannot handle concurrent writerssharing=private for isolated per-build caches that don’t benefit from sharingExample of proper cache configuration:
RUN \
# Global cache that safely handles concurrent access
--mount=type=cache,target=/var/lib/apt/lists,type=cache,sharing=shared \
# Cache that needs exclusive access to prevent corruption
--mount=type=cache,target="/root/.cache/rustup",id="rustup-toolchain",sharing=locked \
# Project-specific build cache with isolated ID to prevent unintended sharing
--mount=type=cache,target="target/",id="cargo-target-${APP_NAME}-${TARGETPLATFORM}",sharing=locked \
# Exclude temporary directories from caching with tmpfs
--mount=type=tmpfs,target="${CARGO_HOME}/registry/src" \
--mount=type=tmpfs,target="${CARGO_HOME}/git/checkouts" \
cargo build --release
Always consider the concurrency patterns of your build environment. Remember that caches with the same ID are shared across different builds, which can cause unexpected interactions between unrelated projects.
Leverage Docker BuildKit’s cache and bind mount capabilities to dramatically improve CI build times and reduce image sizes. Instead of copying source files into intermediate layers, use bind mounts to provide build context and cache mounts for package managers and build artifacts.
Why this matters:
Implementation example:
# Use cache mounts for package managers
RUN \
--mount=target=/var/lib/apt/lists,type=cache,sharing=locked \
--mount=target=/var/cache/apt,type=cache,sharing=locked \
<<HEREDOC
apt update && apt install -y --no-install-recommends \
build-essential \
curl
HEREDOC
# Use bind mounts for source files and cache mounts for build artifacts
RUN \
--mount=type=bind,source=src,target=src \
--mount=type=bind,source=package.json,target=package.json \
--mount=type=cache,target=node_modules \
npm install && npm run build
Make sure your CI environment supports BuildKit (Docker 18.09+) and enable BuildKit features with DOCKER_BUILDKIT=1.
Ensure naming follows consistent patterns throughout the codebase in both style and structure:
- {{# if (hasTool 'grep') }}
+ {{# if (has_tool 'grep') }}
- export additional-language-server-workspace-configuration: func(...)
+ export language-server-additional-workspace-configuration: func(...)
- (emphasis) @markup.emphasis
+ (emphasis) @emphasis.markup
This consistency improves code readability, makes the codebase more predictable, and reduces cognitive load when writing or reviewing code.
Ensure consistent styling is maintained across related elements in the codebase. This applies to:
// Example: All AI lab icons should be 16x16px
// When changing highlights in javascript/highlights.scm:
(regex_flags) @keyword.operator.regex
// Also update in typescript/highlights.scm and tsx/highlights.scm
Maintaining consistency improves readability, reduces confusion, and creates a more professional codebase that’s easier to maintain over time.
Never use unwrap() on nullable values that could reasonably be None, as this can cause crashes that are harder for users to work around than bugs. Instead, provide graceful fallbacks or proper error handling.
The principle is: “We shouldn’t crash here under any circumstances” and “Bugs would be easier to work around for users than crashes.”
Preferred patterns:
// Bad - crashes on None
let country_code = locale.countryCode().unwrap();
// Good - graceful fallback
if let Some(country_code) = locale.countryCode() {
format!("{}_{}.UTF-8", language_code, country_code)
} else {
// Fall back to en_US in case the country code is not available.
"en_US.UTF-8".to_string()
}
// Good - using map_or for cleaner handling
match self.hint.mouse {
None => MouseButton::Left,
Some(c) => c.button.0,
}
// Better as:
self.hint.mouse.map_or(MouseButton::Left, |c| c.button.0)
// Bad - empty string treated as valid due to unwrap_or(0)
let codepoint = text.chars().next().map(u32::from).unwrap_or(0);
// Good - explicit empty check
let codepoint = match text.chars().next() {
Some(c) => u32::from(c),
None => return false, // Handle empty case explicitly
};
Use if let Some(), map_or(), or explicit match statements instead of unwrap() to handle nullable values safely.
Break down complex inline conditions and nested logic into separate, well-named functions or simpler expressions to improve code readability and maintainability.
Complex boolean expressions, deeply nested conditionals, and inline logic with multiple concerns should be extracted into helper functions or simplified using more readable patterns. This makes the code easier to understand, test, and modify.
Examples of improvements:
// Before: Complex inline condition
return value !== "" &&
!(value === "\n" &&
typeof adjacentNodes === "object" &&
(adjacentNodes?.previous?.kind === "cj-letter" ||
adjacentNodes?.next?.kind === "cj-letter") &&
!isSentenceUseCJDividingSpace(path))
? isBreakable ? line : " "
: isBreakable ? softline : "";
// After: Extracted helper function
if (value !== "" && canBeConvertedToSpace(path, value, adjacentNodes)) {
return isBreakable ? line : " ";
}
return isBreakable ? softline : "";
function canBeConvertedToSpace(path, value, adjacentNodes) {
// Clear, focused logic here
}
// Before: Complex array operations
if (commaGroup.groups.length > 1) {
for (const group of commaGroup.groups) {
if (group.value && typeof group.value === "string" && group.value.includes("#{")) {
// complex logic
break;
}
}
}
// After: Simplified with array methods
if (commaGroup.groups.some(group =>
typeof group.value === "string" && group.value.includes("#{"))) {
// simplified logic
}
This approach reduces cognitive load, makes code self-documenting through function names, and enables better testing of individual logical components.
Choose more efficient algorithmic approaches by leveraging built-in methods and APIs instead of implementing manual solutions. This includes using iterator methods over manual loops, direct comparisons over complex operations, and existing path traversal APIs over custom implementations.
Key optimizations to apply:
.next().done instead of manual for-loops with early returnsa.offset - b.offset) over complex multi-step operationspath.siblings, path.next, path.index instead of manual array traversal with findIndex() and find()Example transformations:
// Instead of manual loop with early return
function isLeaf(node, options) {
for (const _ of getChildren(node, options)) {
return false;
}
return true;
}
// Use iterator method
function isLeaf(node, options) {
return getChildren(node, options).next().done;
}
// Instead of complex string operations
if (!options.originalText.slice(locEnd(iNode), locStart(iNextNode)).includes(" "))
// Use direct comparison
if (locEnd(iNode) === locStart(iNextNode))
// Instead of manual array traversal
const elementIdx = elements.findIndex((v) => v == elementNode);
const nextNode = elements.find((e, i) => i > elementIdx && e !== null);
// Use path APIs
// path.siblings, path.next, path.index should be used
This approach reduces computational complexity, improves readability, and leverages well-tested library functions.
When configuring environment variables, especially those related to paths, implement these safety practices:
# Validate paths before setting environment variables
if [[ -r "/var/tmp" && -w "/var/tmp" ]]
then
TEMP_DIR="/var/tmp"
else
TEMP_DIR="/tmp"
fi
# Use dynamic evaluation in shell config files
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.bashrc
# NOT: /opt/homebrew/bin/brew shellenv >> ~/.bashrc
# Add directories (not executables) to PATH
export PATH="/opt/homebrew/bin:$PATH" # Correct
# NOT: export PATH="/opt/homebrew/bin/brew:$PATH" # Incorrect
# Handle unset variables in strict mode shells
export PATH="${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin${PATH+:$PATH}";
When designing APIs, create appropriate abstractions that hide platform-specific or low-level implementation details from consuming code. Avoid exposing raw interfaces outside their designated modules and minimize unnecessary dependencies.
Good Practice:
For example, instead of binding to an unused protocol:
// AVOID: Unnecessary binding that adds dependencies
if (registryBind(
xdg.WmDialogV1,
registry,
global,
)) |wm_dialog| {
context.xdg_wm_dialog = wm_dialog;
return;
}
Instead, simply check if the protocol is available without binding:
// BETTER: Just compare against the name and set a flag
if (isProtocolSupported(registry, global, "xdg_wm_dialog")) {
context.has_wm_dialog_support = true;
return;
}
Similarly, avoid using raw C interfaces outside their dedicated modules. Create proper abstractions that isolate platform-specific details, making the codebase more maintainable and portable.
Never print or log sensitive information such as tokens, passwords, or secrets that might be present in environment variables or configuration. When debugging with environment variables, always sanitize the output by filtering out sensitive keys.
Instead of:
print(*os.environ)
# or
print("token_start", repr(os.environ["GITHUB_TOKEN"][:10]))
Use sanitized output:
print("Environment variables (sanitized):")
print({k: v for k, v in os.environ.items() if "TOKEN" not in k and "PASSWORD" not in k and "SECRET" not in k})
This prevents accidental exposure of credentials in logs, console output, or error reports that could lead to security breaches if captured by unauthorized parties.
Organize configuration settings logically and avoid redundancy in project configuration files. Group related options into appropriate sections, eliminate duplicated settings (especially those already provided by extended configurations), and document non-obvious choices with explanatory comments.
TypeScript configurations should:
// In tsconfig.json
{
"extends": "@tsconfig/ember",
"compilerOptions": {
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
- "isolatedModules": true,
+ "verbatimModuleSyntax": true, // In "Linting" section below
/* Linting */
"strict": true,
+ "verbatimModuleSyntax": true, // Moved from "Bundler mode"
- "strictBuiltinIteratorReturn": true, // Redundant with "strict: true"
}
}
For new plugins or packages, prefer modern module configurations:
{
"name": "@vitejs/plugin-example",
"type": "module", // Prefer ESM for new packages
"files": ["dist"]
}
This approach improves maintainability and helps onboard new developers by making configuration intent clearer while reducing conflicting settings.
Prioritize native or Rust-based implementations of build tools over their JavaScript counterparts to significantly improve performance in both development and build phases. Tools like Rolldown (replacing Rollup and esbuild) can reduce build times and provide a more consistent experience between development and production environments.
When developing plugins, utilize native performance features like hook filters to reduce overhead:
// Example: Using hook filters in Rolldown plugins for better performance
const plugin = {
name: 'my-performance-plugin',
resolveId: {
filter: /\.custom$/, // Only process specific files
handler(source, importer) {
// Handler only called for matching files, reducing JS-Rust communication overhead
return this.resolve(source, importer);
}
}
}
For large applications, consider replacing multiple JavaScript-based tools with their native equivalents to create a more streamlined, performant pipeline. This approach reduces both build times and runtime overhead while maintaining compatibility with the existing ecosystem.
Always provide explicit error handling instead of allowing silent failures or blank screens. Any place where an error can occur but is not handled explicitly is a bug. When errors occur, communicate clearly to users what went wrong and suggest recovery actions when possible.
Example of problematic silent failure:
{!!report && <TestCaseViewLoader report={report} tests={filteredTests.tests} />}
Better approach with explicit error handling:
{!!report ?
<TestCaseViewLoader report={report} tests={filteredTests.tests} /> :
<div className='error'>Report data could not be found</div>}
Even better with recovery guidance:
{!!report ?
<TestCaseViewLoader report={report} tests={filteredTests.tests} /> :
<div className='error'>
Report data could not be found. Try refreshing the page or check your connection.
</div>}
This principle ensures users understand when something has gone wrong rather than being left with confusing blank screens or unresponsive interfaces.
When using std::filesystem operations, prefer passing std::error_code parameters instead of relying on try-catch blocks for error handling. This approach provides better performance and more explicit error checking.
Most std::filesystem functions have overloads that accept an std::error_code reference parameter. Use these overloads and check the error code explicitly rather than catching exceptions.
Example:
// Avoid try-catch approach
try {
if (std::filesystem::exists(path) && std::filesystem::is_directory(path)) {
// process directory
}
} catch (...) {
// handle error
}
// Prefer error_code approach
std::error_code ec1, ec2;
if (std::filesystem::exists(path, ec1) && !ec1 &&
std::filesystem::is_directory(path, ec2) && !ec2) {
// process directory
} else if (ec1 || ec2) {
// handle specific errors
}
This pattern is especially important for operations like std::filesystem::exists(), std::filesystem::is_directory(), std::filesystem::canonical(), and directory iteration where exceptions can be thrown for various system-level issues. The error_code approach allows for more granular error handling and avoids the performance overhead of exception handling in expected error scenarios.
Always validate and sanitize external input using established libraries rather than manual string manipulation or custom parsing. External input includes user data, environment variables, command line arguments, and data from untrusted sources. Manual construction of structured data (like JSON) with user input creates injection vulnerabilities.
Use proper validation libraries from //base or //v8 instead of manual string operations. For example, instead of manually constructing JSON:
// UNSAFE - Manual JSON construction
std::wstringstream stm;
stm << L"[";
std::for_each(data, data + dataCount, [&](const auto& item) {
stm << item << L","; // No escaping, injection risk
});
stm << L"]";
// SAFE - Use proper JSON library
base::Value::List json_array;
for (const auto& item : data) {
json_array.Append(base::Value(SanitizeInput(item)));
}
This principle applies to all external data sources: environment variables that could bypass security controls, user input in notifications, permission callbacks, and any data crossing trust boundaries. The goal is to prevent injection attacks and ensure data integrity through proper validation and sanitization.
Use consistent, standards-aligned naming for identifiers, especially for user-facing text/URLs and registry keys.
ID (not Id) when it’s normal prose/descriptions; only use Id if an external API/storage contract explicitly requires it.kebab-case for URL segments and related identifiers that mirror URLs.kebab-case canonical key for shape/component registration; if you add an alias, make it explicit and short, and keep both entries consistent with docs/config.Example (shape registry + ID prose):
// Canonical kebab-case registry key (and optional explicit alias)
const shapes = {
'my-new-shape': myNewShape,
'm-nsh': myNewShape,
};
// Documentation prose should use ID
// "ID of the edge" (unless an external API contract requires "Id")
Design CI/CD workflows with intentional triggers and conditions to avoid unnecessary executions, rate limiting, and contextually inappropriate behavior. Use specific event triggers and conditional statements to ensure workflow steps run only when needed and appropriate.
Avoid overly broad automation like daily cron jobs that can cause rate limiting issues as your project scales. Instead, rely on event-driven triggers and manual execution when needed.
For steps that should only run in specific contexts, use conditional execution:
- name: clang-format apply
if: failure() && github.event_name == 'pull_request'
run: ninja -C build clang-format
- name: Comment patch
if: failure() && github.event_name == 'pull_request'
uses: mshick/add-pr-comment@v2
Consider separating workflows by purpose rather than adding complex conditions to a single workflow. This improves maintainability and reduces the risk of unintended executions.
Clearly specify what constitutes your public API contract to manage versioning expectations and documentation requirements. Distinguish between structured outputs intended for programmatic consumption versus human-readable outputs that may change without being considered breaking changes.
For CLI tools or libraries:
Example in package exports:
{
"exports": {
// Public API with stability guarantees
".": "./src/public-api.ts",
// Explicitly mark experimental features
"./experimental": "./src/experimental-features.ts",
// Internal APIs not covered by semver
"./internal": null
}
}
When documenting API endpoints, be specific about response headers and their purposes, such as x-artifact-tag for artifact download endpoints. For authentication endpoints, clearly document their scope and intended usage contexts.
Configure your Homebrew installation according to the defined support tiers to ensure optimal functionality and support. For Tier 1 support (fully supported):
/opt/homebrew on Apple Silicon, /usr/local on Intel x86_64, /home/linuxbrew/.linuxbrew on Linux)Non-standard configurations will receive reduced support (Tier 2 or 3) or may be entirely unsupported. When using shared dotfiles across platforms, use platform detection:
command -v brew || export PATH="/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/local/bin"
command -v brew && eval "$(brew shellenv)"
Ensure API documentation provides clear, accurate, and comprehensive information for developers. This includes precise function signatures, detailed parameter descriptions, correct terminology, and helpful external references.
Key practices:
Example of good API documentation:
// Clear function signature with proper typing
function parse(text: string, options?: ParserOptions): Promise<AST> | AST;
// Detailed parameter description with examples
// The `file` parameter could be a normal path or a url string like `file:///C:/test.txt`
// Helpful external reference
Strings provided to `plugins` are ultimately passed to [`import()` expression](https://nodejs.org/api/esm.html#import-expressions)
This approach helps developers understand exactly how to use APIs correctly and reduces confusion about parameter types, optional arguments, and expected behaviors.
Always adhere to the established formatting and syntax conventions of each programming language while maintaining consistency across related language configurations. This includes:
Example:
# For Go
tab_size = 4
hard_tabs = true
# For JavaScript and related languages
line_comments = ["// "]
block_comment = ["/*", "*/"]
Following language-specific conventions improves code readability, leverages standard tooling, and helps maintain consistency across the codebase, especially when working with multiple languages in the same project.
Use bit manipulation techniques to optimize memory usage and computational efficiency in data structures and enums. For flag enums, consistently use bit-shift notation (1 << n) to make bit positions explicit and enable efficient bitwise operations. For compact data representation, leverage bitfields within unions to pack multiple boolean flags into minimal memory space.
Example of bit-shift enum notation:
enum eRectCorner {
CORNER_NONE = 0,
CORNER_TOPLEFT = 1 << 0,
CORNER_TOPRIGHT = 1 << 1,
CORNER_BOTTOMRIGHT = 1 << 2,
CORNER_BOTTOMLEFT = 1 << 3
};
Example of bitfield optimization:
union {
uint16_t all = 0;
struct {
bool buffer : 1;
bool damage : 1;
bool scale : 1;
// ... more flags
};
};
This approach reduces memory footprint, enables efficient bitwise operations for flag combinations, and leverages compiler optimizations for bit manipulation algorithms.
Group related configuration options into nested TOML sections rather than using flat key-value pairs. This improves readability, maintainability, and makes relationships between settings more explicit.
Example: Instead of:
word-completion = true
word-completion-trigger-length = 7
Use:
[word-completion]
enable = true
trigger-length = 7
This approach:
When adding new configuration options, consider if they logically belong in an existing section or warrant creating a new nested section.
When modifying build tool configurations, especially during migrations, provide detailed technical justification for each change. Document why specific options, plugins, or flags are being added, removed, or modified with concrete reasoning.
This practice ensures build pipeline changes are transparent, maintainable, and can be properly reviewed. It prevents configuration drift and helps future developers understand the rationale behind build decisions.
Example of good documentation:
// Remove babel plugins that are now redundant with esbuild:
// - "@babel/plugin-transform-logical-assignment-operators" - logical assignment
// has been natively supported since Node 15
// - "@babel/plugin-transform-nullish-coalescing-operator" - nullish coalescing
// has been natively supported since Node 14
// - "@babel/plugin-transform-modules-commonjs" - handled by --format=cjs flag
args: [
'esbuild',
'--format=cjs',
'--platform=node'
]
Always explain the technical basis for configuration decisions, reference version support when relevant, and note when options become obsolete due to dependency changes.
Treat resource URIs and external references as untrusted input: normalize and validate schemes, and reject anything not on an explicit allowlist. Motivation: schemes such as file: (and other unsafe schemes like javascript: or data: when used for resources) can expose local files or enable injection attacks, and are commonly blocked by browsers — so they must not be implicitly trusted.
How to apply:
Example (pattern adapted from code under review): // before: filtered out many schemes, but allowed file: was removed filter(isString) .filter(s => { const v = s.trim().toLowerCase(); // allow only http(s) or relative paths starting without a scheme return isTruthy(v) && ( v.startsWith(‘http:’) || v.startsWith(‘https:’) || v.startsWith(‘.’) || v.startsWith(‘/’) ); });
Notes and extensions:
Optimize performance by eliminating redundant operations and arranging code to avoid unnecessary computations, especially in frequently executed paths. Follow these principles:
# Instead of this:
primary_container.dependencies.each do |dep|
Homebrew::Install.perform_preinstall_checks_once
# other operations...
end
# Do this:
Homebrew::Install.perform_preinstall_checks_once
primary_container.dependencies.each do |dep|
# other operations...
end
# Instead of repeatedly reading files in a loop:
formulae_and_casks_to_check.each do |formula_or_cask|
autobump_file = formula_or_cask.tap.path/".github/autobump.txt"
next false unless File.exist?(autobump_file)
if File.read(autobump_file).include?(formula_or_cask.name)
# ...
end
end
# Read files once and cache the results:
autobump_files = {}
formulae_and_casks_to_check.each do |formula_or_cask|
tap = formula_or_cask.tap
next if tap.nil?
autobump_files[tap] ||= begin
autobump_path = tap.path/".github/autobump.txt"
autobump_path.exist? ? File.read(autobump_path).lines.map(&:strip) : []
end
# Use cached content
end
# Cache expensive operation results
deploy_new_x86_64_runner = @all_supported || deploy_new_x86_64_runner?
Formula.all.any? do |formula|
# First check the simple condition
next false if formula.class.pour_bottle_only_if != :clt_installed
# Only then perform expensive dependency analysis
non_test_dependencies = Dependency.expand(formula, cache_key: "determine-test-runners") do |_, dependency|
Dependency.prune if dependency.test?
end
# ...
end
These optimizations are particularly important in performance-critical paths that execute frequently or process large amounts of data.
Always validate performance changes through profiling or benchmarking before implementation, and favor memory-efficient patterns when making optimizations. Key practices:
// Before changing buffer sizes, validate impact:
const SCROLLBACK_LEN: usize = 1024;
// Profile current performance
// Test new value
const SCROLLBACK_LEN: usize = 2048;
// Validate no significant regression
&str over &String to avoid double indirectionlet mut map = HashMap::with_capacity(items.len());
// Instead of
pub fn get_items(&self) -> Vec<String> {
self.items.iter().map(|i| i.to_string()).collect()
}
// Prefer
pub fn get_items(&self) -> impl Iterator<Item = &str> + '_ {
self.items.iter().map(|i| i.as_str())
}
Authentication state files (such as browser session files, cookies, or tokens) contain sensitive credentials that can lead to full account takeover if exposed. These files must never be committed to version control systems as they could be used to impersonate users or test accounts.
Prevention strategies:
.gitignore file and store files in dedicated directories like playwright/.auth/Example implementation:
// Option 1: Secure directory with .gitignore
{
name: 'firefox',
use: {
storageState: 'playwright/.auth/user.json', // Add playwright/.auth to .gitignore
},
}
// Option 2: Temporary directory (safer)
{
name: 'firefox',
use: {
storageState: `${mkdirtemp()}/playwright/.auth/user.json`,
},
}
Always verify that authentication state files are properly excluded from version control and build artifacts to prevent credential exposure.
When working with environment variables in Vite applications, be explicit about variable loading behavior and precedence. Environment variables from .env files are always loaded regardless of mode, with mode-specific files (.env.[mode]) taking precedence over generic ones.
For type safety, use the TypeScript declaration merging pattern to strongly type your environment variables:
/// <reference types="vite/client" />
// By adding this interface, you can make the type of ImportMetaEnv strict
// to disallow unknown keys.
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
// more env variables...
}
When loading environment variables in config files, be explicit about which prefixes to include:
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
// Set the third parameter to 'APP_' to load envs with the `APP_` prefix.
// If necessary, you can set the optional third parameter to '' to load all env regardless of the `VITE_` prefix.
const env = loadEnv(mode, process.cwd(), 'APP_')
return {
// use env variables in config
define: {
'process.env.APP_ENV': JSON.stringify(env.APP_ENV)
}
}
})
To disable environment variable loading altogether, set envDir: false in your Vite config.
When designing interfaces for filtering, traversal, or search algorithms, research existing codebase patterns to maintain consistency in terminology and boolean logic. Before introducing new parameter names like “skip”, “filter”, “match”, or “predicate”, analyze which terms are already established in similar contexts.
Ensure clear documentation of predicate behavior, explicitly stating the expected return values and their effects:
-- Good: Clear documentation with explicit boolean logic
• {filter}? (`fun(dir: string): boolean`) Predicate that
decides if a directory is traversed. Return true to traverse
a directory, or false to skip.
-- Avoid: Ambiguous or inconsistent terminology
• {skip}? (`fun(dir: string): boolean`) Do not traverse
This consistency reduces cognitive load for developers and prevents confusion about whether predicates use positive logic (return true to include) or negative logic (return true to exclude). Research shows that “match” and “filter” are the most common patterns in established codebases, making them safer choices for new algorithm interfaces.
Avoid hardcoding configuration values that affect user experience or behavior. Instead, make these values configurable with sensible defaults. This is especially important for timing values, thresholds, and user-facing constants that different users may want to customize.
Examples of values that should be configurable rather than hardcoded:
const MIN_WORD_LEN: usize = 7; should be configurable for users who want completion for shorter words like “because”const DEBOUNCE: Duration = Duration::from_secs(1); should be configurable as users may prefer faster response times like 20mslet token = token.unwrap_or("//"); should use a configurable default comment token rather than hardcoding “//”When making values configurable:
// Instead of:
const MIN_WORD_LEN: usize = 7;
// Do:
pub struct CompletionConfig {
pub min_word_length: usize,
}
impl Default for CompletionConfig {
fn default() -> Self {
Self {
min_word_length: 7, // Reasonable default, but configurable
}
}
}
This approach improves user experience by allowing customization while maintaining reasonable defaults for users who don’t need to change the settings.
Names should clearly communicate their actual purpose and be consistent across similar contexts. Avoid names that mislead about functionality or create confusion about the component’s role.
When naming components, props, or UI elements, ensure the name accurately reflects what the code does rather than what it might do. For example, if a component handles a single checkbox, don’t name it in a way that suggests it handles multiple checkboxes.
Maintain consistency in naming patterns, especially for UI elements. If you show additional text in one context, apply the same pattern consistently rather than making it conditional.
Example of unclear naming:
// Misleading - suggests multiple checkboxes but handles one
export const CheckBox: React.FunctionComponent<{
checkBoxSettings: Check<boolean>[];
}>
// Conditional labeling creates inconsistency
{isFailed && <span>View Trace</span>}
Example of clear naming:
// Clear - accurately reflects single checkbox functionality
export const CheckBox: React.FunctionComponent<{
settings: Check<boolean>;
}>
// Consistent and semantically meaningful
<span>View Failing Trace</span>
The goal is to make code self-documenting through meaningful names that eliminate ambiguity about purpose and maintain consistent patterns.
Keep all build configuration files (Snapcraft, Flatpak manifests, etc.) in the repository alongside your code to ensure they are tested, versioned, and maintained together with the application. This approach facilitates CI testing, allows for regression detection, and ensures consistency across distribution methods.
Include multiple build variants when appropriate (e.g., release vs. development builds):
# Example Flatpak manifest with development variant
app-id: com.example.app
runtime: org.gnome.Platform
# ... common configuration ...
# Production build
modules:
- name: app
buildsystem: simple
build-commands:
- zig build -Doptimize=ReleaseFast
# With corresponding development variant
# com.example.app.Devel.yml
app-id: com.example.app.Devel
runtime: org.gnome.Platform
# ... common configuration ...
modules:
- name: app
buildsystem: simple
build-commands:
- zig build -Doptimize=Debug
Configure your CI workflows to verify all distribution methods on appropriate triggers (e.g., only run on relevant branches) and optimize test matrices by eliminating redundant tests that wouldn’t provide additional signal. This ensures reliable builds across all supported platforms while keeping CI/CD pipelines efficient.
When defining configuration options, always clearly document parameter constraints, valid ranges, and behaviors. For numeric values, explicitly state acceptable ranges and how out-of-range values are handled. Configuration options should have appropriate granularity - avoid simple booleans when more nuanced control is beneficial.
For example, instead of:
{
"diagnostics": {
"include_warnings": true
}
}
Consider more granular control:
{
"diagnostics": {
"minimum_level": "warning", // Options: "error", "warning", "info", "hint"
"inline": {
"enabled": true
}
}
}
Group related settings logically, provide sensible defaults, and ensure configuration structure reflects the natural workflow (prerequisites before implementation details). This makes configurations more intuitive, flexible, and less prone to user error.
Configuration values should be properly initialized and stay updated throughout their lifecycle. Follow these guidelines:
constructor(@IConfigurationService configService: IConfigurationService) { // Initialize immediately this._configValue = configService.getValue(‘myConfig’);
// Listen for changes
this._register(configService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('myConfig')) {
this._configValue = configService.getValue('myConfig');
}
})); } } ```
// BETTER: Cache and update on changes private _cachedConfig = this.configService.getValue(‘myConfig’); getConfig() { return this._cachedConfig; }
3. When handling configuration changes, use `affectsConfiguration()` to efficiently check if your configuration was modified before updating cached values.
4. For services that depend on initial configuration state, ensure values are available before service initialization or handle the undefined case appropriately.
---
## API documentation accuracy
<!-- source: helix-editor/helix | topic: API | language: Markdown | updated: 2025-03-24 -->
Ensure API documentation accurately describes actual behavior and avoids subjective commentary that may become outdated. Documentation should clearly explain how features interact, what the expected behavior is, and avoid qualitative assessments about performance or quality that can change over time.
When documenting APIs or software integrations, focus on factual descriptions of functionality rather than opinions about how well something works. For example, instead of saying "Seems to work less well than Dance" in a comparison table, simply list the available options without subjective commentary.
Additionally, when API behavior might be misunderstood, provide clear explanations. For instance, if documentation suggests "only one language server can be used for each feature" but the actual behavior allows multiple servers for some features like diagnostics, clarify this discrepancy with additional documentation.
Example of good practice:
```toml
# Clear, factual description
[language-server.efm-lsp-prettier]
command = "efm-langserver"
# Explains actual behavior without opinion
config = { documentFormatting = true }
This approach keeps documentation maintainable, prevents user confusion, and ensures that API behavior is accurately represented to developers.
Establish consistent patterns for API integrations by following these guidelines:
def api_request(url_options) type = if (data = url_options[:data].presence) :data elsif (data = url_options[:json].presence) :json end
case data when Hash if type == :json [”–#{type}”, JSON.generate(data)] else [”–#{type}”, URI.encode_www_form(data)] end end end
3. Handle API response evolution:
- Document field deprecations clearly
- Consider backwards compatibility needs
- Provide migration paths for breaking changes
4. Implement consistent error handling:
- Handle API-specific errors explicitly
- Provide meaningful error messages
- Include fallback behaviors where appropriate
This standardization ensures maintainable and reliable API integrations while promoting clear documentation and consistent implementation patterns across the codebase.
---
## Separate configuration responsibilities
<!-- source: vitejs/vite | topic: Configurations | language: Other | updated: 2025-03-21 -->
Design configuration files with clear separation of responsibilities and maintain flexibility for future changes. Avoid unnecessarily bundling configurations together when they serve different purposes, as this can create tight coupling and make future transitions difficult.
For tool-specific configurations (like babel, webpack, etc.), keep them in their dedicated files rather than abstracting them in framework plugins. This allows users to:
1. Have full visibility into their build pipeline
2. Customize configurations as needed
3. Swap underlying tools without major refactoring
When creating configuration patterns (like in renovate.json5, .gitignore, etc.), be as specific as possible when targeting special cases:
```json
// Instead of broad patterns like this:
{
"fileMatch": ["\\.[mc]?[tj]sx?$"]
}
// Use specific targeting when appropriate:
{
"fileMatch": ["packages\/create-vite\/src\/index\\.ts$"]
}
This approach reduces the risk of unintended matches and makes configurations more maintainable and transparent.
Remove configuration keys that explicitly set values identical to their defaults. This reduces visual clutter, minimizes maintenance overhead, and prevents confusion about which settings are intentionally customized versus accidentally duplicated.
When reviewing configuration files, identify and remove keys that match default behavior. For example:
# Before - unnecessary explicit defaults
[[language]]
name = "werk"
scope = "source.werk"
file-types = [ "werk", { glob = "Werkfile" } ]
roots = [] # Remove: [] is the default
language-id = "werk" # Remove: matches name by default
# After - clean configuration
[[language]]
name = "werk"
scope = "source.werk"
file-types = [ "werk", { glob = "Werkfile" } ]
This practice helps distinguish between intentional configuration choices and default values, making the actual customizations more apparent to future maintainers.
Define explicit and minimal permissions in GitHub Actions workflows to ensure proper operation while maintaining security. Workflows should only have permissions necessary for their intended tasks, and permission checks should occur early in the workflow to prevent unnecessary actions.
For workflows that modify resources:
issues: write for workflows that close issues)permissions: {} as a default and add only what’s neededExample:
name: Issue Management Workflow
# Start with empty permissions
permissions: {}
jobs:
manage-issues:
runs-on: ubuntu-latest
# Add only required permissions
permissions:
issues: write
steps:
# Check user permissions first before proceeding
- name: Check User Permissions
uses: actions/github-script@v7
with:
script: |
// Verify user has appropriate permissions
if (!context.payload.sender.permissions.write) {
core.setFailed('User does not have write permissions')
return
}
# Remaining steps only execute if permissions check passes
- name: Close stale issues
# ...
This approach minimizes security risks, prevents workflow failures due to permission issues, and follows the principle of least privilege.
Always move potentially blocking operations to background threads to maintain UI responsiveness. Use appropriate spawning mechanisms based on the operation type:
// Do this instead cx.background_spawn(async move { let result = heavy_computation(); // Update state after computation }).await;
2. For state updates after background work:
```rust
// Accumulate new state first
let new_state = cx.background_spawn(async move {
let mut new_data = Vec::new();
// ... heavy computation ...
new_data
}).await;
// Then update actual state once
self.state = new_state;
Key principles:
This pattern is essential for maintaining application responsiveness and preventing UI freezes.
When documenting network protocol configurations (TLS, HTTP/2, CORS), provide specific details about required options, default values, and explicit behavior. Avoid ambiguous terminology like “sufficient values” and instead specify exactly what options are needed and how different settings interact.
For example, instead of writing:
Enable TLS + HTTP/2. Note this downgrades to TLS only when the `server.proxy` option is also used.
The value is an options object passed to `https.createServer()`.
Prefer more explicit documentation with required parameters:
Enable TLS + HTTP/2. The value is an [options object](https://nodejs.org/api/https.html#https_https_createserver_options_requestlistener) passed to `https.createServer()`.
Required options include `key`/`cert` or `pfx` for server identity. Using `server.proxy` will disable HTTP/2 while maintaining TLS support.
For default configuration values, include the actual implementation details as seen in the CORS example, which clearly specifies the regex pattern for allowed origins. This precision prevents confusion, reduces follow-up questions, and ensures developers can implement network features correctly and securely.
Configuration settings should align with official language documentation and established community standards rather than arbitrary personal preferences. This applies to indentation styles, formatter configurations, and syntax requirements.
For language-specific settings, consult official documentation:
For tool configurations, ensure commands and arguments are syntactically correct:
# Correct formatter configurations
formatter = { command = "prettier", args = ["--parser", "typescript"] }
formatter = { command = "biome", args = ["format", "--stdin-file-path=a.js"] }
formatter = { command = "deno", args = ["fmt", "--ext", "js"] }
# Use full 6-character hex codes, not 3-character shortcuts
"ui.background" = { bg = "#262335" } # not "#263"
This ensures consistency with ecosystem expectations and prevents configuration errors that could break functionality.
Hardcoded configuration values scattered throughout codebases create maintenance burdens and increase the risk of inconsistency. Define configuration values (like versions, paths, and feature flags) in a single location and reference them elsewhere.
For build systems and CI workflows:
Example:
# GOOD: Define version at the top level
env:
ZIG_VERSION: "0.13.0"
jobs:
build:
steps:
- name: Setup Zig
uses: goto-bus-stop/setup-zig@v2
with:
version: ${{ env.ZIG_VERSION }}
test:
steps:
- name: Build with Zig
run: zig-${ZIG_VERSION} build test
This approach makes version updates simpler, reduces errors from inconsistent values, and makes configuration more maintainable. For complex configurations, consider creating a dedicated configuration module that can be imported by other components of the system.
Always generate configuration files programmatically when they contain dynamic content that changes frequently or needs to stay in sync with the application (like version numbers, release dates, or build timestamps). Manual maintenance of such files is tedious, error-prone, and creates maintenance overhead.
For example, instead of manually updating version information in XML metadata files:
<!-- Avoid manual updates like this -->
<releases>
<release version="1.0.1" date="2024-12-31">
<url type="details">https://ghostty.org/docs/install/release-notes/1-0-1</url>
</release>
</releases>
Generate these files during the build process:
# Generate at build time to ensure consistency with application version
generate_appdata_xml --version="$APP_VERSION" --build-date="$(date +%Y-%m-%d)" --release-notes-url="https://ghostty.org/docs/install/release-notes/$APP_VERSION"
This approach ensures configuration files stay synchronized with the application state and eliminates manual update errors.
Always pin specific versions for base images, dependencies, and environment configurations to ensure reproducible builds and prevent unexpected failures from upstream changes.
When configuring Docker images, development containers, or dependency management tools, specify exact versions rather than using generic tags like “latest” or broad version ranges. This prevents builds from breaking when upstream maintainers release new versions or change default behaviors.
Example from Docker configurations:
# Instead of generic versions
FROM python:3
# Use pinned versions
FROM python:3.11-slim-bookworm
# Pin dependency versions
ARG POETRY_VERSION=1.8
RUN pip install "poetry==${POETRY_VERSION}"
This practice is especially critical for:
The small overhead of occasionally updating pinned versions is far outweighed by the stability and predictability gained, particularly when upstream changes can introduce security vulnerabilities or breaking changes that affect your build process.
Configuration options must be documented comprehensively with:
Example of well-documented config:
/// Controls whether to disable GDK color management in GTK applications.
///
/// By default this is set to `false`, meaning color management is enabled.
/// You may want to enable this setting (set to `true`) if you experience:
/// - Incorrect or washed out colors in your terminal
/// - Color inconsistencies between GTK applications
/// - Performance issues related to color management
///
/// This is a workaround for known issues with GTK's color management implementation,
/// particularly affecting applications running under Wayland.
/// Fixed in GTK 4.15.6.
@"gtk-gdk-disable-color-mgmt": bool = false,
Poor documentation can lead to user confusion, support issues, and inconsistent usage. Clear documentation helps users understand when and how to use configuration options effectively.
Break down complex code blocks and expressions into simpler, more readable components. Complex boolean logic, nested conditions, and multi-operation lines should be refactored for clarity.
Key practices:
Example - Before:
return unless artifacts.reject do |k|
k.is_a?(::Cask::Artifact::Font)
end.empty?
After:
return if artifacts.all?(::Cask::Artifact::Font)
Or when dealing with complex conditions:
Before:
print_stderr = !(verbose && show_info).nil?
After:
print_stderr = if verbose && show_info
true
else
false
end
This approach makes code easier to read, understand, and maintain while reducing the cognitive load on reviewers and future maintainers.
When working with Vue single-file components, pay special attention to how imports are processed, particularly with query parameters. URL handling can significantly impact module resolution and hot module replacement (HMR).
Ensure proper handling of URLs with query parameters when importing Vue components to prevent duplicate entries in the module graph. For example, when a .html?vue file has additional query parameters like &lang.js, injecting further parameters (like ?import) can cause issues.
// Potentially problematic:
import Component from './Component.vue?custom=param&lang.js'
// Consider how query parameters are processed in your build tooling
// Be careful when manually adding parameters to imports
Also note that HMR behavior differs between file update, create, and delete operations. Custom HMR plugins only run on ‘update’ events by default, not on ‘create’ or ‘delete’. When developing components that rely on HMR, test all file operations to ensure proper reactivity during development.
When working with tests in a monorepo, implement a hybrid testing approach that balances local development experience with CI performance. Set up local Vitest configurations in each package while also configuring a root workspace for unified testing. This preserves Turborepo’s caching benefits in CI while providing a better developer experience.
Always explicitly specify coverage outputs in your Turborepo configuration:
{
"tasks": {
"test": {
"dependsOn": ["^test", "@repo/vitest-config#build"],
"outputs": ["coverage/**"] // Explicitly define coverage output paths
},
"merge-json-reports": {
"inputs": ["coverage/raw/**"],
"outputs": ["coverage/merged/**"]
},
"report": {
"dependsOn": ["merge-json-reports"],
"inputs": ["coverage/merge"],
"outputs": ["coverage/report/**"]
}
}
}
This approach enables you to efficiently run tests locally during development while maintaining proper caching for CI environments and generating comprehensive coverage reports that can be merged across packages.
Choose methods and patterns that reduce unnecessary memory allocations and object creation to improve performance. When working with buffers, prefer direct methods like Buffer.byteLength() over approaches that create intermediate objects:
// Less efficient - creates an unnecessary buffer object in memory
const size = Buffer.from(chunk.code).length;
// More efficient - calculates the byte length directly
const size = Buffer.byteLength(chunk.code);
When handling object operations, avoid deep cloning when only specific properties are needed. Use targeted cloning strategies based on the actual requirements:
// Less efficient - may clone objects unnecessarily
function deepClone<T>(value: T): T {
if (Array.isArray(value)) {
return value.map((v) => deepClone(v)) as T;
}
if (isObject(value)) {
const cloned: Record<string, any> = {};
for (const key in value) {
cloned[key] = deepClone(value[key]);
}
return cloned as T;
}
// Only use structuredClone for complex types that need it
if (value instanceof RegExp) {
return structuredClone(value);
}
return value as T;
}
Be mindful of expensive operations like structuredClone() which can significantly impact performance on basic primitives. Consider using specialized handling for different data types to optimize memory usage and processing time.
Maintain up-to-date build and CI/CD tooling to leverage the latest features, performance improvements, and security patches. Regularly check for updates to build orchestration tools like Turborepo and use provided codemods for seamless upgrades. When configuring build pipelines, optimize task dependencies by using topological approaches (like Turborepo’s topo mode) to enable more efficient parallel execution. Additionally, when adding new scripts to your workflow, ensure proper execution order by establishing clear dependencies between build steps.
Example:
{
"name": "project",
"devDependencies": {
"turbo": "^2.0.0" // Using latest major version
},
"scripts": {
"upgrade-turbo": "npx @turbo/codemod upgrade",
"build": "turbo run build",
"preview-storybook": "turbo run build preview-storybook" // Ensuring build runs first
},
"turbo": {
"pipeline": {
"test": {
"dependsOn": ["^test"],
"dependencyMode": "topo" // Only block on actual dependencies
}
}
}
}
Code-style changes (formatting, spacing, selector tweaks, spell/lint adjustments) must not alter semantics or intended content.
div.mermaid svg:first-of-type {
border: 2px solid darkred;
}
codespell-ignore pragma) rather than changing the underlying payload.This prevents unintended styling regressions and avoids subtle bugs from formatting-induced content changes.
Explicitly define and standardize build configuration patterns across the project to ensure consistent behavior and optimal performance. Use explicit build type declarations and separate configurations for development and release builds.
Key points:
Example:
# Good: Explicit build configuration
packages = eachSystem (system: {
default = pkgs.callPackage mkHelix {
cargoBuildType = "release"; # Explicit build type
rustPlatform = stableToolchain; # Production toolchain
};
# Debug build with development toolchain
debug = pkgs.callPackage mkHelix {
cargoBuildType = "debug";
rustPlatform = devToolchain;
};
});
# Avoid: Implicit or mixed configurations
packages = eachSystem (system: {
default = pkgs.callPackage mkHelix {}; # Implicit build type
});
This pattern ensures clear separation between development and production builds, makes configuration intentions explicit, and helps prevent unintended performance impacts from build options.
Always use workspace-level dependency declarations (workspace = true) rather than specifying exact versions in individual crates. This ensures consistency across your project, simplifies maintenance, and reduces the risk of version conflicts.
When adding or updating dependencies:
Example:
- git2 = { version = "0.19.0", default-features = false }
+ git2 = { workspace = true, default-features = false }
or
- futures = "0.3.30"
+ futures = { workspace = true }
This practice centralizes dependency management at the workspace level, making updates and security patches easier to apply consistently across all crates.
Integration/e2e tests should be deterministic and directly tied to specified behavior.
Apply these rules:
1) Avoid time-based waits. Wait for an observable condition (DOM element present, network idle, event emitted, SVG rendered) instead of cy.wait(500).
2) Make syntax/format expectations strict. When behavior depends on parsing (e.g., dateRange), define the accepted format precisely and test the exact edge cases (whitespace/colon/spacing variants, valid date-only/time-only/date+time cases).
3) Eliminate flakiness from external assets. For font/icon rendering, use a stable local asset source and/or wait for fonts to finish loading before rendering/asserting.
4) Keep snapshot identifiers stable. If your visual tests compare images, avoid changing snapshot keys/titles; add tests within existing describe blocks to prevent snapshot mismatch.
Example (replace time-based waits):
// Bad (flaky)
cy.wait(500);
// Prefer (event/condition-based)
cy.get('svg', { timeout: 10_000 }).should('exist');
// or: wait for a specific rendered marker / data attribute
// cy.get('[data-testid="render-complete"]', { timeout: 10_000 }).should('be.visible');
Example (strict format tests for parsing):
const ok = 'dateRange : 13:00, 14:00';
const bad1 = 'dateRange: 13:00, 14:00';
const bad2 = 'dateRange 13:00, 14:00';
expect(parserFnConstructor(`gantt\n${ok}`)).not.toThrow();
expect(parserFnConstructor(`gantt\n${bad1}`)).toThrow();
expect(parserFnConstructor(`gantt\n${bad2}`)).toThrow();
Maintain consistent naming patterns throughout your codebase, following established conventions and ensuring uniformity within the same context. This includes using correct syntax for configuration values, matching case conventions for related identifiers, organizing entries systematically (like alphabetically), and choosing descriptive names that clearly indicate purpose.
Examples of good practices:
underlined instead of underline in modifier arrays to match the established APIselectionfg consistently instead of mixing selectionFG and selectionfghx_launcher.sh instead of generic names like hx[language-server.<name>] for clarityInconsistent naming creates confusion, makes code harder to maintain, and can lead to subtle bugs when identifiers don’t match their expected format.
Separate development-time assertions from production error handling based on the runtime environment. Development assertions should be used to catch programming errors and validate internal assumptions during development, while production code should focus on graceful error handling with meaningful user-facing messages.
Use environment checks to conditionally enable development assertions:
const assertComment = process.env.NODE_ENV === "production"
? noop
: function(comment, text) {
if (!isLineComment(comment) && !isBlockComment(comment)) {
throw new TypeError(`Unknown comment type: "${comment.type}".`);
}
};
// In production, provide simple validation with clear messages
if (!isLineComment(comment) && !isBlockComment(comment)) {
throw new TypeError(`Unknown comment type: "${comment.type}".`);
}
This approach allows comprehensive debugging during development while maintaining clean, user-friendly error handling in production. Configure your build system to remove development-only assertions rather than replacing them with verbose conditional checks that add unnecessary complexity to the codebase.
Avoid hardcoded or duplicated configuration values by centralizing them in a dedicated location. When configurations are needed across multiple components, extract the logic for accessing and applying them so it can be reused. This prevents inconsistencies when configurations change and makes the codebase more maintainable.
Instead of this:
private enum WindowConfig {
static let defaultSize = CGSize(width: 800, height: 600)
}
Do this:
// In a centralized configuration file/class
struct WindowConfigManager {
func getDefaultSize(from config: AppConfig) -> CGSize {
// Extract from config or fallback to default
return CGSize(
width: config.windowWidth ?? 800,
height: config.windowHeight ?? 600
)
}
}
// When using the configuration
let windowSize = windowConfigManager.getDefaultSize(from: appConfig)
This approach ensures configurations are managed consistently, prevents duplicate values across the codebase, and makes it easier to update configuration behavior in one place.
Ensure all code examples and documentation maintain consistent formatting standards, use descriptive variable names, and apply proper syntax highlighting. This includes using meaningful identifiers instead of cryptic names like a60, applying correct language tags for syntax highlighting (e.g., css instead of jsx for CSS code), and providing clear examples rather than error messages when demonstrating new features.
Examples of good practices:
something instead of a60 for importscss for CSS code,ts for TypeScriptimport { type A } from "mod"; instead of syntax error messagesyarn exec prettier across all documentation/** @type {import("prettier").Options} */This consistency helps developers understand features more clearly and maintains professional documentation standards across the entire codebase.
Implement error handling that accumulates diagnostics rather than failing immediately, especially for operations that could help users identify and fix problems. Design systems to continue functioning when possible, with configurable strictness levels.
For diagnostic operations like queries or validation, prioritize providing useful information even when errors exist. This helps users understand and fix issues rather than blocking them entirely.
Example implementation pattern:
// Instead of immediately failing on first error
if err != nil {
return fmt.Errorf("invalid task configuration: %w", err)
}
// Use a diagnostic collector approach
diagnostics := &DiagnosticCollector{}
if err != nil {
diagnostics.Add(Diagnostic{
Severity: Error,
Message: fmt.Sprintf("invalid task configuration: %s", err),
})
}
// Only fail immediately for critical errors or in execution mode
if !queryMode && diagnostics.HasErrors() {
return diagnostics.Error()
}
// Otherwise, continue with as much functionality as possible
// but include warnings about the issues
return result, diagnostics.Warnings()
Consider providing configuration options for users to control error behavior, such as the --continue flag with values like “none”, “independent-tasks-only”, or “all” to specify which operations should continue when errors occur.
Documentation should be written from the perspective of its intended audience, using language and detail levels appropriate for that audience. Focus on what matters most to the reader rather than technical implementation details.
For user-facing documentation (changelogs, READMEs, FAQs):
For developer documentation:
Example from changelog entries:
❌ Technical: "Shell initialization on macOS to manually check the ~/.hushlogin file"
✅ User-focused: "Hide login message if ~/.hushlogin is present"
❌ Vague: "could be easily done by user"
✅ Precise: "can be done outside of alacritty_terminal"
This approach ensures documentation serves its intended purpose by meeting readers where they are and providing the information they actually need.
When catching an exception and re-throwing a different exception type, always preserve the original exception as the cause. This maintains the full stack trace and context, making debugging significantly easier.
Swallowing the original exception by not setting it as a cause breaks the error chain and hides valuable debugging information about the root cause of the failure.
Bad:
try {
return Long.parseUnsignedLong(string);
} catch (NumberFormatException e) {
throw new ParseException("identifier is too large"); // Lost original cause!
}
Good:
try {
return Long.parseUnsignedLong(string);
} catch (NumberFormatException e) {
throw new ParseException("identifier is too large", e); // Preserves cause
}
For custom exceptions that don’t accept a cause parameter, use initCause():
try {
// some operation
} catch (IOException e) {
CustomException custom = new CustomException("operation failed");
custom.initCause(e);
throw custom;
}
This practice is especially important in complex systems where exceptions may be caught and re-thrown multiple times through different layers, as each layer can add context while preserving the original root cause.
Always provide clear documentation and implementation for caching strategies, including key generation, invalidation policies, and default behaviors. When implementing caching:
--cache=local:rw,remote:r)Proper cache strategy documentation prevents unexpected behavior, improves performance, and gives users control over how and where their data is cached.
Use naming that is explicit, consistent, and self-describing.
Rules:
today, midnightDate).untilStatement[1]).Example:
// Named constants (avoid magic strings)
export const STMT_STATE = 'state';
export const STMT_DIR = 'dir';
function getDirection(rootDoc) {
const doc = rootDoc.find((d) => d.stmt === STMT_DIR);
return doc;
}
// Shared ID generator (consistent IDs)
export const getEdgeId = (from, to, { counter = 0 } = {}) =>
`edge_${from}_${to}_${counter}`;
// Named capture groups (clarity)
const match = /^until\s+(?<ids>[\d\w- ]+)/.exec(str);
if (match) {
for (const id of match.groups.ids.split(' ')) {
// ...
}
}
Apply these consistently across the codebase to reduce confusion, prevent subtle mismatches (like casing), and make identifiers easier to search, understand, and maintain.
Leverage Rust’s functional operators for handling nullable and optional values. Instead of using unwrap() or explicit if-statements, prefer combinators like ok(), and_then(), map_or_else() and the ? operator with Option types. This leads to more concise, readable, and null-safe code:
// Instead of this:
let package_manager = PackageJson::load(&base.repo_root.join_component("package.json"))
.and_then(|package_json| {
Ok(PackageManager::read_or_detect_package_manager(
&package_json,
&base.repo_root,
))
})
.map_or_else(|_| "Not found".to_owned(), |pm| pm.unwrap().to_string());
// Prefer this:
let package_manager = PackageJson::load(&base.repo_root.join_component("package.json"))
.ok()
.and_then(|package_json| {
PackageManager::read_or_detect_package_manager(&package_json, &base.repo_root).ok()
})
.map_or_else(|| "Not found".to_owned(), |pm| pm.to_string());
// Instead of this:
if self.commits.is_empty() {
return None;
}
if let Some(first_commit) = self.commits.first() {
let id = &first_commit.id;
return Some(format!("{id}^"));
}
// Prefer this:
let first_commit = self.commits.first()?;
let id = &first_commit.id;
Some(format!("{id}^"))
Additionally, prefer using Option
When adding or changing configurable behavior, define it in the correct config scope and expose it via YAML/frontmatter—don’t introduce new diagram-specific syntax/directives, and don’t place diagram-only options in global config.
Rules
elk.nodePlacement.strategy is an object path). Avoid ambiguous/flat structures that don’t match the existing nesting patterns.config: entry.Examples
---
config:
markdownAutoWrap: false
---
gantt %% gantt content …
Apply these rules for each new option so it has a single source of truth (schema), a clear location (scope), and a consistent user-facing configuration mechanism (YAML).
---
## Protect shared state
<!-- source: wavetermdev/waveterm | topic: Concurrency | language: Go | updated: 2025-02-13 -->
Ensure mutable shared data is never exposed or accessed without explicit synchronization. When data crosses goroutine boundaries you must either copy it, provide a concurrency-safe accessor that returns a snapshot, or protect it with proper synchronization (mutexes, atomics, or reference counting). This prevents races when marshaling, iterating, or doing read-modify-write updates.
Guidelines (practical):
- Return copies for internal maps/structs or provide an accessor that returns a copied snapshot. e.g.:
func (m *MShellProc) GetRemoteRuntimeState() RemoteRuntimeState {
varsCopy := make(map[string]string)
for k,v := range m.Remote.StateVars { // hold m lock while reading
varsCopy[k] = v
}
state.RemoteVars = varsCopy
return state
}
- Do not expose internal mutable slices/maps directly. If an API must iterate over a collection that is guarded by a lock, provide a locked copy for iteration (avoid iterating over the locked map). Use helper methods like remote.GetRemoteMap() that return a copy.
- Protect read-modify-write operations (e.g., append/offset updates) with a lock or an atomic protocol. If an operation must be atomic across multiple fields, hold the mutex for the entire operation.
- Use reference counting or equivalent coordination when cache entries or resources may be concurrently flushed and used. Only remove/zero resources when ref count is zero and hold the lock while updating refs.
- Make channel ownership explicit: only the sender should close a channel. Do not attempt to close a channel from a receiver. If draining with a timeout, avoid hiding ownership errors—fail fast or document panic behavior deliberately.
- Prefer fail-fast when unexpected contention indicates a logic error (e.g., file-create flock): return an error immediately rather than silently waiting.
- Choose callbacks vs channels deliberately: callbacks are lightweight and can capture closures but will run inline and block the caller; channels can decouple execution and allow concurrency but add complexity. Document blocking behavior and ensure caller expectations are clear.
Why: these rules address several recurring concurrency bugs in our codebase—races caused by sharing internal state (maps/slices), races when updating file offsets or cache entries concurrently, unsafe iteration over maps, incorrect channel closing, and hidden blocking. Applying them reduces data races, unexpected panics, and subtle bugs during marshaling or concurrent operations.
Quick patterns:
- Safe accessor that returns snapshot: provide function that locks, copies, unlocks, return copy.
- Refcount pattern for cache entry:
entry.Lock.Lock()
entry.Refs++
entry.Lock.Unlock()
// use entry
entry.Lock.Lock()
entry.Refs--
if entry.Refs == 0 && shouldRemove { remove }
entry.Lock.Unlock()
References: [0,1,2,3,4,5,6,7]
---
## Semantic naming conventions
<!-- source: vercel/turborepo | topic: Naming Conventions | language: TypeScript | updated: 2025-02-13 -->
Use names that clearly convey the purpose and content of variables, parameters, and properties. When working with objects, always access specific properties rather than using the object directly in string operations to prevent "[object Object]" outputs. Include proper type declarations for parameters that describe their structure.
Example:
```typescript
// Incorrect
function replacePackageManager(packageManager, text) {
const updatedText = match.replace(replacementRegex, `${packageManager} run`);
// Results in "[object Object] run"
}
// Correct
function replacePackageManager(packageManager: { name: string }, text: string): string {
const updatedText = match.replace(replacementRegex, `${packageManager.name} run`);
// Results in "npm run" or similar
}
// Improved parameter naming
affectedPackages(
files: Array<string>,
base?: string | undefined | null, // "base" clearly indicates this is the base commit for comparison
)
Choose parameter names that use domain-specific terminology where appropriate to make code more self-documenting and easier to understand.
Ensure caching implementations store the correct data and use appropriate strategies for the context. Cache should store the final processed output, not intermediate or input data, and should include strategy options for different security/performance requirements.
Key considerations:
--write flag, cache the formatted content, not the unformatted input.--cache-strategy option.Example implementation:
// Good: Store formatted output and handle strategy
if (isCacheExists && cacheStrategy === "content") {
result = { formatted: input };
} else {
result = format(context, input, options);
// Cache the formatted result, not the input
formatResultsCache?.setFormatResultsCache(filename, result.formatted, options);
}
// Good: Handle cache format changes
try {
this.#fileEntryCache = fileEntryCache.createFromFile(cacheFileLocation, useChecksum);
} catch {
// If cache format changed, delete and retry
fs.unlinkSync(cacheFileLocation);
this.#fileEntryCache = fileEntryCache.createFromFile(cacheFileLocation, useChecksum);
}
This ensures cache reliability and prevents subtle bugs where cached data doesn’t match expected output.
Implement comprehensive cache invalidation mechanisms that automatically handle format changes between versions while providing clear manual removal options. When cache formats change, automatically detect and remove incompatible cache files to prevent runtime errors. Additionally, document cache locations and provide accurate removal commands for manual cache management.
For automatic invalidation, check cache format compatibility on startup:
# Cache format changed in version 3.5, remove old cache to prevent crashes
if (cacheFormatVersion !== currentVersion) {
removeOutdatedCache();
}
For manual removal, provide precise documentation with correct command syntax:
# Remove cache manually (note: no -f flag to show errors if file not found)
rm ./node_modules/.cache/prettier/.prettier-cache
This approach prevents crashes from incompatible cache formats while giving users clear guidance for manual cache management when needed.
Names should accurately reflect the actual behavior, constraints, and purpose of the code element they represent. Misleading names create confusion and make code harder to understand and maintain.
Key principles:
RequiredOptions if it contains optional properties)Example of problematic naming:
// Misleading - contains optional properties despite "Required" in name
export interface RequiredOptions {
singleAttributePerLine: boolean;
jsxBracketSameLine?: boolean; // Optional property in "Required" interface
}
Better approach:
// Clear and accurate naming
export interface FormattingOptions {
singleAttributePerLine: boolean;
jsxBracketSameLine?: boolean;
}
// Or separate required vs optional
export interface RequiredFormattingOptions {
singleAttributePerLine: boolean;
}
export interface OptionalFormattingOptions {
jsxBracketSameLine?: boolean;
}
When reviewing code, ask: “Does this name accurately describe what this element actually does or contains?” Names that contradict their implementation create technical debt and developer confusion.
Write code that is explicit, predictable, and organized to improve readability and avoid subtle bugs.
What to do:
Make control flow explicit. In switch statements and other control structures always use break/return/continue as appropriate. If fallthrough is intentional, annotate it with a clear comment or a lint directive (e.g. // fallthrough). Example (fix missing break): switch (action.type) { case LayoutTreeActionType.ReplaceNode: { // …handle replace… break; // prevent accidental fallthrough } case LayoutTreeActionType.SplitHorizontal: { // …handle split… break; } }
Avoid redundant calls and duplicate side-effects. Trust single-responsibility helpers and do not repeat work already performed by a called method. If a method already sets state, do not call the setter again. Example (remove duplication): openAIAssistantChat(): void { this.setActiveAuxView(appconst.InputAuxView_AIChat); // don’t also call this.setAuxViewFocus(true) if setActiveAuxView already sets focus }
Organize runtime values and small types where they belong. Place enums, constants, and small runtime-bound types close to the code that uses them unless there’s a strong reason to centralize them. If you move a value to a shared file, document why (runtime usage, reuse across modules).
Why this matters:
When in doubt, prefer clarity: add a short comment explaining non-obvious choices (intentional fallthrough, why a value is placed in a shared file, or why a duplicate call remains).
Always configure server security settings with explicit allowed lists rather than permissive values. Using true for settings like server.allowedHosts or server.cors creates serious security vulnerabilities by allowing any website to access your development server through DNS rebinding attacks, potentially exposing source code and sensitive content.
// INSECURE: Don't do this
export default defineConfig({
server: {
allowedHosts: true, // Allows any host to access your server
cors: true // Allows any origin to make requests
}
})
// SECURE: Do this instead
export default defineConfig({
server: {
allowedHosts: ['myapp.local', '.example.com'], // Only specific hosts
cors: {
origin: ['https://trusted-site.com'] // Only specific origins
}
}
})
Only add domains you control to these allowlists, and never add Top-Level Domains like .com. This protection is especially important for development servers where authentication might be disabled or less restrictive.
Ensure all network operations are cancellable, timeout-protected, and executed where the resource lives.
Motivation
Rules 1) Always use context and timeouts for outbound network calls and dials. Use context-aware APIs (DialContext, http.NewRequestWithContext) and set sensible connect/read timeouts. Example (HTTP): ctx, cancel := context.WithTimeout(parentCtx, 10*time.Second) defer cancel() req, _ := http.NewRequestWithContext(ctx, “POST”, url, body) resp, err := http.DefaultClient.Do(req)
Example (websocket dial): d := websocket.Dialer{HandshakeTimeout: 20 * time.Second} conn, _, err := d.DialContext(ctx, wsURL, nil)
2) Make long-running reads cancellable by closing the underlying connection from another goroutine when the context expires. Closing the socket unblocks ReadMessage/Read calls so goroutines don’t leak. Example: go func() { <-ctx.Done() conn.Close() }()
3) Prefer incremental transfers for streaming channels: send only new/changed messages instead of replaying entire history to reduce bandwidth and contention on shared websockets. If a timeout happens, send a clear partial/final packet (e.g., a timeout or summary packet) so the client retains what it already received.
4) Execute resource-heavy or resource-local operations on the side that owns the resource (server-side) when invoked remotely. For example, create zip archives of a server’s config on the server and then copy the resulting artifact to the client (via filestore/WFS or an explicit transfer), rather than trying to reconstruct the server’s environment on the client.
5) Preserve transport/URI semantics when parsing and serializing (e.g., trailing slashes) so network requests behave as expected.
When to revisit
References: discussions 0,1,2,3,4,5
State and document explicit, unambiguous contracts for all API endpoints and RPC messages, especially around resource identity, data encoding, and file-operation semantics. Motivation: inconsistent assumptions about where a path comes from, whether payloads are encoded, and what ReadAt/WriteAt should return lead to brittle clients and surprising server behavior. How to apply:
Resource identity in URLs: treat resources as RESTful paths when they represent server resources. Put file/config paths in the URL path segment rather than opaque query params so clients can request /config/keybindings.json or /files/{bucket}/{object}. Example: change
// avoid reading resource from query qvals := r.URL.Query() filePath := qvals.Get(“path”)
// prefer extracting from URL path (mux param or path prefix) // e.g. GET /config/{path} filePath := mux.Vars(r)[“path”]
Encoding contracts: document and enforce how binary data is transported. If a field is named data64, require base64 encoding at the producer side and decode at the consumer side. Make encoding explicit in code:
// when producing file chunks chunk := buf[:n] resp.Data64 = base64.StdEncoding.EncodeToString(chunk)
// when consuming data, err := base64.StdEncoding.DecodeString(resp.Data64)
If sparse writes are supported, prefer these rules: pad only as needed (e.g., block-level padding to avoid huge copies), do not include implicit padding bytes in the bytesWritten return value (return only the number of user bytes written), and ensure ReadAt returns zeros for any uninitialized region within the logical file range. Example contract: “WriteAt will left-pad up to MaxBlockSize in-memory for efficiency; returned bytesWritten excludes implicit zeros. ReadAt will return logical zeros for uninitialized regions within the file length.”
Responsibility boundaries: document which side normalizes/validates paths and who encodes/decodes payloads. For non-URL path formats acceptible to client libraries, document helper functions and keep server endpoints stable. Example: FileReadCommand should pass a well-formed FileData with Info.Path when the fileshare client is expected to own normalization:
data, err := wshclient.FileReadCommand(RpcClient, wshrpc.FileData{Info: &wshrpc.FileInfo{Path: fmt.Sprintf(pattern, oid, fname)}}, …)
Checklist for reviewers and implementers:
Following these rules reduces surprises for clients, avoids implicit assumptions, and makes APIs easier to evolve and document.
Ensure documentation is clear, precise, and technically accurate to prevent confusion and build errors. This includes proper escaping of special characters, consistent terminology, version-specific accuracy, and unambiguous language.
Key practices:
Example of proper escaping:
<!-- Problematic -->
#### Handle <style> and <pre> tags in Handlebars/Glimmer
<!-- Better -->
#### Handle `<style>` and `<pre>` tags in Handlebars/Glimmer
Example of version-specific clarity:
<!-- Vague -->
- ES modules: `standalone.mjs`, starting in version 2.2
<!-- Clear -->
- ES modules: `standalone.mjs`, starting in version 3.0 (In version 2, `esm/standalone.mjs`.)
This prevents build failures, reduces reader confusion, and maintains professional documentation standards.
Make deliberate structural decisions that improve code maintainability and readability. Consider the appropriate implementation layer, proper encapsulation patterns, and logical organization of code components.
Key principles:
function awaitNextLoad(... instead of WebContents.prototype._awaitNextLoadit('returns image with requested size when both dimensions are bigger', async () => { instead of multiple nested describe blocksExample of proper encapsulation:
// Instead of:
WebContents.prototype._awaitNextLoad = function (navigationUrl: string) {
// implementation
}
// Use:
function awaitNextLoad(navigationUrl: string) {
// implementation
}
// Then call with: return awaitNextLoad.call(this)
This approach reduces code complexity, improves maintainability, and makes the codebase easier to navigate and understand.
Ensure UI elements (buttons, icons, tooltips, overlays) are only registered or rendered when the corresponding configuration or feature flag is enabled. Also ensure feature flags are passed into components or a central store so components make rendering decisions from configuration rather than hard-coded assumptions.
Motivation
How to apply
Propagate flags: accept feature flags as props at top-level components and pass them into your UI components or into the app/store. Example pattern (top-level): // LikeC4Diagram.tsx (pattern reference) <LikeC4Diagram enableSearch={enableSearch} />
Gate registration: only add buttons/actions to arrays when the flag is true. Example: const buttons = [] if (flags.enableVscode) { buttons.push({ id: ‘open-in-vscode’, label: ‘Open in VSCode’, onClick: () => { /* … */ }, }) }
Gate rendering: only render optional UI elements in JSX when the flag is true or derived from the store/props. Example:
Notes
When evolving public APIs, prioritize backwards compatibility through proper deprecation strategies and careful interface design. Avoid breaking changes by using overloads, deprecation warnings, and gradual migration paths.
Key principles:
Example approach for adding new parameters:
def add_repository(
self,
repository: Repository,
priority: Priority = Priority.PRIMARY,
# Keep old parameters for backwards compatibility
default: bool = False,
secondary: bool = False
) -> None:
# Handle both old and new parameter styles
if default or secondary:
warnings.warn("default/secondary parameters are deprecated, use priority instead")
This ensures external code continues working while providing a clear upgrade path. Always weigh the benefits of cleaner APIs against the cost of breaking existing integrations.
Always explicitly specify configuration values rather than relying on defaults or implicit behavior. Poetry requires unambiguous configuration to function correctly, and many issues arise from incomplete or assumed specifications.
Key areas requiring explicit specification:
Version Constraints: Explicitly declare Python version requirements and dependency constraints. If using both project.requires-python and tool.poetry.dependencies.python, ensure the Poetry specification is a subset of the project specification.
[project]
requires-python = ">=3.8"
[tool.poetry.dependencies]
python = "^3.8" # Must be subset of project.requires-python
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"] # Include version constraints
Build Dependencies: Assume only Python built-ins are available in build environments. Explicitly declare all required packages, including common ones like setuptools.
[build-system]
requires = ["poetry-core", "setuptools", "cython"] # Don't assume setuptools is available
Repository Sources: Explicitly configure package source priorities and constraints to avoid dependency confusion attacks. Omit URLs for PyPI when configuring it explicitly.
[[tool.poetry.source]]
name = "pypi"
priority = "primary" # No URL needed for PyPI
[[tool.poetry.source]]
name = "private-repo"
url = "https://private.example.com/simple/"
priority = "explicit"
CLI Usage: Use -- to terminate option parsing when values might start with hyphens, and specify full paths or explicit options rather than relying on defaults.
poetry config http-basic.repo token -- ${TOKEN} # Prevent parsing issues
This approach prevents configuration ambiguity, reduces debugging time, and ensures consistent behavior across different environments and Poetry versions.
Always validate values and short-circuit on errors; guard uses of possibly nil/empty values while avoiding redundant checks when types guarantee non-nil.
Motivation:
Practices to follow:
Validate external/untrusted inputs and parse results before use and return early on error. Example: check parse errors and avoid using a possibly nil value:
// wrong: may deref newPk when parsing failed newPk, rtnErr := EvalMetaCommand(ctxWithHistory, pk) if rtnErr == nil { update, rtnErr = HandleCommand(ctxWithHistory, newPk) }
// correct: short-circuit on error newPk, rtnErr := EvalMetaCommand(ctxWithHistory, pk) if rtnErr != nil { return nil, rtnErr } update, rtnErr = HandleCommand(ctxWithHistory, newPk)
Guard resource operations that may be nil (files, sockets, interfaces) before calling methods like Close. Example:
defer func() { for _, extraFile := range cw.Cmd.ExtraFiles { if extraFile != nil { extraFile.Close() } } }()
Validate numeric/string inputs (use helpers) to enforce expected ranges and avoid later checks: Example: use a helper for positive integers
idx, err := resolvePosInt(newScreenIdxStr, 1) if err != nil { return nil, err }
Prefer using slices directly instead of pointers to slices; a nil slice expresses absence without extra indirection. Example: use sudoPw []byte instead of sudoPw *[]byte
Do not add nil checks when the API/type guarantees non-nil; rely on that contract to keep code clear. If the contract changes or is unclear, update the type or document it rather than peppering checks.
When in doubt, ask: is the value coming from external/untrusted input or can it legitimately be nil? If external or ambiguous: validate and short-circuit. If internal and the type guarantees non-nil: omit redundant checks.
References: discussions [0,2,3,4,5,1]
Do not enable configurations that expose Node.js or Electron APIs to untrusted web content in renderer processes. This includes avoiding nodeIntegration: true for remote content and not directly exposing IPC APIs in preload scripts.
Why this matters:
nodeIntegration: true disables sandboxing and grants full Node.js access to renderer processesipcRenderer.on gives renderers direct access to the entire IPC event systemSecure approach:
// ❌ Dangerous - exposes Node.js APIs to remote content
new BrowserWindow({
webPreferences: {
nodeIntegration: true, // Disables sandbox, security risk
contextIsolation: false
}
})
// ✅ Secure - use sandboxed renderer with controlled API exposure
new BrowserWindow({
webPreferences: {
sandbox: true, // Default since Electron 20
contextIsolation: true, // Default since Electron 20
preload: path.join(__dirname, 'preload.js')
}
})
// In preload.js - expose only specific, validated APIs
const { contextBridge, ipcRenderer } = require('electron')
// ❌ Don't expose raw IPC
window.ipcRenderer = ipcRenderer
// ✅ Expose controlled, specific functions
contextBridge.exposeInMainWorld('electronAPI', {
performAction: (...args) => ipcRenderer.invoke('perform-action', ...args)
})
Always validate the origin and content when handling requests from renderer processes, especially when loading remote content. Use the principle of least privilege - only expose the minimum APIs necessary for your application to function.
Follow the project’s established naming conventions consistently across all code. Use camelCase for variables, functions, and parameters, avoiding Hungarian notation and snake_case. Apply type-specific prefixes: classes should have a ‘C’ prefix (e.g., CXCBConnection), enums should have an ‘e’ prefix (e.g., eAutoDirs), and enum values should be in CAPS with descriptive prefixes (e.g., DIR_AUTO_UP). When possible, wrap standalone functions in appropriate namespaces rather than leaving them in global scope.
Example transformations:
// Before
class XCBConnection { }; // Missing C prefix
enum class AutoDirs { auto_up }; // Missing e prefix, snake_case
bool m_benabled; // Hungarian notation
void some_function(); // snake_case
// After
class CXCBConnection { }; // C prefix for classes
enum class eAutoDirs { DIR_AUTO_UP }; // e prefix, CAPS enum values
bool m_enabled; // No Hungarian notation
void someFunction(); // camelCase
This ensures code readability and maintains consistency with the existing codebase, making it easier for developers to understand type information at a glance and follow established patterns.
Error messages should be descriptive, contextual, and self-identifying to aid debugging and user understanding. Include relevant context like method names, parameter values, or identifiers that help locate the source of the error.
Key principles:
Examples:
// Poor: Generic error without context
LOG(ERROR) << "Unable to initialize logging from handle.";
// Better: Descriptive with context and actionable guidance
LOG(FATAL) << "Unable to open nul device needed for initialization, aborting startup. "
<< "As a workaround, try starting with --" << switches::kNoStdioInit;
// Poor: Missing context
isolate->ThrowException(v8::Exception::Error(
gin::StringToV8(isolate, "Unknown error")));
// Better: Self-identifying with context
isolate->ThrowException(v8::Exception::Error(
gin::StringToV8(isolate, "Failed to retrieve target context for world ID: " + std::to_string(world_id))));
// Poor: Generic error
gin_helper::internal::ReplyChannel::Create(isolate, std::move(callback))
->SendError("WebContents does not exist");
// Better: Include channel context for debugging
gin_helper::internal::ReplyChannel::Create(isolate, std::move(callback))
->SendError("WebContents does not exist for channel: " + channel);
This approach transforms cryptic errors into meaningful diagnostics that developers can act upon, reducing debugging time and improving the overall development experience.
When adding new configuration settings, ensure they are properly integrated across all required system components. Configuration settings must be registered in multiple locations to function correctly and be discoverable by users.
Required integration points include:
Example of complete integration:
# In Config class defaults
"max-retries": 0,
# In _get_normalizer method
"max-retries": lambda val: int(val) if val is not None else 0,
# In ConfigCommand.unique_config_values
"max-retries",
Additionally, prefer user-facing configuration options over hidden implementation details. When deprecating config keys, use explicit user warnings rather than developer-only deprecation warnings, as these changes directly impact end users.
This systematic approach prevents incomplete configuration implementations that can lead to runtime errors, inconsistent behavior, or poor user experience when settings are partially recognized by the system.
Extract complex logic into separate, pure functions to improve testability. Functions with clear inputs and outputs are easier to test in isolation without complex mocking or setup.
For example, instead of embedding logic directly in larger functions:
// Hard to test
export async function transform(args: TransformInput): TransformResult {
// ...
// Complex logic embedded in a larger function
let data = await fs.readFile(readmeFilePath, "utf8");
const replacements = ['pnpm run', 'npm run', 'yarn run', 'bun run'];
const replacementRegex = new RegExp(`\\b(?:${replacements.join('|')})\\b`, 'g');
data = data.replace(replacementRegex, `${selectedPackageManager} run`);
// ...
}
Extract the logic into a testable function:
// Easy to test with various inputs
function replacePackageManager(packageManager: string, text: string): string {
const replacements = ['pnpm run', 'npm run', 'yarn run', 'bun run'];
const replacementRegex = new RegExp(`\\b(?:${replacements.join('|')})\\b`, 'g');
return text.replace(replacementRegex, `${packageManager} run`);
}
// Can now be thoroughly tested with parameterized tests
it.each([
['npm', '`yarn build`', '`npm run build`'],
['pnpm', 'Run `npm start`', 'Run `pnpm run start`'],
// more test cases...
])('should replace package managers correctly', (packageManager, input, expected) => {
expect(replacePackageManager(packageManager, input)).toBe(expected);
});
This approach makes unit testing straightforward and enables comprehensive test coverage through parameterized test cases.
Write focused tests that verify specific functionality without unnecessary setup, while still ensuring complete coverage of edge cases. Instead of duplicating complex structures, create minimal test cases that target individual features directly.
Example:
// Instead of copying an entire playground setup
// packages/vite/src/node/__tests__/build.spec.ts
describe('JSON stringify', () => {
test('tree shaking works correctly', async () => {
// Minimal test configuration
const config = { json: { stringify: true } }
// Test-specific assertions
const result = await buildWith(config)
expect(result.hasTreeShaking).toBe(true)
})
// Include tests for all relevant edge cases
test('handles file:// protocol', async () => {
// Add specific test for this protocol
})
})
This approach improves maintainability by keeping tests focused while still ensuring adequate coverage. When adding tests, consider what specific functionality needs verification and create the minimal test setup required, but be thorough in covering variations and edge cases.
Use explicit and clear patterns when handling null/None values to improve code readability and maintainability. Avoid complex conditional expressions, unnecessary type casting, and ambiguous nullable types.
Key principles:
if version is None: version = packages[0] if packages else None
version = version or packages[0]
2. **Use None to mean "unknown" and empty collections for "known empty":**
```python
# Use None when data availability is uncertain
requires_dist = None # "I don't know what the requirements are"
# Use empty list when you know there are no requirements
requires_dist = [] # "I know there are no requirements"
name = poetry.local_config.get(“name”, “”) headers = kwargs.get(“headers”, {}) or {}
if “name” in distribution.metadata: name = distribution.metadata[“name”]
4. **Avoid unnecessary nullable types:**
```python
# Don't make parameters nullable if they're never actually None
def configure_options(self, io: IO) -> None: # Not IO | None
# io is always provided by caller
# Put the default/expected case first
if output is None:
sys.stdout.write(content)
else:
with open(output, 'w') as f:
f.write(content)
if self._cache_control is None: return None
if self._disable_cache: return None
These patterns make null handling intentions clear, reduce the risk of runtime errors, and improve code maintainability by making the expected behavior explicit.
---
## Fail with messages
<!-- source: Homebrew/brew | topic: Error Handling | language: Shell | updated: 2025-01-12 -->
Functions and scripts should never fail silently. When detecting error conditions, always provide clear error messages to stderr that include context about what failed and why, then return an appropriate non-zero exit code. For user-facing commands, include guidance about correct usage when applicable.
Example:
```bash
url_get() {
if [[ ${#} -eq 0 ]]; then
echo "Error: url_get requires at least one argument (URL)" >&2
return 1
fi
# Function implementation...
}
# Usage with error checking
eval RESULTS=( $(url_get "${URL}" param1 param2) )
if [[ ${#RESULTS[@]} -ne 2 ]]; then
echo "Error: Failed to parse URL=${URL}!" >&2
exit 1
fi
Ensure testing dependencies are properly organized, avoid redundancy, and proactively manage unmaintained packages. Place testing-specific dependencies in the correct dependency groups (e.g., group.test.dependencies rather than group.dev.dependencies). Before adding new testing libraries, verify that existing dependencies don’t already provide the same functionality - for example, use pytest-mock instead of adding a separate mock dependency. Monitor the maintenance status of testing dependencies and plan migration paths for stalled projects.
Example of proper dependency management:
[tool.poetry.group.test.dependencies]
pytest-httpserver = "^1.0.8" # Correctly placed in test group
pytest-mock = ">=3.9" # Use existing mock functionality
# Avoid: mock = "^2.0" # Redundant with pytest-mock
# Plan migration for unmaintained dependencies
urllib3 = "<2.3" # Temporary constraint due to httpretty compatibility
# TODO: Migrate from httpretty to mocket for better maintenance
This approach maintains a clean, maintainable test infrastructure while avoiding dependency conflicts and technical debt.
Comments and documentation should explain WHY code exists and what purpose it serves, not just describe what the code does. Focus on the reasoning, motivation, and intent behind implementation decisions.
When writing comments, ask yourself: “Would a developer understand the purpose and reasoning behind this code without additional context?” If not, add explanatory comments that clarify the intent.
Good examples:
// Attempt to make the context current, if it is not.
let mut was_context_reset = if is_current {
false
} else {
match self.context.make_current(&self.surface) {
// ... implementation
}
};
// Windows environment variables require null-terminated strings,
// with a double null at the end to mark the end of the environment block.
result.push(0);
result.push(0);
Avoid comments that just restate the code:
// This comment provides no value
// Unsafe because of Windows API calls.
unsafe { /* ... */ }
Instead, explain safety or purpose:
// Safe because we verify the handle is valid before dereferencing
unsafe { /* ... */ }
This is especially important for complex logic, platform-specific code, non-obvious algorithms, and any code where the implementation strategy might not be immediately clear to future maintainers.
Improve code readability and maintainability by decomposing large, complex functions into smaller, focused ones. When a function handles multiple responsibilities or becomes difficult to understand at a glance, extract logical parts into well-named helper functions.
For example, instead of a single large function like:
const getCssTagsForChunk = (chunk, toOutputPath, seen = new Set(), parentImports, circle = new Set()) => {
const tags = [];
if (circle.has(chunk)) return tags;
circle.add(chunk);
let analyzedChunkImportCss;
const processImportedCss = (files) => {
// 20+ lines of processing logic...
}
// Another 30+ lines handling imports and more processing...
return tags;
}
Break it down into smaller, focused functions:
const toStyleSheetLinkTag = (file, toOutputPath) => ({
tag: 'link',
attrs: {
rel: 'stylesheet',
crossorigin: true,
href: toOutputPath(file),
},
});
const getCssFilesForChunk = (chunk, seenChunks = new Set(), seenCss = new Set()) => {
// Logic to collect CSS files from chunks
}
const getCssTagsForChunk = (chunk, toOutputPath) =>
getCssFilesForChunk(chunk).map(file =>
toStyleSheetLinkTag(file, toOutputPath)
);
This approach:
When refactoring complex logic, also consider extracting helper functions that handle setup tasks or conditional logic blocks to make the main function flow more obvious.
Maintain consistent formatting and rationale for dependency version constraints in configuration files. Use caret notation (^1.0.0) instead of range notation (>=1,<2) for cleaner syntax when specifying compatible version ranges. When constraining to specific Python versions, choose between explicit version strings ("3.7") and comparison operators ("<3.8") based on maintainability - use explicit versions when targeting a single version for easier removal later, and comparison operators for broader compatibility ranges.
For critical dependencies, document the reasoning behind constraint choices. Exact pinning should be intentional and documented (e.g., “We pin poetry-core exactly since Poetry 1.3 because we release Poetry for every poetry-core bugfix”). Avoid yanked versions by checking package status before updating constraints.
Example:
# Preferred: caret notation for compatible ranges
requests-toolbelt = "^1.0.0"
# Avoid: range notation
requests-toolbelt = ">=1,<2"
# Explicit version for single-version targeting (easier to grep/remove)
"backports.cached-property" = { version = "^1.0.2", python = "3.7" }
# Comparison for broader compatibility
importlib-metadata = { version = "^4.4", python = "<3.10" }
This ensures configuration files are maintainable, constraints are intentional, and version specifications follow consistent patterns across the project.
When creating libraries that integrate with Next.js or other frameworks, organize your code with separate entrypoints for each supported framework. This approach improves bundling efficiency, prevents dependency conflicts, and makes framework-specific code easier to maintain.
Structure your exports with clear path separation:
For example:
// In your package.json exports
{
"exports": {
"./link": "./dist/link.js", // Basic HTML component
"./next-js/link": "./dist/next-link.js", // Next.js specific implementation
"./svelte/link": "./dist/svelte-link.js" // Svelte specific implementation
},
"peerDependencies": {
"next": ">=15" // Specify version ranges when possible
}
}
In your framework-specific implementation:
// ./packages/ui/src/next-link.tsx
import Link from 'next/link';
import type { ComponentProps } from 'react';
type CustomLinkProps = ComponentProps<typeof Link>;
export function CustomLink({ children, ...props }: CustomLinkProps) {
return (
<Link className="text-underline hover:text-green-400" {...props}>
{children}
</Link>
);
}
This pattern allows consumers to import exactly what they need while bundlers can properly tree-shake unused framework code. It also enhances type safety since framework-specific props and behaviors are isolated to their respective entrypoints.
When writing metadata files (such as AppStream, package manifests, or configuration files), always consult and follow the official specifications precisely. Pay special attention to case-sensitive identifiers, valid values, and required formats.
Key practices:
Example from AppStream metadata:
<!-- Correct: Case-sensitive SPDX license ID -->
<project_license>Apache-2.0</project_license>
<!-- Valid metadata license from approved list -->
<metadata_license>MIT</metadata_license>
<!-- Modern tag with legacy compatibility -->
<developer_name>Developer Name</developer_name>
<developer id="org.example">
<name>Developer Name</name>
</developer>
This prevents validation failures, ensures compatibility across different parsers, and maintains professional documentation standards.
When designing configuration interfaces, be intentional about default values and consider their impact on user behavior and data quality. Avoid defaults that users might unconsciously accept without proper consideration, especially for critical settings.
For form configurations, consider forcing explicit user choices rather than providing convenient defaults that might be ignored. Users often have “attention problems and just ignore” default selections, leading to poor data quality where values are not “hand picked and relevant.”
Example approaches:
multiple: true in dropdowns to prevent default selection and force explicit choiceThis principle helps ensure that configuration values reflect deliberate user decisions rather than oversight or convenience.
When writing user-facing documentation, always explain WHY a guideline or requirement exists, not just WHAT users should do. Users are more likely to follow instructions when they understand the reasoning behind them.
Avoid “trust me bro” documentation that simply states rules without context. Instead, provide clear explanations of the problems that guidelines solve or the benefits they provide.
Example from issue templates:
# Poor - just states the rule
description: Please attach log files instead of pasting them.
# Better - explains the reasoning
description: When including text files (such as logs or config), please **always ATTACH** them, and not paste them directly. This is important because pasting text directly clutters the issue with unnecessary keywords, making github issue search useless.
This approach helps users understand the impact of their actions and leads to better compliance with documentation guidelines.
Keep repository configuration files canonical, documented, and free of personal workspace/debug artifacts.
Why: Config files determine runtime behavior and developer onboarding. Committing personal IDE or temporary debug configs pollutes the repo, causes accidental formatting/behavior differences, and hides the canonical way to run the app. Likewise, config schemas consumed by the app should be explicit and stable so tooling/parsers and CI can validate them.
How to apply:
task electron:dev.Enforcement suggestions:
References: discussion indices [0, 1].
Eliminate redundant work by implementing early returns, avoiding unnecessary clones/references, and skipping computations when results won’t be used. This fundamental optimization reduces CPU cycles and improves performance across hot code paths.
Key strategies:
Example from the codebase:
// Before: Unnecessary reference and potential clone
match (&event.payload, event.window_id.as_ref()) {
// After: Direct value usage, avoiding clone
match (event.payload, event.window_id.as_ref()) {
// Early return optimization
if self.frame().damage_all || selection == self.old_selection {
return; // Skip expensive selection damage computation
}
This approach is particularly effective in rendering pipelines, event processing loops, and frequently called functions where small optimizations compound significantly.
When asynchronous operations cross process or component boundaries (backend <> frontend, websocket events, UI lifecycle), design explicit synchronization instead of relying on ad-hoc timing. Apply these rules:
Prefer authoritative coordination: move critical claim/transfer logic to the authoritative service (backend). Operations that modify ownership (delete workspace, transfer window ownership) should be atomic and return an explicit result the client can act on (e.g., replacementId or empty). The client should only perform follow-up actions after receiving that result.
Example (pseudo): // server: atomically choose replacement or clear owner and return id or empty string func DeleteWorkspace(id) -> string { if findReplacementForWindow(ownerWindow) { claimReplacement(replacementId, ownerWindow) return replacementId } cleanupWindowOwner(ownerWindow) return “” }
// client: act only on server response const replacement = await WorkspaceService.DeleteWorkspace(workspaceId) if (replacement) { await switchWorkspace(replacement) } else { window.destroy() }
If some coordination must remain client-side, use explicit coordination primitives not blind delays: prefer promises/events/component-ready hooks over setTimeout. Only use timeouts as a fallback when no readiness signal exists.
Example (UI focus): // prefer event-driven readiness await sessionView.ready() inputModel.giveFocus()
// fallback only if necessary setTimeout(() => inputModel.giveFocus(), 50)
For out-of-order or eventual-consistency events (e.g., websocket update before add), implement bounded retries with short delay/backoff and a clear failure path. Log retries and abort after N attempts to avoid infinite loops.
Example (retry for missing line):
async function ensureLineAndApply(lineId, update) {
for (let attempt=0; attempt<5; attempt++) {
if (lines[lineId]) { lines[lineId].apply(update); return }
await sleep(100 * (attempt+1)) // small backoff
}
console.warn(Failed to find line ${lineId} after retries)
}
General rules: use compare-and-swap or explicit claim APIs when possible; bound retries and timeouts; make failure modes observable (logs/metrics); write tests for race scenarios.
Motivation: these practices prevent races between concurrent actors, make system behavior deterministic, and move complex invariants into the authoritative layer where they can be enforced reliably. References: discussions on workspace deletion/claim races (0), UI focus timing (1), and websocket update ordering with retry (2).
Motivation: High-frequency events like mousemove are “chatty” and can cause excessive CPU usage and layout thrashing. Prefer lower-rate pointer events (mouseenter/mouseleave) or throttled handlers attached to specific elements, and minimize repeated DOM writes by toggling classes. Always attach and remove listeners in lifecycle hooks and guard against null refs to avoid leaks.
How to apply:
Example (pattern adapted from the discussion):
// setup const autoHideTabBar = settings?.[“window:autohidetabbar”] ?? false;
useEffect(() => { const tabBar = tabbarWrapperRef.current; if (!tabBar) return;
if (!autoHideTabBar) { tabBar.style.top = ‘0px’; return; }
const tabBarHeight = tabBar.clientHeight + 1;
tabBar.style.top = -${tabBarHeight - 10}px;
const onEnter = () => { // show via class toggle to avoid many inline writes tabBar.classList.add(‘tab-bar-wrapper-auto-hide-visible’); tabBar.style.top = ‘0px’; tabBar.addEventListener(‘mouseleave’, onLeave); };
const onLeave = () => {
tabBar.classList.remove(‘tab-bar-wrapper-auto-hide-visible’);
tabBar.style.top = -${tabBarHeight - 10}px;
tabBar.removeEventListener(‘mouseleave’, onLeave);
};
// attach to the hotspot element (not document) to avoid global mouse tracking tabbarWrapperRef.current.addEventListener(‘mouseenter’, onEnter); return () => { tabbarWrapperRef.current?.removeEventListener(‘mouseenter’, onEnter); tabbarWrapperRef.current?.removeEventListener(‘mouseleave’, onLeave); }; }, [autoHideTabBar]);
Notes:
Choose names that clearly express intent and behavior while avoiding ambiguity. Identifiers should communicate their purpose to other developers without requiring them to read implementation details.
When naming functions, prefer specific, action-oriented names over vague descriptions:
// Avoid: Not clear what "update" means in this context
fn update_task_selection_pinned_state(&mut self) -> Result<(), Error> {
self.preferences.set_active_task(None)?;
Ok(())
}
// Better: Clearly communicates the function's purpose
fn clear_pinned_task(&mut self) -> Result<(), Error> {
self.preferences.set_active_task(None)?;
Ok(())
}
Consider context when choosing names. If changing visibility (e.g., private to public), ensure the name makes sense in its new context:
// Private function with implementation-specific name
fn config_init(...) { ... }
// Better name when made public
pub fn create_config(...) { ... }
For enum variants and type names, choose terms that accurately reflect their purpose:
PackagePresenceReason instead of PackageChangeReason when describing why a package is includeddirect_dependencies() over immediate_dependencies() to clearly relate to other dependency typesLogicalProperty over the generic AdditionalPropertyGlobalFileChanged when NonPackageFileChanged is more preciseWhen multiple related types exist, names should help clarify their relationships and distinctions.
Applications that may need elevated privileges should explicitly warn against running the entire application with sudo. Instead, implement and document proper privilege escalation mechanisms (like polkit on Linux) for specific tasks requiring higher permissions.
When your application includes functionality that might tempt users to run it with sudo, provide clear warnings about the security and data integrity risks. Include these warnings in both documentation and relevant UI/CLI interactions.
Example:
if [[ $EUID -eq 0 ]]; then
echo "WARNING: Do NOT run this application directly with sudo."
echo "Doing so may compromise security and make application data unusable."
echo "See https://example.com/docs/security for proper privilege management."
exit 1
fi
# For specific elevated tasks, use a dedicated privilege management solution:
setup_elevated_access() {
if ! command -v pkexec >/dev/null 2>&1; then
echo "Note: 'pkexec' not detected. You won't be able to edit system files."
echo "See https://example.com/docs/privileges for more information."
fi
}
This approach isolates privileged operations to specific functions rather than running the entire application with elevated privileges, reducing the security attack surface and preventing potential data corruption.
Centralize repeated UI logic and prefer modern, consistent JS style. When you see duplicated logic, ad-hoc class strings, local copies of global state, or repeated boolean checks, extract them into small, well-named helpers (or model/computed methods) and apply consistent ES/React idioms.
Why: centralization improves readability, reduces bugs from divergence, and makes code easier to test and reuse. Using modern patterns (const, for-of, classname helpers) keeps code concise and consistent.
Actionable checklist:
Use a class-name helper (cn/clsx) to compose classes and avoid manual string concatenation:
// from discussion
// bad: className={tab-bar-wrapper${autoHideTabsBar ? '-auto-hide' : ''}}
// better:
className={cn(‘tab-bar-wrapper’, { ‘tab-bar-wrapper-auto-hide’: autoHideTabsBar })}
// and avoid unnecessary fallbacks:
className={cn(‘wave-dropdown’, className)}
Extract repeated UI/focus/keybinding logic into model methods or computed helpers so callers just ask the model for intent: // suggested pattern // inputModel.ts isAuxViewFocused(auxView: InputAuxViewType) { return GlobalModel.inputModel.hasFocus() || (GlobalModel.getActiveScreen().getFocusType() === ‘input’ && GlobalModel.activeMainView.get() === ‘session’ && GlobalModel.inputModel.getActiveAuxView() === auxView); }
// consumer const isHistoryFocused = GlobalModel.inputModel.isAuxViewFocused(InputAuxView_History);
const tab = ..., const elem = this.iconRef.current).for (const item of array) or array helpers over C-style loops.Don’t merge arrays when handling logic differs. Either iterate separately or normalize behavior first; merging is fine only when the processing is identical.
Examples from discussions:
|| '')for (const tab of this.options) and const instead of let and C-style loopsApply this rule in reviews: if you see repeated logic, ad-hoc string building, or duplicated state, request extraction to a helper or model and enforce const/for-of/cn usage for consistency.
Confirm that configuration artifacts (docs, config files, and ignore lists) match actual runtime behavior and preserve developer workflows.
Why: Incorrect docs or overly broad ignore rules cause confusion and break common development scenarios (hot UI changes, devcontainer editor settings, in-container git commits).
How to apply:
Docs: Verify whether a setting requires an app restart by checking the implementation (frontend vs backend) before documenting. Prefer precise, actionable descriptions. Example correction: | window:autohidetabbar | bool | show and hide the tab bar automatically when the mouse moves near the top of the window
Ignore files: Don’t broadly exclude files that are needed for developer tooling inside devcontainers (e.g., .vscode, .git, .github). If you must ignore something for image size or build reasons, use targeted patterns or explicit negations and document the reason. Examples:
!.vscode !.git
node_modules
Checklist before committing changes to configs:
Adopting this rule reduces surprises for developers and ensures configuration changes are both accurate and safe for everyday workflows.
Always check for null/undefined before accessing values or rendering UI instead of relying on non‑null assertions or unconditional usage. Prefer optional chaining and explicit guards in logic and conditional rendering in JSX.
Why: Non-null assertions (!) and unconditional rendering can cause runtime exceptions when data is absent. Explicit checks make intent clear and avoid crashes.
How to apply:
! assertions with optional chaining and guards:
Notes:
! only when you can guarantee the value (and document why). When in doubt, guard.Always propagate errors with proper context and recovery strategy. Use try-catch blocks for both synchronous and asynchronous operations, ensure error information is preserved, and provide meaningful error messages.
Key practices:
Example:
// Instead of:
if (fs.existsSync(srcFile)) {
const stats = fs.statSync(srcFile)
}
// Do:
try {
const stats = fs.statSync(srcFile)
} catch (e) {
if (e.code === 'ENOENT') {
// Handle missing file case
}
// Preserve context and rethrow
throw new Error(`Failed to read ${srcFile}: ${e.message}`, { cause: e })
}
// For async handlers:
async function middleware(req, res, next) {
try {
await processRequest(req)
} catch (e) {
// Add context and pass to error handler
e.url = req.url
e.frame = generateCodeFrame(e.pos)
return next(e)
}
}
When naming platform identifiers, choose one naming convention and use it consistently throughout the codebase. Prefer established ecosystem standards when available, such as Node.js process.platform values (win32, darwin, linux) over custom variations.
Avoid mixing different names for the same platform concept (e.g., windows, win, win32 all referring to Windows). This creates confusion and requires unnecessary translation logic.
Example of the problem:
# Inconsistent - multiple names for Windows platform
artifact-platform: 'windows' # in one place
build-key: 'win32' # in another place
target: 'win' # in yet another place
Example of the solution:
# Consistent - using Node.js process.platform convention
artifact-platform: 'win32' # everywhere
build-key: 'win32'
target: 'win32'
This eliminates the need for conditional transformations like inputs.artifact-platform == 'windows' && 'win32' || inputs.artifact-platform and makes the codebase more predictable and maintainable.
Names should follow established team conventions while accurately reflecting their purpose and functionality. Inconsistent naming schemes and misleading identifiers create confusion and maintenance overhead.
When naming identifiers, ensure they:
Examples:
test poetry export (violates naming scheme), use test/exportpoetry-update (misleading - doesn’t actually update), use poetry-sync (accurately reflects synchronization behavior)This applies to all identifiers including variables, functions, classes, configuration keys, labels, and hook names. Consistent and accurate naming improves code readability and reduces cognitive load for team members.
Always specify exact versions for tools and dependencies in CI/CD workflows to ensure reproducible builds and avoid issues with cached or default system versions. Use package managers and version pinning rather than relying on system-installed tools.
When possible, prefer managed binaries over system defaults. For example, use npm-managed tools via npx, and pin Python versions to specific releases rather than using generic version specifiers.
Example:
# Instead of:
- run: hugo --minify --logLevel info
python-version: ["3.6", "3.7", "3.8", "3.9", "pypy-3.7"]
# Use:
- run: npx hugo --minify --logLevel info
python-version: ["3.6", "3.7", "3.8", "3.9", "pypy-3.7-v7.3.7"]
This practice prevents build failures caused by version mismatches, ensures consistent behavior across different runner environments, and takes advantage of bug fixes in newer tool versions.
Use specific and clear language in all documentation to improve user understanding and avoid ambiguity. Favor precise terminology over vague descriptors, while balancing specificity with maintainability concerns.
Examples:
<strong> instead of <b>)<!-- Instead of this -->
<p>
This documentation describes <b>the old</b> Vite version. For the latest
version, see <a href="https://vite.dev/">the latest document</a>.
</p>
<!-- Use this -->
<p>
This documentation covers Vite 5 <strong>(old version)</strong>. For the latest
version, see <a href="https://vite.dev">https://vite.dev</a>.
</p>
Consider the maintenance implications when determining how specific to be. Sometimes very precise details (like future version numbers) might create maintenance burden that outweighs the benefit of specificity.
When implementing permission checks, understand the hierarchical nature of permissions and avoid redundant checks. Higher-level permissions typically include lower-level ones. Ensure your authorization logic accounts for permission relationships to maintain security while keeping code efficient.
Example:
// Inefficient - checks each permission separately
const hasAccess = data.user.permissions.triage ||
data.user.permissions.write ||
data.user.permissions.admin;
// Better - understands permission hierarchy
const hasAccess = ['triage', 'write', 'admin'].some(p => data.user.permissions[p]);
// Most efficient - if you know the hierarchy (write and admin include triage)
const hasAccess = data.user.permissions.triage ||
data.user.permissions.write ||
data.user.permissions.admin;
The most appropriate implementation depends on the system’s permission model and whether permission hierarchies are guaranteed to remain consistent over time.
Documentation should keep related information physically close together rather than separating it across different sections. When documenting configuration options, provide detailed explanations and defaults directly with each option definition instead of collecting them in distant sections.
Users should not have to scroll through large portions of documentation to find complete information about a single field. Each documented item should be self-contained with its description, possible values, platform restrictions, defaults, and examples all in proximity.
For example, instead of:
*level* = _"Normal"_ | _"AlwaysOnTop"_
Sets the window level (Normal, AlwaysOnTop).
Default: _"Normal"_
Provide detailed explanations:
*level* = _"Normal"_ | _"AlwaysOnTop"_
Sets the window level.
*Normal*
Standard window behavior
*AlwaysOnTop*
Window stays above other windows
Default: _"Normal"_
This approach improves documentation usability by ensuring users can find complete information about any feature without extensive navigation, making the documentation more practical and user-friendly.
When implementing environment-specific or version-dependent behavior, use feature flags or configuration variables instead of complex conditional logic. This approach makes configuration management more maintainable and easier to adjust when requirements change.
For example, instead of nested conditionals to handle OS version-specific behavior:
# Before: Complex conditional logic
if [[ "$OS_VERSION" -ge 10.13 && "$OS_VERSION" -lt 14 ]]; then
# Version-specific behavior
if [[ condition_check ]]; then
# Do something
fi
fi
# After: Using a configuration flag
# In initialization code:
if [[ "$OS_VERSION" -ge 10.13 && "$OS_VERSION" -lt 14 ]]; then
append_to_cccfg "h" # Add a feature flag
fi
# In implementation code:
if [[ "${HOMEBREW_CCCFG}" = *h* ]]; then
# Do version-specific behavior
fi
This pattern:
Centralize visual styles and prefer theme variables over hardcoded values. Motivation: duplicate hardcoded colors, repeated color classes, inconsistent sizing, and ad-hoc styles reduce maintainability and make global theme changes error-prone. How to apply it:
Colors: never hardcode component colors. Use theme variables (design tokens) declared in the global stylesheet (app.less/app.scss). Move color utility classes into the central file and reference them from components. Example central rule: /* app.less */ .icon.color-green i { color: var(–color-green); } .icon.color-default i { color: var(–color-default); }
Then in component styles, avoid duplicating color classes and instead ensure rendered icons include the shared “icon” class (e.g., add the “icon” class in renderIcon output).
Fonts: use the standardized font variable shorthand. Example: /* use the shorthand to get family, size, weight */ .markdown { font: var(–base-font); }
Sizing: follow approved size increments for UI fonts/icons (e.g., 12.5px and 15px where the typeface is optimized in 2.5px steps). Match icon font-size to other SVG icons by using the shared icon class rather than per-component overrides.
File format & maintainability: prefer SCSS for new/complex component styles to leverage nesting and variables. If converting a file, migrate to .scss and import shared variables rather than duplicating them locally.
Checklist for PRs:
Following this rule keeps styles consistent, reduces duplication, and makes global theme changes low-risk.
Configuration options should be separated between common/shared settings and platform-specific settings to avoid build failures and ensure proper cross-platform compatibility. When a configuration option is not supported on all target platforms or architectures, it must be moved from common configuration files to individual platform-specific configuration files.
This separation prevents build failures that occur when unsupported options are included in common configurations. For example, DRM/Widevine support varies by architecture - Linux aarch64 doesn’t support it while other platforms do.
Example of proper separation:
# configs/common/mozconfig - Remove platform-specific options
# ac_add_options --enable-eme=widevine # REMOVED - not supported on all platforms
# configs/linux/mozconfig - Add for supported architectures only
if test "$ARCH" != "aarch64"; then
ac_add_options --enable-eme=widevine
fi
# configs/macos/mozconfig - Add for supported platforms
ac_add_options --enable-eme=widevine
Before adding any configuration option to a common/shared configuration file, verify that it’s supported across all target platforms and architectures. If not, place it in the appropriate platform-specific configuration files with proper conditional checks where needed.
Variable names should clearly convey their purpose, type, and units to improve code readability and prevent errors. Follow these naming conventions:
Unit specification: Include units in variable names when dealing with measurements or time values. Use suffixes like Us for microseconds, Ms for milliseconds, etc.
// Bad
void renderData(CMonitor* pMonitor, float duration) {
m_dLastRenderTimes.push_back(duration / 1000.f);
}
// Good
void renderData(CMonitor* pMonitor, float durationUs) {
m_dLastRenderTimes.push_back(durationUs / 1000.f);
}
Intuitive naming: Choose names that clearly express intent and behavior. Prefer descriptive names over abbreviated ones.
// Bad
m_pConfig->addConfigValue("binds:pin_fullscreen", Hyprlang::INT{0});
// Good
m_pConfig->addConfigValue("binds:allow_pin_fullscreen", Hyprlang::INT{0});
Pointer prefixes: Use p prefix only for actual pointer variables, not for other types.
// Bad
const auto pwindowCurrentFullscreenState = PWINDOW->m_bIsFullscreen;
const auto pwindowCurrentFullscreenMode = PWINDOW->m_pWorkspace->m_efFullscreenMode;
// Good
const auto CURRENTWINDOWFSSTATE = PWINDOW->m_bIsFullscreen;
const auto CURRENTWINDOWFSMODE = PWINDOW->m_pWorkspace->m_efFullscreenMode;
Case conventions: Use camelCase for variables and function names, CAPS for constants. Avoid snake_case.
// Bad
const auto target_portion = (*PGAPSOUT + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x);
size_t space_pos = VALUE.find(' ');
// Good
const auto TARGETPORTION = (*PGAPSOUT + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x);
size_t spacePos = VALUE.find(' ');
These conventions reduce cognitive load, prevent type-related bugs, and make code self-documenting.
When implementing algorithms that involve data transformations, platform-specific behavior, or non-obvious computational choices, always include comments explaining the underlying reasoning and assumptions. This is especially critical for:
The explanation should clarify why the algorithm is necessary, what assumptions it makes about the data or environment, and any relevant technical context that future maintainers might lack.
Example:
// JVM class files use big-endian byte order, but x86/ARM systems are little-endian.
// This function converts between the two representations when reading binary data.
template<typename T>
inline static T swapByteOrder(const T& val) {
int totalBytes = sizeof(val);
T swapped = (T) 0;
for (int i = 0; i < totalBytes; ++i) {
swapped |= (val >> (8*(totalBytes-i-1)) & 0xFF) << (8*i);
}
return swapped;
}
Without such documentation, algorithmic choices appear arbitrary and create maintenance burdens for developers who lack the original context.
Choose names that clearly express their purpose and avoid patterns that can lead to confusion or bugs. Names should be self-documenting and unambiguous in their meaning.
Key principles:
IsKnown() instead of !IsUnknown() to prevent logical errorsattempt_number starting from 1 vs retry_attempt starting from 0)_src from public-facing namesASSESMBLER_WITH_C_PREPROCESSOR → ASSEMBLER_WITH_C_PREPROCESSOR_is_versioned_shared_library_extension_valid to _is_versioned_library_extension_valid for broader applicabilityExample of avoiding double negatives:
// Confusing - double negative can lead to bugs
if (!command_wait_duration_ms.IsUnknown()) {
// This was actually a bug in the original code
}
// Clear - positive logic is easier to understand
if (command_wait_duration_ms.IsKnown()) {
// Intent is immediately clear
}
Example of unambiguous field naming:
// Ambiguous - 0 could mean "first attempt" or "field not supported"
int32 retry_attempt = 8; // starts from 0
// Clear - distinguishes between first attempt vs unsupported field
int32 stream_attempt_number = 8; // starts from 1
Use debug-level logging for technical details and error information that aids developer troubleshooting, while keeping user-facing messages clean and informative. Avoid exposing verbose technical details directly to users, but ensure they are available for debugging.
Technical error details, exception information, and diagnostic data should be logged at debug level to help developers troubleshoot issues without overwhelming end users. User-facing messages should remain concise and actionable.
Example:
try:
SystemGit.clone(url, target)
except CalledProcessError as e:
logger.debug("Git command returned the following error:\n%s", e.stderr)
raise PoetryConsoleError(
f"Failed to clone {url}, check your git configuration and permissions"
" for this repository."
)
Also add debug logging for edge cases and error conditions that might not be immediately obvious:
def get_highest_priority_hash_type(hash_types: set[str]) -> str | None:
if not hash_types:
return None
for prioritised_hash_type in prioritised_hash_types:
if prioritised_hash_type in hash_types:
return prioritised_hash_type
logger.debug('None of the hash types %s is in prioritized_hash_types', hash_types)
# ... handle fallback cases
Choose efficient algorithms and data structures to avoid unnecessary computational complexity. Look for opportunities to replace expensive operations with more efficient alternatives, especially when dealing with collections and search operations.
Key optimization patterns to apply:
list.pop() with set-based approaches, use appropriate data structures for the taskiter_prefix() over full iteration when searching by prefixset() for deduplication instead of manually checking lists, use generators/iterables instead of materializing full lists when possibleExample of inefficient vs efficient approach:
# Inefficient: O(n) list.pop operation
for i, dep in enumerate(dependencies):
if dep.constraint.is_empty():
new_dependencies.append(dependencies.pop(i))
# Efficient: O(1) set-based blacklist approach
blacklist = set()
for dep in dependencies:
if dep.constraint.is_empty():
blacklist.add(dep)
break
# Later: skip blacklisted items
for dep in dependencies:
if dep not in blacklist: # O(1) lookup
process(dep)
Always consider the computational complexity of your chosen approach and whether a more efficient algorithm or data structure could achieve the same result.
When creating Web Workers for network communication, use self-referential URL patterns that are resilient to file renaming. This improves portability and reliability of your networking code.
For optimal worker initialization, consider these approaches:
new Worker(import.meta.url)new Worker(new URL(import.meta.url))new Worker(self.location.href)// Recommended approach - resilient to file renaming
const worker = new Worker(new URL(import.meta.url));
// Alternative when referencing other worker files
const worker = new Worker(new URL('./worker.js', import.meta.url));
Be aware that when using the same script for both main thread and worker (self-referential pattern), bundlers like Vite will need to bundle the script twice, potentially increasing bundle size but allowing for shared code between contexts.
Always handle boundary conditions explicitly in algorithms to prevent unexpected behavior. When implementing algorithms that involve iteration, traversal, or boundary checks, consider different approaches based on the specific requirements:
// When implementing next/previous functionality
if num_rows > 0 {
self.selected_task_index = (self.selected_task_index + 1) % num_rows;
// Instead of manual clamping which would stop at boundaries
}
// Alternative to modulo for previous index
self.selected_task_index = self.selected_task_index.checked_sub(1).unwrap_or(num_rows - 1);
// When shallow references are needed (not the whole graph)
let references = all_modules_iter([self.source].into_iter())
fn visit_stmt(&mut self, stmt: &Stmt) {
if self.abort {
return; // Skip further traversal if abort flag is set
}
stmt.visit_children_with(self);
}
// Instead of hard if/else for pattern matching
let (matches_pattern, does_not_match) = pattern.split_could_match("./");
// Handle both possibilities appropriately
Explicit boundary handling improves code correctness, readability, and helps prevent subtle bugs that appear only in edge cases.
When designing configuration systems, establish clear default values and inheritance patterns. Follow these principles:
Example:
// Bad - Hard to override defaults
config.isSPA = true;
// Good - Allows framework and user overrides
config.isSPA ??= true;
// Bad - Direct object merge loses array handling
const merged = { ...defaults, ...userConfig };
// Good - Use helper that handles arrays and nested objects
const merged = mergeWithDefaults(defaults, userConfig);
// Good - Framework providing defaults while allowing user override
export function frameworkConfig(userConfig) {
return mergeConfig({
build: {
minify: false
},
dev: {
port: 3000
}
}, userConfig);
}
This approach ensures configuration values are predictable, maintainable, and properly documented while providing flexibility for both framework authors and end users.
Replace fragile algorithmic approaches with robust, well-tested alternatives. Brittle algorithms that rely on manual parsing, string manipulation, or assumptions about data format are prone to failure and difficult to maintain.
When processing structured data, prefer established parsing techniques over ad-hoc string operations. For example, replace manual token splitting with regex patterns or proper parsers that handle edge cases gracefully.
Example of improvement:
# Brittle approach - manual string splitting
tokens = line.split(maxsplit=2)
label = tokens[0]
if tokens[1][0] != "(" or tokens[1][-1] != ")":
raise ValueError(f"{tokens[1]} in {line} not surrounded by parentheses")
config_hash = tokens[1][1:-1]
# Robust approach - regex matching
result = CQUERY_RESULT_LINE_REGEX.search(line)
Similarly, in complex systems with error propagation, design algorithms that properly store and handle errors at each layer rather than relying on fragile assumptions about error bubbling behavior. This ensures your algorithms remain reliable as the system evolves.
Always validate configuration options and provide clear feedback to users about potential issues. This includes warning about unused configuration keys, preventing redundant options, and ensuring cross-platform compatibility.
Key practices:
None and default enum values - choose one approach consistentlyallow(unused) instead of cfg attributes for configuration fields to prevent warnings on platforms where the feature isn’t availableExample implementation:
// Warn about unused keys during deserialization
for key in unused.keys() {
log::warn!(target: LOG_TARGET, "Unused config key: {}", key);
}
// Avoid redundant options - choose Option<T> OR T::Default, not both
pub struct WindowConfig {
// Good: Clear intent
pub window_level: WindowLevel, // with Default trait
// Avoid: Ambiguous between None and WindowLevel::Normal
// pub window_level: Option<WindowLevel>,
}
// Validate required combinations
if !content.hyperlinks && content.regex.is_none() {
return Err("At least one of hyperlink or regex must be specified");
}
This approach prevents configuration errors that can be difficult to debug and improves the user experience by providing immediate feedback about configuration issues.
Ensure consistent spacing across UI components by using CSS custom properties for padding/margins and applying spacing only when elements exist. This prevents visual inconsistencies between different UI states and modes.
Use CSS custom properties for consistent spacing values:
#TabsToolbar {
padding: var(--zen-toolbox-padding);
}
Apply spacing conditionally using CSS selectors to prevent unnecessary gaps:
/* Only apply margin when pinned tabs exist */
#vertical-pinned-tabs-container:has(tab:not([hidden])) {
margin-bottom: 8px;
}
This approach ensures that spacing remains consistent across different modes while preventing alignment issues when certain elements are not present.
Configuration documentation should provide concrete, platform-specific examples rather than generic placeholders, and use precise terminology to avoid confusion. Generic paths like /path/to/repository leave developers uncertain about actual implementation.
Replace generic placeholders with realistic examples that show the actual structure and format expected:
# Instead of generic:
common --registry="path/to/local/bcr/registry"
# Provide platform-specific examples:
# Windows:
common --registry="file:///C:/Users/johndoe/bazel-central-registry-main"
# Linux:
common --registry="file:////home/johndoe/bazel-central-registry-main"
Additionally, ensure configuration instructions are complete by:
This prevents confusion and reduces back-and-forth questions about implementation details, making configuration setup more straightforward for developers.
When creating error messages related to security, permissions, or access controls, always provide specific links to relevant documentation. Use query parameters, anchors, or other mechanisms to direct users to the exact section of documentation that addresses their issue, rather than linking to generic pages.
For example, instead of:
#[error("Insufficient permissions to write to remote cache. Please verify that your role has write access for Remote Cache Artifact at https://vercel.com/docs/accounts/team-members-and-roles/access-roles/team-level-roles")]
Prefer:
#[error("Insufficient permissions to write to remote cache. Please verify that your role has write access for Remote Cache Artifact at https://vercel.com/docs/accounts/team-members-and-roles/access-roles/team-level-roles?resource=Remote+Cache+Artifact")]
Specific links reduce friction when users troubleshoot security-related problems and increases the likelihood they’ll correctly address permission issues without requiring additional support.
Features that handle sensitive data such as credit card information, passwords, or personal details should never be enabled by default. These features must require explicit user opt-in to ensure users consciously consent to the handling of their sensitive information.
Enabling sensitive data features by default creates security risks because users may unknowingly have their sensitive information stored, transmitted, or processed without their explicit consent. This violates the principle of informed consent and can lead to data breaches or privacy violations.
Example of problematic code:
// BAD: Enabling credit card autofill by default for all countries
pref("extensions.formautofill.creditCards.supported", true);
pref("extensions.formautofill.creditCards.supportedCountries", 'AF,AX,AL,DZ...');
Instead, such features should be disabled by default and require user action to enable:
// GOOD: Sensitive features disabled by default
pref("extensions.formautofill.creditCards.supported", false);
// Only enable after explicit user consent through settings UI
This principle applies to any feature handling sensitive data including payment information, authentication credentials, personal identifiers, or private communications.
Ensure documentation is grammatically correct, clearly structured, and uses precise terminology. Avoid verbose or repetitive explanations, and provide specific details that help users understand exactly what will happen.
Key practices:
Example of improvement:
Before: "When set this configuration allows users to configure package distribution format policy for all or specific packages. Specifically, to disallow the use of binary distribution format for all, none or specific packages."
After: "When set, this configuration allows users to disallow the use of binary distribution format for all, none or specific packages."
This ensures documentation is accessible, accurate, and actionable for developers at all skill levels.
Remove braces around single-statement if blocks to maintain consistent code style and improve readability. This applies to all control flow statements with single statements, including if, else if, and else blocks.
The codebase follows a consistent style where braces are omitted for single-statement conditionals. This reduces visual clutter and maintains consistency across the project.
Examples:
❌ Avoid:
if (condition) {
return;
}
if (pWindow) {
pWindow->close();
}
✅ Prefer:
if (condition)
return;
if (pWindow)
pWindow->close();
Exception: Keep braces when the statement spans multiple lines or when it improves clarity in complex nested conditions.
This rule helps maintain visual consistency throughout the codebase and follows the established project conventions. Apply this consistently across all new code and when modifying existing code.
When designing APIs for systems that support multiple JavaScript runtimes, prioritize decoupling server state from user modules. This approach enables code to run consistently across different environments (Node.js, browsers, edge runtimes) without relying on runtime-specific features.
Instead of directly accessing server state from user modules:
// Anti-pattern: Tightly coupling server and user code
const vite = createServer()
const { processRoutes } = await vite.ssrLoadModule('internal:routes-processor')
processRoutes(collectRoutes()) // Server state leaks into user module
Use virtual modules to mediate between server and user code:
// Recommended: Decoupled through virtual modules
function vitePlugin() {
return {
name: 'virtual-data-provider',
resolveId(source) {
return source === 'virtual:app-data' ? '\0' + source : undefined
},
async load(id) {
if (id === '\0virtual:app-data') {
return `export const data = ${JSON.stringify(serverData)}`
}
}
}
}
// In user module:
import { data } from 'virtual:app-data'
// Process data without direct server dependency
For communication between environments, prefer structured APIs with clear transport abstractions rather than relying on shared runtime contexts. If runtime-specific features are needed, isolate them in well-defined interfaces that can be implemented differently across environments.
This pattern enables your code to run in any JavaScript runtime with minimal adaptation, making it suitable for environments like Cloudflare Workers, Deno, browsers, or Node.js servers.
When implementing server-side rendering in Next.js projects that use Vite as a bundler, ensure proper environment separation between client and server code. Create distinct module execution environments to prevent leaking server-only code to the client and to support hot module replacement (HMR) during development.
For custom SSR implementations with Next.js and Vite:
// vite.config.js
export default {
server: {
middlewareMode: true
},
environments: {
// Ensure proper Node.js environment for server components
node: {
dev: {
createEnvironment: createNodeEnvironment,
},
},
},
}
// server.js
const runner = createServerModuleRunner(server.environments.node)
// Use the runner for SSR with HMR support
const { render } = await runner.import('/src/entry-server.js')
This configuration helps maintain a clear separation between client and server environments, preventing server-side code from being exposed to the client while enabling HMR support for a smoother development experience with Next.js server components.
Ensure library-provided integration points are used so styles and portals behave correctly in host environments (e.g., shadow roots, webcomponents).
Motivation
How to apply 1) Use provider APIs for style nonces
const root = document.getElementById(‘root’) as HTMLDivElement const nonce = root.getAttribute(‘nonce’) || undefined
ReactDOM.createRoot(root).render(
<MantineProvider theme={theme} getStyleNonce={() => nonce} forceColorScheme={scheme}>
Or, if a component needs the nonce at runtime, use the hook inside the component:
function SomeComponent() { const styleNonce = useMantineStyleNonce() // use styleNonce when necessary }
2) Forward portal/overlay props when rendering inside shadow roots
const ResetControlPointsButton = ({ portalProps }) => { return ( <Tooltip label=”Reset all control points” {…portalProps}> </Tooltip> ) }
Checklist
References: 0, 1
Always validate that environment variables are properly defined and consistently named before using them in scripts or build processes. Undefined or misnamed variables can cause silent failures or unexpected behavior in builds and deployments.
Check for variable existence and provide meaningful defaults or error messages. Ensure variable names are consistent across different build environments (development, CI, packaging systems like Nix).
Example of problematic code:
# Bad: Using undefined variable
MESSAGE=$(git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1)
# Better: Use defined variable or provide default
HASH=$(git rev-parse HEAD)
MESSAGE=$(git show ${HASH:-HEAD} | head -n 5 | tail -n 1)
Consider using build system features like CMake’s add_compile_definitions instead of shell script environment variable manipulation when possible, as build systems provide better validation and error handling.
When implementing terminal protocol responses (CSI, DCS, OSC sequences), ensure proper formatting with correct terminators and maintain protocol transparency. Terminal protocols require specific response formats with appropriate terminators - CSI responses should use the same C1 mode as the request, DCS responses need proper DCS/ST framing, and OSC responses should echo the same terminator (BEL or ST) as the requesting sequence.
For example, when handling terminal state reports:
void AdaptDispatch::_ReturnDcsResponse(const std::wstring_view response) const
{
const auto dcs = _terminalInput.GetInputMode(TerminalInput::Mode::SendC1) ? L"\x90" : L"\x1BP";
const auto st = _terminalInput.GetInputMode(TerminalInput::Mode::SendC1) ? L"\x9C" : L"\x1B\\";
_api.ReturnResponse(fmt::format(FMT_COMPILE(L"{}{}{}"), dcs, response, st));
}
Additionally, maintain protocol transparency by avoiding reactions to sequences that should be handled by the terminal client. ConPTY should not react to sequences like “CSI 1 t” or “CSI 2 t” for show/hide operations, as these are the terminal’s responsibility. This prevents double-processing and maintains the expected protocol behavior between terminal and application.
Always properly close and clean up network connections to prevent memory leaks and resource exhaustion. When establishing WebSocket connections or other network resources, ensure they are explicitly closed and event listeners are removed when no longer needed. Additionally, implement resilient error handling strategies for network operations by using approaches like Promise.allSettled() instead of Promise.all() to handle partial failures gracefully.
Example:
// Bad practice - potential memory leak
async function pingServer(socketProtocol, hostAndPath) {
const socket = new WebSocket(
`${socketProtocol}://${hostAndPath}`,
'vite-ping'
)
return new Promise((resolve) => {
socket.addEventListener('open', () => resolve(true))
socket.addEventListener('error', () => resolve(false))
})
}
// Good practice - properly managed resources
async function pingServer(socketProtocol, hostAndPath) {
const socket = new WebSocket(
`${socketProtocol}://${hostAndPath}`,
'vite-ping'
)
return new Promise((resolve) => {
const onOpen = () => {
cleanup()
resolve(true)
}
const onError = () => {
cleanup()
resolve(false)
}
socket.addEventListener('open', onOpen)
socket.addEventListener('error', onError)
function cleanup() {
socket.removeEventListener('open', onOpen)
socket.removeEventListener('error', onError)
socket.close()
}
})
}
// Use Promise.allSettled for resilient multi-request handling
async function loadResources(urls) {
// Will continue even if some requests fail
const results = await Promise.allSettled(
urls.map(url => fetch(url))
)
// Process successful results, handle failures gracefully
return results.filter(r => r.status === 'fulfilled').map(r => r.value)
}
When using glob patterns for file system operations, ensure optimal performance and consistent behavior by configuring glob libraries appropriately and handling paths efficiently:
expandDirectories: false when replacing libraries like fast-glob with alternatives that have different defaultsabsolute: true when you need absolute paths in resultscwd to limit search scope and improve performance// Less efficient: may search unnecessary directories
const files = globSync(pattern, {
ignore: ['**/node_modules/**']
})
// More efficient: properly scoped search with correct options
const files = globSync(pattern, {
cwd: path.resolve(path.dirname(id), dir),
absolute: true,
expandDirectories: false,
ignore: ['**/node_modules/**']
})
dot: true) when neededRemember that glob operations are computationally expensive, so always consider the algorithmic efficiency of your approach when working with large directory trees.
Maintain consistent spacing patterns around operators, keywords, and interpolation syntax throughout the codebase. This improves readability and reduces cognitive load when scanning code.
Key guidelines:
new to distinguish them from method calls: new (x: number) => void#{$variable} or #{ $variable } but not mixed usageExample of good operator placement:
const result = someCondition
&& anotherLongCondition
|| fallbackCondition;
Example of consistent interpolation spacing:
// Consistent - no spaces
.icon-#{$size} { }
.text-#{$name} { }
// Consistent - with spaces
.icon-#{ $size } { }
.text-#{ $name } { }
This consistency helps establish clear visual patterns that make code easier to read and maintain, while reducing debates about formatting during code reviews.
Prefer ES module configuration files with TypeScript annotations over JSON formats for better developer experience and tooling support. Use .js or .mjs extensions with proper type annotations to enable IDE autocompletion and type safety.
When creating configuration files, especially shared configurations:
Use ES modules instead of JSON: Choose prettier.config.js or index.js over .prettierrc.json to support dynamic imports and better tooling integration.
Add TypeScript annotations: Include /** @type {import("prettier").Config} */ at the top of configuration files to enable IDE autocompletion and type checking.
Set proper package.json fields: Use "type": "module" and "exports": "./index.js" for modern module resolution.
Install types as devDependency: Add prettier as a devDependency to support TypeScript annotations.
Example configuration:
/** @type {import("prettier").Config} */
const config = {
trailingComma: "es5",
tabWidth: 4,
singleQuote: true,
};
export default config;
Example package.json for shared configs:
{
"name": "@username/prettier-config",
"type": "module",
"exports": "./index.js",
"devDependencies": {
"prettier": "^3.3.3"
}
}
This approach provides better IDE support, enables dynamic configuration, and follows modern JavaScript standards while maintaining compatibility with tools like vscode-prettier.
Use complete, descriptive variable names instead of abbreviations to enhance code readability and maintainability. Short abbreviations like dir, repo, and single-letter variables often obscure the purpose of the variable and make code harder to understand for new contributors.
Good:
normalise_tap_name() {
local directory="$1"
local user
local repository
user="$(tr '[:upper:]' '[:lower:]' <<<"${directory%%/*}")"
repository="$(tr '[:upper:]' '[:lower:]' <<<"${directory#*/}")"
repository="${repository#@(home|linux)brew-}"
echo "${user}/${repository}"
}
Bad:
normalise_tap_name() {
local dir="$1"
local u
local repo
u="$(tr '[:upper:]' '[:lower:]' <<<"${dir%%/*}")"
repo="$(tr '[:upper:]' '[:lower:]' <<<"${dir#*/}")"
repo="${repo#@(home|linux)brew-}"
echo "${u}/${repo}"
}
Exceptions: Standard abbreviations that are widely understood within the domain or temporary variables with extremely limited scope and obvious context.
When making configuration changes, especially those that deviate from standard practices or involve deprecation notices, always include clear explanatory comments. Temporary modifications to configuration settings should document both the reason and expected duration of the exception.
For example, instead of:
set +o pipefail
DELIMITER="END_LABELS_$(LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | head -c20)"
set -o pipefail
Prefer:
# Temporarily disable pipefail because the random string generation command may fail harmlessly
set +o pipefail
DELIMITER="END_LABELS_$(LC_ALL=C tr -dc '[:alnum:]' </dev/urandom | head -c20)"
set -o pipefail
For deprecation notices, clearly specify alternatives:
# Deprecated: this image will be retired after April 2023
# Use homebrew/ubuntu22.04 or homebrew/ubuntu24.04 instead
echo "The homebrew/ubuntu18.04 image is deprecated and will soon be retired..." > .docker-deprecate
When possible, use standardized tools for configuration tasks rather than custom solutions (e.g., uuidgen for generating unique identifiers).
Variable, method, and class names should clearly and accurately describe their purpose, content, or behavior. Misleading or vague names create confusion and make code harder to understand and maintain.
Examples of improvements:
local_repo → lockfile_repo when it specifically holds lockfile datarepo_with_packages → repo_add_default_packages to reflect what it doesget_system_python() → get_running_python() when it returns the currently executing Pythoncached → cached_wheel when specifically referring to wheel cachingmodule_name() function should not do the opposite of converting module namesWhen reviewing code, ask: “Does this name accurately tell me what this thing is or does?” If there’s any ambiguity or if the name could mislead someone reading the code, choose a more descriptive alternative.
When evolving public APIs, prioritize backward compatibility and avoid breaking changes to existing interfaces. Support both legacy and new syntax when standards evolve, and clearly document any deprecations.
Key practices:
Example from import syntax evolution:
// Support both new and legacy syntax
const importAttributesPlugins = ["importAttributes", "importAssertions"];
// Or use parser options to handle both
const keyword = property === "assertions" || node.extra?.deprecatedAssertSyntax ? "assert" : "with";
This approach ensures that existing code continues to work while allowing adoption of newer standards, reducing friction for API consumers and maintaining ecosystem stability.
Always ensure build commands in CI/CD configurations include all necessary steps for successful deployment, particularly dependency installation. Incomplete commands are a common source of deployment failures.
For platform-specific deployments (like Render), use the complete sequence of commands:
npm install && npm run build
Rather than incomplete commands:
npm run build
This ensures dependencies are installed before the build process begins, preventing failures due to missing packages in clean CI environments.
When using locks in asynchronous code, minimize the scope and duration for which locks are held, especially across .await points. Holding locks during asynchronous operations can block progress in other tasks and lead to decreased concurrency or even deadlocks.
Always follow these practices:
// Bad: Lock held during potentially long-running operation
let changed_packages_guard = changed_packages.lock().await;
if !changed_packages_guard.borrow().is_empty() {
let changed_packages = changed_packages_guard.take();
self.execute_run(changed_packages).await?; // Lock still held during execution
}
// Good: Lock released after data extraction
let some_changed_packages = {
let mut changed_packages_guard = changed_packages.lock().await;
(!changed_packages_guard.is_empty())
.then(|| std::mem::take(changed_packages_guard.deref_mut()))
};
if let Some(changed_packages) = some_changed_packages {
self.execute_run(changed_packages).await?; // Lock already released
}
This pattern is particularly crucial when dealing with I/O operations, network requests, or UI updates, as these operations may take significant time to complete. Using scope blocks to manage lock lifetimes ensures other concurrent operations can make progress while long-running tasks execute.
Separate CI configuration from code that serves other purposes. When variables or settings affect both user-facing behavior and CI pipeline behavior, extract CI-specific logic into dedicated configuration files. This prevents unintended CI pipeline changes when updating user-facing functionality and allows for better coordination between code changes and CI environment updates.
For example, instead of:
# This controls both user warnings and CI runners
HOMEBREW_MACOS_OLDEST_SUPPORTED="13"
Refactor to:
# User-facing support declaration
HOMEBREW_MACOS_OLDEST_SUPPORTED="13"
# CI configuration in a separate file (github_runner_matrix.rb)
HOMEBREW_CI_MACOS_VERSIONS = ["13", "14"]
This separation allows you to control the timing of CI environment changes independently from feature changes, ensuring proper sequencing of: code changes, release tagging, and then CI environment updates.
Always use specialized HTML escaping functions when outputting dynamic content to prevent Cross-Site Scripting (XSS) vulnerabilities. Don’t rely on general serialization methods like JSON.stringify which may not correctly escape all HTML-sensitive characters or may add unnecessary escapes.
When working with HTML attribute values:
// Incorrect: Using JSON.stringify for HTML attributes
res += ` ${key}=${JSON.stringify(attrs[key])}`
// Correct: Using dedicated HTML escaping
res += ` ${key}="${escapeHtml(attrs[key])}"`
This approach ensures all potentially dangerous characters are properly escaped before being inserted into HTML, preventing script injection attacks while avoiding unnecessary character escaping that could affect functionality or readability.
Implement appropriate error handling strategies based on the criticality of operations. For non-critical operations that could fail (like file operations and JSON parsing), use try/catch blocks to handle errors gracefully and continue execution with proper logging. For critical operations where execution cannot reasonably continue, provide clear error messages and abort.
Good example:
// When reading files that might not exist
try {
const config = readJsonSync(configPath);
// Process config
} catch (error) {
// Log the error
debug(`Error reading config: ${error.message}`);
// Continue with fallback or degraded functionality if appropriate
config = defaultConfig;
}
// For critical operations
try {
const packageJSON = readJsonSync(packageJsonPath);
if (!packageJSON) {
log.error("Critical error: Could not read package.json");
return { success: false, error: "Missing required package.json" };
}
} catch (error) {
log.error(`Failed to parse package.json: ${error.message}`);
return { success: false, error: "Invalid package.json" };
}
Be defensive with operations that might fail, but make intentional decisions about whether to continue execution based on the criticality of the error. Always provide clear error messages and sufficient context for debugging.
When evolving APIs, maintain backwards compatibility while introducing new features by following a staged deprecation approach:
Example:
// Stage 1: Add new API alongside existing
interface Config {
// Existing API
ssrLoadModule(url: string): Promise<Module>
// New API
environments: {
ssr: {
moduleGraph: ModuleGraph
loadModule(url: string): Promise<Module>
}
}
}
// Stage 2: Add deprecation warning system
interface FutureOptions {
deprecationWarnings?: boolean | {
ssrLoadModule?: boolean
}
}
// Stage 3: Feature flags for breaking changes
interface Config {
future?: {
// Opt-in to new behavior
useEnvironmentAPI?: boolean
}
}
This approach allows users to migrate at their own pace while maintaining a clear upgrade path. Document both old and new APIs until deprecation is complete, and provide migration guides that explain the benefits of new approaches.
When generating and inserting HTML or CSS as raw strings, treat it as untrusted input and avoid direct injection into the DOM. Constructing
Guidance:
Examples: // Unsafe: building a ; // avoid this unless input is fully trusted
// Safer: set CSS variables on elements (no raw HTML injection) // For each themed container element: <div data-likec4-color={name} style={{ [’–likec4-color’ as any]: color }} />
// If injection is required, sanitize and document import DOMPurify from ‘dompurify’; const safe = DOMPurify.sanitize(styles, {ALLOWED_TAGS: [‘style’], ALLOWED_ATTR: []}); return <style dangerouslySetInnerHTML={{ __html: safe }} />; // include comment why injection is necessary
Why this matters: Unescaped or unsanitized content inserted into the DOM can enable XSS or CSS injections. Using safe APIs, validation, or vetted sanitization prevents class of security vulnerabilities and makes intent explicit during code review.
Optimize CI pipelines by running tasks only on packages affected by code changes. Use the --affected flag in Turborepo commands to automatically filter tasks to packages with changes, significantly reducing CI execution time in large monorepos.
# Run build only on affected packages
turbo run build --affected
# Specify custom base branch for comparison
TURBO_SCM_BASE=development turbo run test --affected
By default, affected mode compares changes between main and HEAD. Override these defaults with environment variables TURBO_SCM_BASE and TURBO_SCM_HEAD when needed, such as when working with feature branches or alternative main branches.
Ensure your checkout has sufficient history depth; shallow clones may cause all packages to be considered changed. This approach ensures CI resources are used efficiently by focusing only on what changed, preventing unnecessary builds and tests while maintaining comprehensive validation.
Structure code to minimize complexity and improve readability through logical organization. This includes using early returns to reduce nesting levels and ordering operations in a logical sequence.
Use early returns to flatten code structure and avoid deep nesting:
# Prefer this - early return pattern
if argv[1] != "get":
eprint("Unknown command ...")
return 1
# Handle main logic here
...
# Instead of nested if-else chains
if argv[1] == "get":
# Handle main logic here
...
else:
eprint("Unknown command ...")
return 1
Additionally, organize method calls in logical order where setup operations precede execution operations:
# Setup first
self.ScratchFile('BUILD', [...])
self.ScratchFile('main.cc', [...])
# Then execute
exit_code, _, stderr = self.RunBazel([...])
This approach reduces cognitive load by keeping indentation shallow and presenting operations in their natural sequence.
For security-sensitive CI workflows, pin third-party GitHub Actions to immutable commit SHAs (not floating tags like v3/v4). This prevents supply-chain risk from upstream tag changes. Use Dependabot (or equivalent) to keep pinned SHAs updated automatically.
Example (pinned):
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0
Avoid (unpinned/mutable):
- uses: actions/checkout@4
- uses: hadolint/hadolint-action@3.1.0
When writing technical documentation, link to related concepts the first time they are mentioned, and include concrete examples to illustrate complex features or functionality.
When introducing a term or concept:
Example:
// Less helpful:
Turborepo's Environment Modes allow you to control which environment variables are available to a task at runtime.
// More helpful:
[Turborepo's Environment Modes](/repo/docs/core-concepts/environment-variables) allow you to control which environment variables are available to a task at runtime. For example:
```json
{
"envMode": "strict",
"env": ["API_KEY", "DEBUG"]
}
This approach helps readers immediately access relevant context without needing to search for it, and concrete examples make abstract concepts easier to understand and implement.
---
## Use descriptive variable names
<!-- source: prettier/prettier | topic: Naming Conventions | language: JavaScript | updated: 2024-08-16 -->
Choose variable and function names that clearly communicate their purpose, type, and context. Avoid abbreviations, overly generic terms, and names that could be confused for different types.
Key principles:
- **Communicate intent**: Use `array` instead of `xs`, `whitespaceCharacters` instead of `characters`
- **Indicate type when ambiguous**: Use `shouldCache` for booleans instead of `cache`, `clonedNode` instead of `clone` (which sounds like a function)
- **Be appropriately specific**: Use `createCachedSearchFunction` instead of the too-generic `createCachedFunction`, `isPrevNodeMarkdownlintComment` instead of `isPrevNodeSpecificComment`
- **Include context in method names**: Use `splitByContinuousWhitespace` instead of just `split`
Example improvements:
```javascript
// Before: unclear and generic
function chunk(xs, chunkSize) { ... }
const cache = new Map();
function createCachedFunction(function_) { ... }
// After: descriptive and clear
function chunk(array, size) { ... }
const shouldCache = true;
function createCachedSearchFunction(searchFunction) { ... }
This approach makes code self-documenting and reduces the cognitive load for other developers reading and maintaining the code.
When marking code as deprecated, use JSDoc standards to provide clear guidance for developers. Always use the @deprecated tag followed by when it was deprecated and what should be used instead. Additionally, use the {@link} tag to create clickable references to replacement functionality.
Example:
/**
* @deprecated as of Turborepo 2.0.0. Consider using {@link RootSchema.globalDependencies} instead.
*/
export interface SomeDeprecatedInterface {
// ...
}
This approach creates clickable references in many IDEs and documentation tools, allowing developers to quickly navigate to the recommended alternatives. Proper deprecation documentation helps with code maintenance and reduces confusion during migration to newer APIs.
Select appropriate logging levels based on the frequency and importance of the logged operation. Use trace for high-frequency operations (e.g., operations executed once per package or file) to prevent log noise at lower verbosity levels, and reserve debug for less frequent, more significant events or aggregated information.
Include relevant context in log messages to make them actionable:
// Less useful - lacks context
debug!("files to cache: {:?}", files_to_be_cached.len());
// More useful - includes task identifier
debug!("{}: files to cache: {:?}", self.task_id, files_to_be_cached.len());
// For high-frequency operations, use trace
trace!("loading package.json from {}", path);
By thoughtfully selecting logging levels and providing context, you create logs that are both informative when needed and not overwhelming during regular operation. This enables effective debugging without drowning developers in noise when using increased verbosity.
Choose names that clearly communicate purpose and meaning rather than implementation details or obscure abbreviations. Names should be easily understood by other developers and reflect what the identifier actually represents or does.
For function parameters, use names that describe the data’s role in the function rather than its source or format. For documentation and labels, prefer commonly understood terminology that developers can easily search for and recognize.
// Avoid: implementation-focused names
function getPreferredQuote(rawContent: string) { ... }
// Prefer: purpose-focused names
function getPreferredQuote(text: string) { ... }
// Avoid: obscure abbreviations
JS(ESM):
// Prefer: clear, searchable terms
JS (ES Modules):
This approach improves code readability, makes documentation more discoverable, and helps other developers quickly understand the purpose of variables, functions, and parameters.
Tests should be well-structured with clear separation of concerns, proper grouping, and appropriate cleanup mechanisms. Separate different types of tests (performance vs functional), use descriptive test blocks, and ensure proper isolation to prevent side effects between tests.
Key practices:
Example structure:
describe("doc builders", () => {
test("Invalid usage", () => {
// test invalid scenarios
});
test("Valid usage", () => {
// test valid scenarios
});
});
test("node version error", async () => {
const originalProcessVersion = process.version;
try {
Object.defineProperty(process, "version", { value: "v8.0.0" });
const result = await runPrettier("cli", ["--help"]);
// assertions
} finally {
Object.defineProperty(process, "version", {
value: originalProcessVersion
});
}
});
This approach prevents test pollution, improves maintainability, and ensures reliable test execution across different environments.
When implementing multiple network-related interfaces or classes that handle similar operations (like downloading), clearly document the purpose, scope, and differences between each interface to prevent confusion and misuse.
This is particularly important when you have specialized implementations for different protocols or use cases. For example, if you have both a general Downloader interface and a specialized HttpDownloader class, or when introducing remote download proxies like GrpcRemoteDownloader, each should have clear documentation explaining:
Example from the codebase:
public DownloadManager(
RepositoryCache repositoryCache,
Downloader downloader,
HttpDownloader httpDownloader) {
// Document why we need both Downloader and HttpDownloader:
// - Downloader: General interface, may be GrpcRemoteDownloader for remote asset API
// - HttpDownloader: Direct HTTP implementation, used by bzlmod for registry access
// - The bzlmod downloader uses downloadAndReadOneUrl() which only exists on HttpDownloader
}
This prevents developers from having to reverse-engineer the differences between interfaces and reduces the likelihood of using the wrong interface for a given use case. It also helps during code reviews to ensure the appropriate download mechanism is being used for each context.
Always measure and validate performance optimizations with concrete benchmarks before implementing them. Performance assumptions can be misleading, and minor gains may not justify added complexity or reduced correctness.
When considering performance optimizations:
Example from caching strategy evaluation:
# Benchmark showed minimal difference despite expectations
--cache-strategy=metadata x 0.30 ops/sec ±6.05% (5 runs sampled)
--cache-strategy=content x 0.30 ops/sec ±0.94% (5 runs sampled)
# Decision: Choose content strategy despite 10-20ms cost
# Reason: "For normal projects, there is no performance difference,
# and content is more convenient"
Avoid premature optimization and be prepared to prioritize correctness and usability over marginal performance gains. If benchmarks show negligible differences, choose the option that provides better developer experience or system reliability.
When implementing Angular syntax parsing, ensure robust handling of Angular-specific constructs by properly distinguishing AST node types and normalizing flexible syntax patterns.
For AST visitor keys, only include actual Node objects, not primitive values:
// Correct - empty array since name and value are strings, not nodes
angularLetDeclaration: [],
// Incorrect - includes non-node primitives
angularLetDeclaration: ["name", "value"],
For Angular control flow blocks, normalize whitespace in block names to handle flexible syntax:
// Should handle both:
@else if () {} // standard spacing
@else if () {} // flexible whitespace
// Implementation should normalize "else if" → "else if"
This ensures the parser correctly processes Angular’s flexible syntax while maintaining proper AST structure for tooling compatibility.
Maintain consistent indentation based on file type to ensure code readability and prevent unwanted whitespace changes in PRs. Use 4 spaces for C# (.cs) files and 2 spaces for configuration files (like JSON, devcontainer files).
Example for C# files:
public class Example
{
public void Method()
{
if (condition)
{
DoSomething();
}
}
}
Example for configuration files:
{
"name": "Project",
"settings": {
"editor.tabSize": 4,
"editor.insertSpaces": true
}
}
When working in different editors, ensure your editor settings reflect these standards. Configure IDE settings on a per-language basis (e.g., in VSCode settings.json) to automatically apply the correct indentation for each file type. This prevents accidental reformatting and maintains consistency throughout the codebase.
Large files and security-sensitive artifacts should be automatically generated in CI/CD pipelines rather than manually committed to version control. This reduces security risks from potentially malicious content and ensures artifacts stay current with the codebase.
For large profile files or binary artifacts, implement automated generation through CI jobs or release pipelines:
# Instead of committing large profile files directly
# Use CI to regenerate profiles automatically
def regenerate_profile():
# Run profiling in controlled CI environment
bazel run //tools:profile_generator
# Output profile as build artifact
Additionally, follow organizational policies for dependency placement. Files that could create bundling dependencies should be placed in appropriate directories (like tools/ instead of third_party/) and explicitly documented:
# Move sensitive configs to policy-compliant locations
# tools/proguard/config.proguard instead of third_party/
# Add to exclude lists to document the choice
exclude = ["tools/proguard/config.proguard"]
This approach ensures CI/CD security, maintains compliance with organizational policies, and keeps sensitive artifacts synchronized with code changes through automation.
Ensure robust parsing of API inputs and proper formatting of outputs to prevent parsing errors and unexpected behavior. API implementations must handle edge cases where command identifiers might appear within parameter values, and all output formats must properly escape special characters.
For input parsing, avoid simple substring matching that could incorrectly identify commands within parameter data. For example, a command like /notify blah blah /decorations should be parsed as the /notify command with /decorations as part of the parameter string, not as a /decorations command.
For output formatting, always escape special characters in structured formats like JSON:
// Bad - missing escaping
result += std::format(R"#("{}",)#", current);
// Good - with proper escaping
result += std::format(R"#("{}",)#", escapeJSONStrings(current));
This prevents client-side parsing failures when API responses contain quotes, newlines, or other special characters. Implement comprehensive input validation and output sanitization as fundamental requirements for all API endpoints.
When setting Rust build configurations, especially in CI/Docker environments, explicitly document optimization choices and their tradeoffs. Consider whether configurations should live in Cargo.toml, .cargo/config.toml, or as environment variables in CI scripts. For Docker builds, document RUSTFLAGS options like optimization levels, relocation models, and linking settings, along with their impact on binary size, performance, and security. Ensure consistency between Docker build commands and any custom profiles defined in project files.
# Document optimization choices and tradeoffs
ARG RUSTFLAGS="-C strip=symbols -C relocation-model=static -C target-feature=+crt-static -C opt-level=z"
# strip=symbols: Reduces binary size
# relocation-model=static: Reduces size at expense of ASLR security
# target-feature=+crt-static: Ensures fully static linking
# opt-level=z: Optimizes for size; benchmark to assess performance impact
# Ensure consistency with any custom profiles in Cargo.toml
RUN cargo build --release # Uses custom profile if defined in Cargo.toml
Use early returns and guard clauses to reduce nesting levels and improve code readability. When you have multiple conditional branches or error conditions, return early from the function rather than creating deeply nested if-else structures.
This pattern is especially beneficial when dealing with:
false or emptyExample of improvement:
// Instead of deeply nested conditions:
fn process_data(data: &str) -> Result<String, Error> {
if !data.is_empty() {
if data.len() > 10 {
if data.starts_with("valid") {
// 4 levels of indentation - hard to read
Ok(data.to_uppercase())
} else {
Err(Error::InvalidPrefix)
}
} else {
Err(Error::TooShort)
}
} else {
Err(Error::Empty)
}
}
// Use early returns for cleaner code:
fn process_data(data: &str) -> Result<String, Error> {
if data.is_empty() {
return Err(Error::Empty);
}
if data.len() <= 10 {
return Err(Error::TooShort);
}
if !data.starts_with("valid") {
return Err(Error::InvalidPrefix);
}
Ok(data.to_uppercase())
}
This approach reduces cognitive load by handling edge cases upfront and keeping the main logic at a consistent indentation level. It also makes the function’s requirements and error conditions immediately clear to readers.
Use precise file patterns and correct installation paths in CMake configuration to avoid unintended inclusions and ensure proper system integration. Overly broad patterns can consume unrelated files from subprojects, while incorrect paths can break package discovery.
Key practices:
src/*.h* instead of *.h*)GNUInstallDirs for installation pathsExample of precise pattern usage:
# Bad - too broad, includes subprojects
file(GLOB_RECURSE HEADERS_HL CONFIGURE_DEPENDS "*.h*")
# Good - scoped to source directory
file(GLOB_RECURSE HEADERS_HL CONFIGURE_DEPENDS "src/*.h*")
# Good - precise pattern with exclusions
install(DIRECTORY protocols/ DESTINATION include/hyprland/protocols
FILES_MATCHING PATTERN "*.h")
# Good - using standard CMake variables
install(TARGETS Hyprland hyprctl DESTINATION ${CMAKE_INSTALL_BINDIR})
This prevents build system confusion, ensures clean installations, and maintains compatibility across different environments and package managers.
Ensure configuration documentation is accurate, consistent, and clearly indicates optional versus required values. Use consistent terminology throughout documentation, provide accurate technical details, and make examples actionable for developers.
Key practices:
Example of good documentation structure:
*position* "None" | { x = <integer>, y = <integer> }
Window startup position
Specified in number of pixels.
If the position is _"None"_, the window manager will handle placement.
Default: _"None"_
This approach helps developers understand exactly what configuration options are available, what values are valid, and how to properly use them in their own configurations.
Require API surfaces (payloads, function contracts, and compact descriptor grammars) to be explicit, well-documented, and normalized at the boundary. This reduces client/server surprises, clarifies intent (single vs collection), and ensures deterministic parsing.
Guidelines
Names and shapes: use names that reveal type and multiplicity. Prefer pluralized fields for arrays (and document element type). Example: change a singular ambiguous field: // before if (“screenstatusindicator” in update) { /* … / } // after if (“screenstatusindicators” in update) { for (const indicator of update.screenstatusindicators) { / … */ } } Rationale: clients and servers immediately know to expect a list; use const in iteration to avoid accidental reassignment.
Method contracts and side effects: document whether higher-level calls encapsulate sub-operations and whether they early-return. If a wrapper may return early and skip sub-effects, provide an explicit API to perform the sub-effect or call that explicit API when you require it. Example: // If setActiveAuxView may return early and not call setAuxViewFocus, call setAuxViewFocus explicitly this.setActiveAuxView(appconst.InputAuxView_AIChat); this.setAuxViewFocus(true); Or, if the higher-level API guarantees the behavior, prefer the single call that documents the intent: this.inputModel.setAuxViewFocus(false); // if it calls giveFocus internally
| Use ‘:’ to separate ordered sequence, and ‘ | ’ to express alternatives for modifier groups. |
Why this matters
Apply this rule when defining REST/IPC payloads, library public methods, or compact descriptor syntaxes so client code can rely on stable, well-documented interfaces.
Motivation Keep code readable, consistent and easy to change by centralizing configuration, constants and mutable state, and by extracting repeated flows into well-scoped helpers or service types.
Rules
Move literal paths and long user-facing strings to package-level consts in the appropriate package (e.g., base or config). Don’t inline repeated strings. Example:
// in base.go
const ConfigDir = “config”
const AIUseTelemetryMsg = In order to protect against abuse, you must have telemetry turned on ...
// usage
fullPath := path.Join(scbase.GetWaveHomeDir(), ConfigDir, filePath)
Replace package-level mutable globals with concrete types that implement interfaces. This enables multiple instances, easier testing, and clearer ownership of state. Example: // instead of package globals: // var cache map[string]*CacheEntry
type BlockStoreType struct { mu sync.Mutex cache map[string]*CacheEntry // other fields }
func NewBlockStore() BlockStoreType { return &BlockStoreType{cache: map[string]CacheEntry{}} }
// implement BlockStore methods on *BlockStoreType
Remove boilerplate by extracting common flows into helpers or central services. If multiple code paths perform the same multi-step operation (e.g., copying files between remotes and writing to PTY), consolidate into a single function or route through a central component (mshell). This reduces duplicate writeStringToPty calls and branching. Example: // high-level helper func copyFileRemoteToRemote(ctx context.Context, src RemoteRef, dst RemoteRef, opts CopyOpts) error { /* unified logic */ }
// caller becomes a small orchestration wrapper err := copyFileRemoteToRemote(ctx, sourceRemoteId, destRemoteId, opts)
Prefer idiomatic, simple APIs when building payloads or encoding. For JSON request payloads, use json.Marshal to get []byte directly instead of manual bytes.Buffer + Encoder when appropriate: payload, err := json.Marshal(cloudCompletionRequestConfig) if err != nil { return err } req, _ := http.NewRequest(“POST”, url, bytes.NewReader(payload))
Application guidance
Why this matters Centralizing constants and state improves discoverability and reduces risk when changing behavior (e.g., renaming the config directory or changing a long message). Extracting repeated logic reduces bugs and makes reasoning/test coverage easier. Using idiomatic APIs keeps code concise and consistent.
References: 0,1,2,3,4
Keep all SQL and DB-specific logic in a single dbops layer and expose a small, consistent API that handles common patterns: insert/update (use REPLACE/UPSERT), delete, queries, and serialization of complex fields. Motivation: reduces duplicated SQL across packages, avoids mismatch between INSERT vs UPDATE code paths, and centralizes serialization/transaction handling for sqlite or other stores.
How to apply (practical steps):
Example (replace separate insert/update with REPLACE):
query := REPLACE INTO block_file VALUES (?, ?, ?, ?, ?, ?, ?, ?)
// tx.Exec(query, fileInfo.BlockId, fileInfo.Name, fileInfo.Opts.MaxSize, fileInfo.Opts.Circular, fileInfo.Size, fileInfo.CreatedTs, fileInfo.ModTs, metaJson)
metaJson, err := quickJson(fileInfo.Meta) if err != nil { return fmt.Errorf(“error serializing meta for %s: %w”, fileInfo.Name, err) } // then use metaJson in the REPLACE/UPSERT
Checklist for changes:
Benefit: clearer separation of concerns, fewer duplicated SQL code paths, consistent serialization, and easier maintenance and optimization of queries.
Establish a clear configuration precedence and control policy: explicit user-supplied settings take priority over automatic detection, unless a centralized policy (e.g., cloud/service-side limits or security constraints) explicitly disallows client overrides. Motivation: prevents surprising behavior while allowing deliberate overrides and enforcing safety/consistency where needed.
How to apply:
Examples:
Respect explicit kwarg, otherwise detect: if _, ok := pk.Kwargs[KwArgSudo]; ok { runPacket.IsSudo = sudoArg // explicit override } else { runPacket.IsSudo = IsSudoCommand(cmdStr) // fallback detection }
Enforce cloud defaults server-side (ignore client-specified tokens/choices): // do not trust opts.MaxTokens for cloud; set fixed values before sending cloudReq.MaxTokens = cloudDefaultMaxTokens cloudReq.MaxChoices = cloudDefaultMaxChoices
Documentation: record the precedence rules in the project config guide and call out contexts where server-side policies override client inputs. When changing behavior, log or document when a client-supplied value was ignored so callers can diagnose differences.
When writing CI/CD scripts and documentation, prefer Node.js APIs over shell commands for file operations to ensure cross-platform compatibility. Shell commands like echo "content" > file don’t work consistently across different operating systems, particularly Windows, which can cause CI/CD pipelines to fail.
Instead of using shell-specific commands, use Node.js built-in APIs that work uniformly across all platforms:
# Avoid - doesn't work on Windows
echo "npx lint-staged" > .husky/pre-commit
# Prefer - works on all platforms
node --eval "fs.writeFileSync('.husky/pre-commit','npx lint-staged\n')"
This approach ensures that setup scripts, pre-commit hooks, and other CI/CD automation work reliably regardless of the operating system where they’re executed, reducing platform-specific failures and improving the developer experience across diverse development environments.
When generating CSS from external data (JSON, user input, theme files), validate and sanitize both CSS property names and values before injecting them into style elements to prevent style-breaking input and XSS/style injection.
Motivation: Building CSS via string concatenation (e.g. --term-${key}: ${value};) can allow malicious or malformed keys/values to break the stylesheet or inject content. Use browser APIs and input validation to make this safe.
How to apply:
;, } or HTML tag delimiters, and limit length. For colors/units consider explicit parsers or allowlists (hex colors, rgb(), numbers+units).Example (adapted from the discussion):
// unsafe: --term-${key}: ${value};
// safer approach:
function isValidKey(key) {
// allow lowercase letters, numbers, and hyphens (adjust to your naming rules)
return /^[a-z0-9-]+$/.test(key);
}
function isValidValue(value) { if (typeof value !== ‘string’ || value.length > 200) return false; // disallow characters that can close or break CSS rules return !/[;{}<>]/.test(value); }
async function applyTheme(themeJson, styleEl) { for (const [key, value] of Object.entries(themeJson)) { if (!isValidKey(key) || !isValidValue(String(value))) continue; // reject invalid entries
// use CSS custom property API which avoids injecting raw CSS text
// ensure the property name is valid per your rules
styleEl.style.setProperty(`--term-${CSS.escape(key)}`, String(value)); } }
Notes:
References: [0]
The provided discussions focus on terminal emulator documentation and configuration issues, but do not contain any content related to networking (network protocols, HTTP requests, TCP/IP, DNS, websockets, data transfer, network security, or connection management).
The discussions cover platform-specific API behavior documentation, cross-platform command line handling, and documentation formatting - none of which relate to networking concepts. Therefore, no meaningful networking-related coding standard can be derived from these discussions.
The discussions would be more appropriate for categories like “Documentation Standards,” “Cross-Platform Compatibility,” or “Configuration Management” rather than “Networking.”
When code changes affect how people understand or use behavior—especially grammar directives/annotations or feature support—add documentation that explains intent and keeps docs aligned with current functionality.
Apply this in two ways: 1) For non-obvious inline constructs (e.g., grammar annotations), add an immediate “what/why” comment so readers don’t need to infer meaning from implementation. 2) For user-facing feature support changes (e.g., removing directive support in favor of YAML frontmatter), ensure the relevant developer/user documentation is updated (or explicitly tracked via a follow-up PR) so there’s no mismatch between code and guidance.
Example (grammar annotation):
terminal SANKEY_LINK_VALUE returns number: /"(0|[1-9][0-9]*)(\.[0-9]+)?"|.../;
/**
* @greedy
* This token should be matched late so it doesn’t preempt other token rules.
*/
@greedy
Make identifiers convey intent: include meaningful domain fields in types and choose function names that reflect user-facing semantics (not internal storage order). When internal representation differs from user expectations (for example newest items appended to the end, but UI cycles newest-first), rename functions to express the user direction and add a brief inline comment explaining the storage-order invariant.
Why: Names and exposed type fields are primary documentation for future readers. Including key identifiers (e.g., command, info) in interfaces and using semantic method names reduces confusion and prevents subtle bugs or tech debt.
How to apply (practical rules):
Benefits: clearer types for consumers, fewer accidental misuse and less cognitive load when reasoning about ordering and behavior, reduced tech debt because intent is explicitly encoded in names and small comments.
When using GitHub Actions workflow commands for annotations, always include double colons in the syntax (::command::). Proper formatting ensures warnings and errors are correctly displayed in the GitHub Actions UI and processed by workflow runners.
Example:
# Correct
puts "::warning::#{message_full}" if ENV["GITHUB_ACTIONS"]
puts "::error::#{message_full}" if ENV["GITHUB_ACTIONS"]
# Incorrect
puts "::warning #{message_full}" if ENV["GITHUB_ACTIONS"]
puts "::error #{message_full}" if ENV["GITHUB_ACTIONS"]
Missing the second set of colons will prevent GitHub Actions from properly parsing these annotations, resulting in warnings and errors not being prominently displayed in the workflow run interface. This makes CI/CD issues harder to identify and debug.
API functions should use specific types and enums to clearly communicate valid parameter values rather than accepting arbitrary generic types that suggest any value is acceptable.
When designing function signatures, avoid generic types like &[u8], primitive types, or overly broad parameters when the function only accepts a limited set of valid inputs. Instead, use enums, specific types from relevant libraries, or custom types that encode the constraints directly in the type system.
For example, instead of accepting arbitrary parameters that appear to allow any value:
// Poor API design - suggests any parameters are valid
fn should_build_esc_key_sequence(
key: &KeyEvent,
text: &str,
mode: TermMode,
mods: ModifiersState,
) -> bool {
// Implementation suggests only specific combinations are valid
}
Use types that make the valid parameter space explicit:
// Better API design - constraints are clear from types
enum KeySequenceMode {
ReportAllKeys,
DisambiguateEscCodes,
Standard,
}
fn should_build_esc_key_sequence(
key: &KeyEvent,
mode: KeySequenceMode,
) -> bool {
// Valid inputs are now clear from the signature
}
Similarly, prefer specific types from APIs over generic alternatives. Use LPDWORD from Windows APIs instead of *mut u32 when available, or the actual type names rather than generic byte arrays when the function expects specific message formats.
This approach prevents incorrect usage, makes the API self-documenting, and catches invalid parameters at compile time rather than runtime.
Design APIs to provide consistent behavior and user experience across different runtime environments and module systems. Abstract platform-specific differences behind a uniform interface so users don’t need to handle environment-specific logic.
When designing APIs that run on multiple platforms (Node.js, Deno, browsers), ensure that:
process.unref() in Node vs Deno) are handled internallyFor example, instead of requiring users to call different cleanup methods per platform:
// Bad: Platform-specific API
if (isDeno) {
await esbuild.stop(); // Required in Deno
} else {
// Node handles cleanup automatically
}
// Good: Consistent API
await esbuild.stop(); // Works the same everywhere, with internal platform handling
This approach reduces cognitive load for API consumers and prevents environment-specific bugs in user code.
Documentation language should be precise, unambiguous, and clearly scoped to prevent misinterpretation while maintaining readability. Avoid open-ended terms that could be misunderstood or exploited, and use established terminology when dealing with legal, technical, or domain-specific concepts.
When writing documentation:
Example from legal documentation:
// Ambiguous - could be misinterpreted
"license does not hinder the ability of one to contribute to, or view the source code"
// Precise - clearly scoped
"license does not hinder the ability of any non-commercial entity to contribute to, redistribute or view the source code of the project"
This approach ensures documentation serves its intended purpose without creating loopholes or confusion for readers.
Configuration files, hooks, and settings should include clear, accurate descriptions that explain their purpose and behavior. Descriptions should match the actual functionality and help developers understand what the configuration does and why it exists.
This prevents confusion when developers encounter unfamiliar configurations and reduces the cognitive load of understanding complex setups. Descriptions should be specific enough to distinguish between similar configurations and avoid misleading developers about the actual behavior.
Example of good configuration documentation:
- id: poetry-lock-check
name: poetry-lock-check
description: check that poetry lock file is consistent with pyproject.toml
# Cron schedule with clear explanation
on:
schedule:
- cron: '0 * * * *' # Run every hour at minute 0
Avoid vague descriptions that don’t match the actual behavior, such as describing a hook as “synchronize dependencies” when it actually runs poetry install --sync by default, which may not be what users expect from a basic “install” operation.
When adding a new rendering demo or introducing a new configuration/YAML option, always update the relevant Cypress integration/screenshot tests so the feature is exercised and captured automatically.
How to apply:
it(...) case (or extend an existing one) that uses a snapshot helper to render the diagram source plus the exact config/front-matter that the demo uses.nodeSpacing/rankSpacing, or new YAML config fields like themeVariables).Example pattern (Cypress + snapshot):
it('Should render subgraphs with different nodeSpacing', () => {
imgSnapshotTest(`---
title: Subgraph nodeSpacing and rankSpacing example
---
flowchart LR
X --> Y
subgraph X
direction LR
A
C
end
subgraph Y
direction LR
B
D
end
`, {
flowchart: { nodeSpacing: 1, rankSpacing: 1 },
});
});
// And for new YAML config options:
imgSnapshotTest(`---
config:
theme: base
themeVariables:
lineColor: yellow
---
flowchart LR
subgraph red
A --> B
end
`, {});
This keeps automated visual/regression coverage aligned with every user-visible change and every supported config surface.
When making HTTP requests, use standard library enums for status codes, set appropriate timeouts, and handle redirects efficiently. Avoid raw status code numbers in favor of HTTPStatus enums for better readability and maintainability. Always configure timeouts to prevent indefinite hanging, preferably making them configurable via environment variables with sensible defaults. For upload operations, consider using HEAD requests to check for redirects before expensive POST operations to avoid retransmitting large payloads.
Example:
from http import HTTPStatus
import os
# Use HTTPStatus enums instead of raw codes
if resp.status_code in (HTTPStatus.MOVED_PERMANENTLY, HTTPStatus.PERMANENT_REDIRECT):
# handle redirect
# Configure timeouts with environment variable support
timeout = int(os.getenv('POETRY_REQUEST_TIMEOUT', 60))
response = session.get(url, timeout=timeout)
# Check for redirects before expensive operations
resp = session.head(url)
if resp.status_code == HTTPStatus.MOVED_PERMANENTLY:
url = resp.headers['Location']
Identify expensive operations that may be called multiple times and implement appropriate caching mechanisms to avoid redundant computation. Use @cached_property for class properties that involve expensive calculations, store expensive method calls in local variables when used repeatedly in loops, and consider memoization for frequently accessed data that doesn’t change during execution.
Examples of expensive operations to cache:
# Instead of recalculating expensive properties in loops:
for item in items:
if self.option("top-level") and not any(
locked.is_same_package_as(r) for r in root.all_requires
):
# expensive calls repeated for each item
# Store expensive calculations outside the loop:
is_top_level = self.option("top-level")
all_requires = root.all_requires
for item in items:
if is_top_level and not any(
locked.is_same_package_as(r) for r in all_requires
):
# cached values used efficiently
# Use @cached_property for expensive file operations:
@cached_property
def includes_system_site_packages(self) -> bool:
pyvenv_cfg = self._path / "pyvenv.cfg"
return "include-system-site-packages = true" in pyvenv_cfg.read_text()
This optimization prevents redundant work and can significantly improve performance, especially in loops or frequently called code paths.
Maintain uniform error handling patterns throughout the codebase. Avoid mixing different error handling approaches like panics, process::exit(), and proper Result returns within the same application flow.
When functions can fail, consistently use Result types and propagate errors up the call stack rather than handling them inconsistently at different levels. This makes error handling predictable and allows callers to decide how to respond to failures.
Example of inconsistent handling to avoid:
// Bad: mixing panic and proper error handling
pub fn migrate(options: MigrateOptions) {
if let Err(e) = some_operation() {
eprintln!("Error: {}", e);
process::exit(1); // Inconsistent with other subcommands
}
}
// Good: consistent Result-based error handling
pub fn migrate(options: MigrateOptions) -> Result<(), Box<dyn Error>> {
some_operation()?; // Propagate errors consistently
Ok(())
}
Instead of using panics for error conditions, return proper error types with span information when possible. This is especially important for compile-time errors and user-facing operations where graceful degradation is preferred over abrupt termination.
The goal is to make error handling predictable across the entire codebase, allowing for better testing, debugging, and user experience.
When designing APIs, avoid exposing internal structures, implementation details, or platform-specific concepts to external consumers. Instead, create clean, stable interfaces that focus on what users need to accomplish rather than how the system works internally.
This principle helps maintain API stability, reduces coupling, and makes the interface easier to understand and use. Internal details like context objects, editor structs, document IDs, or event types should be abstracted away behind purpose-built API methods.
For example, instead of exposing editor and context structs directly:
// Bad - exposes implementation details
module.register_fn("editor-cursor", Editor::cursor);
module.register_fn("cx->cursor", |cx: &mut Context| cx.editor.cursor());
// Good - provides clean, purpose-built interface
module.register_fn("active-cursor", get_active_cursor);
Similarly, avoid exposing internal IDs or enum variants that are meant for internal use:
// Bad - exposes document ID creation and internal types
module.register_fn("doc-id->usize", document_id_to_usize);
module.register_value("PromptEvent::Update", PromptEvent::Update);
// Good - use opaque types or only expose what's needed
// Document IDs should be opaque handles, Update events shouldn't be exposed to plugins
The goal is to design APIs from the perspective of “What should users be able to do?” rather than “What does our internal implementation look like?” This creates more maintainable, stable, and user-friendly interfaces.
Always use secure cryptographic algorithms and minimum key sizes—even for dummy, test, or helper keys. Avoid generating or shipping 1024-bit RSA keys (they are considered weak). Prefer modern algorithms (ed25519) when supported; otherwise use at least 2048-bit RSA. Mark any ephemeral/dummy keys clearly in code, avoid persisting them, and follow library defaults where possible.
How to apply:
Additional guidance:
Motivation: Weak keys reduce the security of authentication and can introduce vulnerabilities even in helper code. Using strong defaults prevents accidental weakening of systems and aligns code with current security best practices.
Motivation: avoid large, unnecessary memory allocations and excessive decoding or retention of full data sets. For parsing, logs, or history, operate on raw bytes or streams and read only the portion you need. For long-lived state, avoid keeping full large objects in memory—cap, page, or store lightweight references.
How to apply:
Parse bytes, not decoded strings: work with Uint8Array slices and byte indexes so you only allocate what’s needed and delay TextDecoder until you must produce text. Example (from change in discussion): let curLineBytes = new Uint8Array(this.rawData.buffer, this.parsePos, i - this.parsePos); let jsonStartIndex = curLineBytes.indexOf(“{“.charCodeAt(0)); let byteSize = curLineBytes.slice(jsonStartIndex, curLineBytes.length).length; // only decode when needed: new TextDecoder().decode(curLineBytes.slice(jsonStartIndex))
For large files (logs), do not read the entire file into memory. Use streaming APIs, read-from-end buffered seeks, or delegate to existing OS tools such as tail -n and capture output. If implementing in-process, read the file in chunks from the end until you have enough lines rather than reading the whole file.
Manage in-memory history/state: avoid unbounded retention of large generated content. Options include capping history size, storing compact metadata or references, lazy-loading full content, or persisting to disk/DB and fetching on demand.
Why this improves performance: reduces peak memory usage, lowers GC pressure, and often speeds up operations by avoiding expensive encodings and unnecessary data copies. Follow this rule when designing parsers, log readers, and history/state storage to prevent scalability bottlenecks.
Always return and propagate errors; surface them to callers and the UI, and clean up resources on error paths.
Motivation
Rules
When to log vs return
Benefits
References: discussions 0, 1, 2, 3.
Define and use named constants for special sentinel identifiers (e.g., “local”, “connected”) and add semantic methods on domain types near their definitions to encapsulate boolean checks (e.g., RemoteType.IsLocal()). Motivation: magic strings and scattered boolean logic reduce clarity and increase risk of inconsistent checks. Placing constants and small predicates next to the type that owns the concept creates a single source of truth and improves identifier semantics.
How to apply:
Replace literal sentinel strings with package-scoped constants with clear names. Put them in a file close to related resolver/constants (or the type they relate to). Example: // in resolver.go (or near R_Remote definitions) const ( SentinelLocal = “local” SentinelConnected = “connected” ) // Use SentinelLocal instead of “local” throughout code.
Add semantic helper methods on the domain type that perform common checks instead of repeating boolean expressions. Place these methods beside the type declaration (e.g., sstore.go next to RemoteType): func (r RemoteType) IsLocal() bool { // encapsulate the precise logic once return r.Local && !r.IsSudo() }
Use the constants and helpers where previously ad-hoc logic occurred. Example replacement from discussion: // before: if ids.Remote.DisplayName == “local” { … } // after: if ids.Remote.DisplayName == SentinelLocal || ids.Remote.IsLocal() { // consistent handling for local remote }
Rules summary:
Benefits: improves readability, ensures consistency, reduces bugs from divergent checks, and makes future changes (e.g., renaming sentinel values or changing local-ness rules) much simpler.
Make targeted, purposeful CSS modifications that either enhance visual presentation or fix specific functionality issues without disrupting existing styles. When adding new styles, focus on specific improvements like centering text or adjusting colors. When modifying existing styles, preserve the original intent and make minimal changes to address the specific problem.
For example, instead of changing existing padding values, adjust positioning properties to fix overlapping issues:
/* Good: Targeted addition for visual improvement */
.sponsorsSection h2 {
text-align: center;
}
/* Good: Minimal adjustment to fix functionality */
.button {
top: -5px;
right: 16px;
}
This approach maintains code stability while allowing for necessary improvements and fixes.
When updating configuration schemas, ensure each config option is fully specified and not redundantly redefined.
Apply these rules:
1) Always set type and default for new properties so downstream consumers get predictable behavior and the schema remains type-correct.
2) Use inheritance from base config definitions ($defs / allOf) and remove redundant properties that are already provided by the base schema—only override when behavior truly differs.
3) Keep default consistent with the declared type and (when you’re standardizing UX) align defaults across related diagram configs.
Example (pattern):
properties:
markdownAutoWrap:
type: boolean
default: true
BlockDiagramConfig:
title: Block Diagram Config
allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }]
description: The object containing configurations specific for block diagrams.
type: object
unevaluatedProperties: false
properties:
padding:
type: number
default: 8
# Note: don’t re-declare useMaxWidth here if BaseDiagramConfig already defines it with the desired default.
When parsing API endpoint URLs, implement rigorous input validation using precise regular expressions. This includes:
github\.com)For example, instead of:
[[ "${API_URL}" =~ https://(([^:@]+)(:([^@]+))?@)?github.com/(.*)$ ]]
Use a more precise pattern:
[[ "${API_URL}" =~ https://(([^:@/?#]+)(:([^@/?#]+))?@)?github\.com/(.*)$ ]]
For API keys or tokens, consider restricting to known valid formats:
[[ "${API_TOKEN}" =~ ^[[:alnum:]_]+$ ]]
This approach prevents security vulnerabilities and ensures consistent API authentication handling across your application.
When providing team configuration files that developers might want to customize, use .example suffixes and implement automatic copying mechanisms to avoid conflicts with personal settings.
This approach prevents team configuration files from overriding individual developer preferences while ensuring new team members get sensible defaults. The pattern works by:
.example extensions (e.g., settings.example.json).gitignoreExample implementation:
// package.json
{
"scripts": {
"postinstall": "node -e \"try{fs.existsSync('.vscode/settings.json')||fs.writeFileSync('.vscode/settings.json',fs.readFileSync('.vscode/settings.example.json'))}catch(_){}\""
}
}
This pattern is particularly valuable for IDE settings, environment configurations, and any config files that developers commonly customize. It balances team consistency with individual developer workflow preferences.
When documenting CI/CD tools and integrations, always specify exact version requirements and compatibility constraints. This prevents integration failures and ensures reproducible builds across different environments.
Include specific version numbers using comparison operators (>=, >, ==) rather than vague statements like “recent versions” or “supported versions”. When possible, provide fallback instructions or alternative configurations for older versions that teams might still be using.
Example:
**Yes**. Provided that you are using `tox` >= 4, you can use it in combination with
the PEP 517 compliant build system provided by Poetry. (With tox 3, you have to set the
[isolated build](https://tox.wiki/en/3.27.1/config.html#conf-isolated_build) option.)
This approach helps teams understand exactly what they need to install or upgrade, and provides clear migration paths when updating their CI/CD pipelines.
Configure paths and system references dynamically to ensure they work across all environments (development, testing, production). Avoid hardcoded paths or environment-specific values that will break when code is packaged or deployed.
For file paths:
// Avoid this:
const filePath = "../../../../../examples/basic/README.md";
// Use this instead:
const rootReadme = path.join(prompts.root, "README.md");
// Or with @turbo/workspaces:
const rootReadme = path.join(project.paths.root, "README.md");
For tool-specific code:
// Avoid hardcoding for specific package managers:
data = data.replace(/\bpnpm\b/g, `${selectedPackageManager} run`);
// Make it work for all package managers:
// Transform from any package manager to the selected one
This approach ensures configurations remain portable across different environments and development setups, preventing unexpected failures during deployment or when sharing code with other team members.
Keep layout constants, feature flags, and user-configurable settings in centralized configuration modules (not hardcoded in components). Motivation: makes it easy to find and change UI “magic” values (e.g., tab width, spacing) and ensures behavior can be toggled per-environment or per-user (e.g., suppressing update banners when users turn off update checks).
How to apply:
Examples:
Move tab width into magiclayout.ts: // magiclayout.ts export const TAB_WIDTH = 175;
// tabs.tsx import { TAB_WIDTH } from ‘../../config/magiclayout’;
Check a user setting before showing an update sidebar entry: // clientConfig.ts (runtime/user settings) export const clientConfig = { checkForUpdates: true, // toggled by user };
// sidebar.tsx import { clientConfig } from ‘../../config/clientConfig’; … {clientConfig.checkForUpdates && clientData?.releaseinfo?.releaseavailable && (
)}
Notes:
Always include clear comments explaining the reasoning behind CI workflow decisions, including test environment separation, version matrix choices, and build requirements. This prevents confusion about when different workflows should be used and helps maintain consistency across the team.
For test workflows, clearly distinguish between development tests (fast, no build required) and production tests (with build artifacts). For version matrices, document the purpose of each version selection:
node:
# Latest even version
- "20"
# Minimal version for development
- "16"
include:
- os: "ubuntu-latest"
# Pick a version that is fast (normally highest LTS version)
node: "18"
ENABLE_CODE_COVERAGE: true
This documentation helps developers understand which workflow to modify for different types of changes and prevents misplacement of build-dependent steps in development test workflows.
Add explanatory comments for complex logic, special cases, or non-obvious code behavior. Comments should explain the “why” behind the code and “what” specific conditions or syntax patterns are being handled.
When code involves:
Include comments that:
Example from the discussions:
// Prettier does not officially support stylus.
// But, we need to handle "stylus" here for printing a style block in Vue SFC as stylus code by external plugin.
// https://github.com/prettier/prettier/pull/12707
if (lang === "stylus") {
return inferParserByLanguage("stylus", options);
}
Or for complex conditions:
// For example, there is the following key-value pair:
// "xs-only": "only screen and (max-width: #{map-get($grid-breakpoints, "sm")-1})"
// "only screen and (max-width: #{map-get($grid-breakpoints, " is a "value-string"
// and "sm" is a "value-word"
// We should not insert any spaces and lines here.
if (isMapItemNode) {
const isPartOfValue = node.groups?.[1]?.type === "value-colon" && i > 1;
// ...
}
Avoid over-commenting simple or self-explanatory code, but err on the side of clarity for complex logic that future maintainers will need to understand.
Maintain consistent naming patterns and capitalization throughout the codebase, especially for configuration options, string values, and identifiers. This includes using consistent capitalization for similar values (e.g., “None” instead of mixing “none” and “None”), adopting uniform naming patterns for related options (e.g., using “duration” consistently instead of verbose alternatives like “fade_time_in_secs”), and ensuring clear, consistent prefixes or patterns for grouped identifiers.
For example, instead of mixing capitalization:
# Inconsistent
*line_indicator* { foreground = "none", background = "none" }
*decorations* "Full" | "None" | "Transparent"
# Consistent
*line_indicator* { foreground = "None", background = "None" }
*decorations* "Full" | "None" | "Transparent"
Similarly, prefer concise, consistent naming over verbose alternatives:
# Verbose and inconsistent
*fade_time_in_secs* <float>
# Concise and consistent with other duration options
*duration* <integer>
This approach reduces cognitive load, prevents confusion, and makes the codebase more maintainable by establishing predictable naming patterns that developers can rely on.
When introducing dependencies or features that have security implications, explicitly evaluate whether the benefits justify the potential risks. Prefer safer alternatives when available, and clearly document security considerations.
For dependencies, favor native implementations over transpiled code from memory-unsafe languages. For example, choose a “small safe rust parser” over a “massive transpilation of a C library” that could introduce security vulnerabilities.
For features that access system resources (like clipboard, filesystem, network), be explicit about potential abuse scenarios in documentation. Instead of downplaying risks with phrases like “not that necessary,” clearly state that “allowing any application to read from the clipboard can be easily abused while not providing significant benefits.”
Always consider: Does this dependency/feature introduce unnecessary attack surface? Are there safer alternatives? Have we clearly communicated the security implications to users?
Ensure proper use and documentation of unsafe code to prevent security vulnerabilities. The unsafe keyword should only be used for operations that can violate memory safety contracts, not for general thread safety or global state concerns. All unsafe functions must include comprehensive safety documentation explaining the contracts that callers must uphold.
When marking code as unsafe:
unsafe for true memory safety violations (e.g., raw pointer dereferencing, FFI calls)unsafe for thread safety issues or global state mutations that use safe Rust APIs/// # Safety commentsExample of proper unsafe documentation:
/// # Safety
///
/// The underlying sources must outlive their registration in the `Poller`.
unsafe fn register(&mut self, poller: &Arc<Poller>, event: Event, mode: PollMode) -> io::Result<()>;
Example of improper unsafe usage:
// WRONG: This just calls std::env::remove_var, which is safe
unsafe fn reset_activation_token_env() {
std::env::remove_var("DESKTOP_STARTUP_ID");
}
Thread safety and global state concerns should be addressed through proper synchronization primitives (Mutex, RwLock) rather than marking functions as unsafe.
Analyze whether optional chaining (?.) is actually needed based on the surrounding context and prior validations. Remove optional chaining when values are already confirmed to be truthy through previous checks, but add it when there’s genuine risk of null/undefined access.
Remove when redundant:
// Bad: unnecessary after null check
if (!adjacentNodes.previous || !adjacentNodes.next) {
return true;
}
const previousKind = adjacentNodes.previous?.kind; // redundant ?.
const nextKind = adjacentNodes.next?.kind; // redundant ?.
// Good: direct access after validation
if (!adjacentNodes.previous || !adjacentNodes.next) {
return true;
}
const previousKind = adjacentNodes.previous.kind;
const nextKind = adjacentNodes.next.kind;
Add when necessary:
// Bad: potential exception
return node.groups[0].value === "url";
// Good: safe access
return node.groups?.[0].value === "url";
Before using optional chaining, verify: 1) Is there a genuine possibility the value could be null/undefined? 2) Have you already validated the value exists in prior code? 3) Are you mimicking existing safe patterns in the codebase? This prevents both unnecessary defensive coding and potential runtime exceptions.
When exposing IPC event handlers through contextBridge in Electron applications, always strip the event parameter before calling renderer callbacks to prevent security vulnerabilities. The event object contains event.sender which can be exploited by malicious code in the renderer process to send arbitrary IPC messages, leading to privilege escalation.
Instead of directly passing the callback:
onWindowFocus: (callback) => ipcRenderer.on('window-focus', callback)
Strip the event parameter by wrapping the callback:
onWindowFocus: (callback) => ipcRenderer.on('window-focus', () => callback())
This security practice prevents the renderer process from accessing the event object and its potentially dangerous properties, maintaining proper isolation between the main and renderer processes.
When working with data structures, prioritize efficiency through proper memory management and compact data representation. Use appropriate conversion patterns that handle memory cleanup correctly, and leverage bit manipulation techniques for space-efficient data storage.
For data structure conversions, ensure proper memory management by clearing source data after copying:
typval_T rv = {
.vval.v_list = fr_list,
.v_type = VAR_LIST
};
Object result = vim_to_object(&rv);
tv_clear(&rv); // Clean up source after conversion
return result;
For compact data representation, use bitmasks and enums instead of multiple boolean flags:
enum {
kCapsLock = 0x02,
kNumLock = 0x10,
};
// Instead of multiple #ifdef blocks, use:
if (mods & kCapsLock) {
PUT(*dict, "CapsLock", BOOLEAN_OBJ(true));
}
This approach reduces memory overhead, improves cache locality, and makes the code more maintainable while avoiding platform-specific conditional compilation complexity.
Every public API element (classes, methods, properties, constructors) must have XML documentation comments that clearly describe its purpose and usage. This improves developer experience through IntelliSense and ensures the API is well-documented.
For implementation classes that implement interfaces:
<inheritdoc /> at the class level to inherit documentation from interfacesFor method parameters and properties:
<param> descriptions rather than <remarks> for better IntelliSense visibility<param name="paramName">Description (additional context)</param>Example:
/// <summary>
/// Creates a new repository transfer description.
/// </summary>
/// <param name="newOwner">The new owner of the repository after the transfer.</param>
/// <param name="teamId">A list of team Ids to add to the repository (only applies to Organization owned repositories).</param>
public RepositoryTransfer(string newOwner, IReadOnlyList<int> teamId)
{
Ensure.ArgumentNotNullOrEmptyString(newOwner, nameof(newOwner));
Ensure.ArgumentNotNullOrEmptyEnumerable(teamId, nameof(teamId));
NewOwner = newOwner;
TeamId = teamId;
}
Maintain consistency across similar members - if one method overload has documentation, all overloads should be documented with the same level of detail.
When working with configurations, maintain consistency by following established conventions and proper categorization. This includes using naming patterns that match related tools/frameworks and organizing configuration entries in appropriate sections based on actual capabilities.
For naming conventions, prefer established patterns from related ecosystems:
// Good: matches Webpack convention
sideEffects: false
// Avoid: creates new naming pattern
sideEffectFree: true
For configuration organization, ensure entries are categorized correctly based on actual support:
// Good: placed in appropriate section
const unsupportedPlatforms = {
'aarch64-linux-android': '@esbuild/android-arm64',
}
// Avoid: miscategorized based on assumptions
const supportedPlatforms = {
'aarch64-linux-android': '@esbuild/android-arm64', // Not actually supported
}
This approach makes configurations more intuitive for users familiar with related tools and prevents confusion about actual capabilities.
Choose appropriate module loading syntax based on your execution context and build configuration settings. Different environments have different module system capabilities that must be respected.
When tsconfig.json has module: esnext or package.json has type: module, import statements may not be automatically transformed to require calls. In contexts like sandboxed preload scripts that don’t support ESM, you must use require syntax instead:
// In sandboxed preload scripts, use require even with ESM config
const { ipcRenderer, contextBridge } = require('electron/renderer');
// For dynamic imports in ESM contexts, use import()
packageJson = await import(packageJsonPath, { assert: { type: 'json' } });
Always verify that your chosen loading mechanism is compatible with both your build configuration and the target execution environment. Sandboxed contexts, Node.js versions, and TypeScript compiler settings all influence which module syntax will work correctly.
Delete internal system properties and APIs after use to prevent application code from accessing protected functionality. This security practice ensures that internal methods cannot be called by user code, protecting system integrity and preventing potential security vulnerabilities.
When internal properties are exposed temporarily (e.g., during initialization), clean them up immediately after use:
const { appCodeLoaded } = process;
delete process.appCodeLoaded;
This pattern prevents application code from discovering and potentially misusing internal system APIs that should remain private to the framework or runtime environment.
Environment variables should be properly validated, parsed, and documented with clear override mechanisms. Always validate that environment variable names are non-empty strings before processing. When parsing environment variable values, trim whitespace and remove surrounding quotes to handle cross-platform differences, especially on Windows where quotes may be preserved. Provide meaningful override mechanisms using descriptive environment variable names rather than hardcoding values.
Example of proper environment variable handling:
function getEnv(varName, trim = false) {
la(is.unemptyString(varName), 'expected environment variable name, not', varName)
const envVar = process.env[varName]
const configVar = process.env[`npm_config_${varName}`]
let result = envVar || configVar
// Handle Windows quote preservation and whitespace
return trim ? dequote(_.trim(result)) : result
}
// Provide override mechanisms with descriptive names
if (process.env.CYPRESS_DOCKER_DEV_INSPECT_OVERRIDE) {
argv.unshift(`--inspect-brk=${process.env.CYPRESS_DOCKER_DEV_INSPECT_OVERRIDE}`)
} else {
argv.unshift('--inspect-brk=5566')
}
// Platform-specific environment setup
function getOpenModeEnv() {
if (os.platform() !== 'linux') return
// Document why this environment variable is needed
return { GTK_USE_PORTAL: '1' }
}
This approach ensures configuration is flexible, well-documented, and handles cross-platform differences gracefully while providing clear override paths for different deployment scenarios.
When naming variables, methods, or configuration options, prioritize terms that are both intuitive to users and familiar within the relevant domain. Avoid technical jargon when simpler, more natural alternatives exist, while also preferring established terminology that the target audience already knows.
For user-facing actions, choose verbs that clearly communicate the intended behavior. For example, prefer “Create” over “Spawn” for window operations, as “create” is more natural and immediately understandable to users.
For domain-specific concepts, use well-established terminology that practitioners in that field would recognize. For instance, in terminal emulators, use “inverse” rather than “opposing” when referring to swapped foreground/background colors, since “inverse text” is the standard term.
Example:
# Preferred - uses natural, domain-appropriate language
- CreateNewWindow # intuitive action verb
- inverse_colors # established terminal terminology
# Avoid - technical jargon or non-standard terms
- SpawnNewWindow # technical but less intuitive
- opposing_colors # generic but not domain-standard
This approach ensures that names are both accessible to users and technically precise within the relevant context.
When implementing or documenting network functionality, ensure proper configuration options are provided and compatibility across different environments is considered. Network requests should have configurable timeouts and work reliably across platform variations.
For timeout configuration, document default values and provide environment variables for customization:
# Default timeout is 15 seconds, similar to pip
# Use POETRY_REQUESTS_TIMEOUT to customize
export POETRY_REQUESTS_TIMEOUT=30
For cross-platform network requests, include platform-specific parameters when necessary:
# Windows PowerShell 5.1 compatibility
(Invoke-WebRequest -Uri https://example.com/script.py -UseBasicParsing).Content | python
This ensures network operations are both configurable for different use cases and compatible across the environments where users will actually run the code. Always test network functionality on the target platforms and document any platform-specific requirements or parameters needed for reliable operation.
When configuring code style tools, avoid enabling rules or settings that duplicate functionality already provided by other tools in your toolchain. This reduces configuration complexity, prevents conflicting rules, and improves maintainability.
Before adding a new linting rule or formatter setting, verify that it doesn’t overlap with existing tools:
flake8-annotations (ANN) when using mypy in strict modeflake8-quotes (Q) when using black for formattingExample from pyproject.toml:
[tool.ruff]
extend-select = [
"B", # flake8-bugbear
# "ANN", # flake8-annotations - redundant with mypy strict mode
"C4", # flake8-comprehensions
# "Q", # flake8-quotes - black handles quote formatting
]
[tool.ruff.isort]
# section-order = [...] # unnecessary, matches default order
This approach ensures your style enforcement is consistent, avoids tool conflicts, and keeps configuration files focused on meaningful customizations rather than redundant specifications.
Always verify that configuration file options and command flags are correct and properly documented. Incorrect configuration syntax can cause silent failures or unintended side effects that are difficult to debug.
Common issues include:
Before committing configuration changes:
poetry lock --no-update instead of poetry lock)Example from the discussions:
# Wrong - silently breaks functionality
[flake8]
enable-select = TC, TC1
# Correct - properly documented option
[flake8]
extend-select = TC, TC1
# Wrong - updates all dependencies unintentionally
poetry lock
# Correct - only regenerates lock without updating versions
poetry lock --no-update
Implement error handling that considers recoverability, appropriate logging levels, and prevents redundant operations. Use warnings for recoverable errors during retry attempts, and errors only for final failures. Avoid duplicate error logging when errors are already wrapped or handled elsewhere. Implement guards to prevent redundant error handler setup, and distinguish between recoverable errors (network issues, temporary failures) and non-recoverable ones (configuration errors) to avoid unnecessary retry loops.
Example of proper retry error handling:
async function importWithRetry(importFn) {
try {
return await importFn()
} catch (error) {
for (let i = 0; i < 3; i++) {
console.warn(`Retrying import attempt ${i + 1}/3: ${url?.href}`) // Warning, not error
// ... retry logic
}
console.error(`Final import failure after retries: ${url?.href}`) // Error only on final failure
throw error
}
}
Avoid duplicate logging:
// Instead of logging and throwing
errors.log(err)
throw err
// Just throw the wrapped error
throw errors.get('ERROR_WRITING_FILE', dest, error)
Add explanatory comments when code logic is unclear, implements workarounds, or has special reasoning that isn’t immediately apparent to other developers. Comments should explain the “why” behind the implementation, not just the “what”.
This includes:
Example:
// Fetch a dynamic import and re-try 3 times with a 2-second back-off
// See GitHub issue #1234 - this works around intermittent module loading failures
function retryImport(modulePath) {
// implementation here
}
onStudioTestFileChange(filePath) {
// wait for the studio test file to be written to disk, then reload the test
return this.onTestFileChange(filePath).then(() => {
// rest of implementation
})
}
The goal is to make code self-documenting and reduce the cognitive load for future maintainers who need to understand the reasoning behind implementation decisions.
Always preserve existing security constraints and validation mechanisms rather than weakening them for convenience or functionality. When modifying authentication, validation, or security-related code, ensure that the changes maintain or strengthen the security posture.
Key principles:
Example from hash validation:
# Good: Maintain strict validation
known_hashes = {f["hash"] for f in package.files if f["file"] == archive.name}
if known_hashes and archive_hash not in known_hashes:
# Still fails for security when no known hashes exist
# Bad: Weakening the constraint
if archive_hash not in known_hashes: # Passes when known_hashes is empty
When in doubt about whether a security constraint is necessary, err on the side of maintaining it unless there’s clear evidence it’s safe to remove.
Choose names that clearly reveal the purpose and behavior of variables, functions, and methods. Names should be self-documenting and follow these patterns:
is, has, or should prefixes (e.g., isInitialBuildSuccessful instead of diagnostics)loadStorybookInfo() instead of storybookInfo)before, after instead of a, b)"initializes" instead of "should initialize")Example improvements:
// Before
const diagnostics: boolean
async get storybookInfo()
function percentageDiff(a: number, b: number)
// After
const diagnosticsEnabled: boolean
async loadStorybookInfo()
function percentageDiff(before: number, after: number)
Well-named code reduces the need for comments and makes the codebase more maintainable by clearly communicating intent to other developers.
When evolving APIs, prioritize maintaining backward compatibility over enforcing strict design constraints. Teams should choose approaches that allow existing code to continue working rather than forcing breaking changes for theoretical purity.
This principle applies when:
For example, when a team discovered their API documentation required strict method chaining but developers commonly used direct calls, they chose to update the documentation to match actual usage rather than enforce the strict requirement:
// Instead of forcing this breaking change:
cy.wrap(null).should(() => { /* assertions */ })
// They allowed the existing pattern:
cy.should(() => { /* assertions */ })
Similarly, when evolving from single-item to multi-item support, design the API to handle both cases uniformly rather than creating separate modes. Make the new interface accept arrays while treating single items as arrays of one, ensuring existing code continues to work without modification.
When writing tests, prioritize semantic and accessibility-based selectors over data attributes or generic selectors. Use accessible names, roles, and text content to select elements, as these selectors validate both functionality and accessibility simultaneously.
Preferred approach:
// Good - validates both functionality and accessibility
cy.contains('button', 'Choose Editor').click()
cy.findByRole('button', { name: 'Save Settings' }).click()
// Acceptable when semantic selectors aren't sufficient
cy.get('[data-cy="choose-editor"]').click()
// Avoid - fragile and doesn't validate accessibility
cy.get('.btn-primary').click()
cy.get('button').first().click()
Key benefits:
When to use data selectors:
Ensure your tests validate meaningful behavior rather than just element presence. A test that only checks if a component renders without validating its actual functionality provides limited value and may give false confidence.
Always ensure external links in documentation are valid, secure, and point to authoritative sources. This includes:
For example, instead of:
Check out [this guide](http://personal-blog.com/outdated-page#non-existent-section) for more information.
Use:
Check out [the official documentation](https://github.com/organization/project/blob/main/docs/guide.md#relevant-section) for more information.
Broken or insecure links reduce the credibility of documentation and create frustrating experiences for users. Regular verification of links ensures documentation remains reliable and trustworthy over time.
When implementing security-related models such as permissions, carefully design the properties to prevent unauthorized modifications and maintain appropriate constraints:
// Avoid public bool Admin { get; protected set; } // Never public bool Admin { get; set; }
2. When modeling permission values, consider the tradeoff between type safety and flexibility:
- Use enums (StringEnum<PermissionLevel>) when values are strictly defined and limited
- Use strings only when necessary (e.g., for custom roles in enterprise systems)
- Document the rationale when moving from constrained types to more flexible ones
3. When expanding permission models, ensure backward compatibility while maintaining security guarantees.
Proper permission modeling reduces the risk of security vulnerabilities by preventing unintended permission modifications and providing compile-time safety where appropriate.
---
## Explain non-obvious code
<!-- source: cypress-io/cypress | topic: Documentation | language: TypeScript | updated: 2022-11-30 -->
Add explanatory comments for complex logic, workarounds, and non-obvious code patterns to help future maintainers understand the reasoning behind implementation decisions. Include links to external resources like GitHub issues, documentation, or source materials when relevant.
Key areas that need explanation:
- Complex regular expressions and their expected input/output
- Workarounds and why they're necessary (with GitHub issue links)
- Unusual approaches like postMessage usage
- Complex types copied from external libraries (with source links)
- Regression fixes (with links to the issues they address)
Example:
```typescript
// Workaround for macOS focus issues - see GitHub issue #12345
resetFocusIfMacOS () {
// Implementation here
}
// Remove file extension from filename (e.g., "Component.vue" -> "Component")
return fileName.replace(/\....?$/, '')
// Using postMessage is necessary here because we need to communicate
// across different origins in a secure context
const onPostMessage = (event) => {
// Implementation here
}
This practice ensures that complex or non-obvious code decisions are documented for future developers who need to maintain, debug, or extend the functionality.
Error messages should be informative and include the actual values that caused the problem, not just generic descriptions. Use centralized error message utilities and ensure both the message and stack trace are properly updated.
Key practices:
$errUtils.modifyErrMsg to ensure consistency between message and stack traceExample from the discussions:
// Bad - vague and unhelpful
throw new Error('cy.session optional third argument must be an object')
// Good - includes actual problematic value
throw new Error(`cy.session optional third argument must be an object, you passed: ${typeof options}`)
// Better - uses proper error utilities and centralized messages
$errUtils.throwErrByPath('sessions.invalid_options', {
args: { expectedType: 'object', actualType: typeof options, actualValue: options }
})
This approach helps developers quickly understand what went wrong and how to fix it, reducing debugging time and improving the development experience.
When testing across different versions of dependencies, proactively address version compatibility issues to prevent compilation failures and ensure proper behavior validation. Use mocking or stubbing techniques to resolve dependency conflicts, and explicitly test version-specific behaviors including error messages.
For compilation issues caused by version mismatches, consider using tools like mock-require or proxyquire to stub incompatible modules:
// React 17 test that needs to handle React 18-only dependencies
// import React from 'react'
// Use conditional imports or mocking to handle version conflicts
import { mount } from 'cypress/react17' // version-specific import
// Test version-specific behaviors explicitly
describe('legacy mount behavior', () => {
it('should provide helpful error message when using wrong version', () => {
// Test that React18 mount gives appropriate error in React17 environment
})
})
This approach prevents build failures while ensuring comprehensive testing of version-specific functionality and migration scenarios.
Functions should be focused, concise, and easy to understand. Break down large functions (>100 lines) into smaller, well-named functions that each handle a single responsibility. Remove unused parameters to reduce cognitive load and prevent confusion. Prefer functional programming patterns like .some(), .map(), and .filter() over imperative loops when they improve readability. Use proper async/await patterns instead of mixing promise styles.
Example of improvement:
// Before: Large function with unused parameter
async function processData(data: any[], _unusedFlag?: boolean) {
// 150+ lines of mixed logic
let results = []
data.forEach((item) => {
if (item.isValid && item.hasPermission && item.isActive) {
results.push(item)
}
})
// more complex logic...
}
// After: Decomposed with functional patterns
async function processData(data: any[]) {
const validItems = filterValidItems(data)
const processedItems = await processItems(validItems)
return formatResults(processedItems)
}
function filterValidItems(data: any[]) {
return data.filter(item =>
item.isValid && item.hasPermission && item.isActive
)
}
This approach makes code more testable, readable, and maintainable by reducing complexity and making each function’s purpose clear.
Ensure all methods have docstrings and complex logic includes explanatory comments to help contributors understand code intent and functionality. Missing documentation creates barriers for new contributors and makes code maintenance more difficult.
For methods, add docstrings that describe the purpose and intended usage:
def _group_by_source(self, deps: list[Dependency]) -> dict[str, list[Dependency]]:
"""Group dependencies by their source origin.
Separates direct origin dependencies from non-direct origin dependencies
to enable proper constraint merging logic.
"""
For complex logic, add comments explaining the reasoning and approach:
# Group dependencies by source to apply different merge strategies
dep_groups = self._group_by_source(deps)
# Merge non-direct dependencies first, then combine with direct ones
# This ensures direct dependencies take precedence in constraint resolution
This documentation is especially valuable after refactoring, as it helps reviewers and future maintainers understand the improved logic without having to reverse-engineer the implementation.
When implementing or extending APIs, preserve compatibility with existing standards and expected behaviors. APIs should maintain the same contracts, interfaces, and behavioral patterns as the systems they emulate or replace.
Key principles:
Example from bundler API design:
// Bad: Bundler writes files directly, breaking API contract
defer ioutil.WriteFile(path.Join(targetFolder, url), []byte(source.Contents), 0644)
// Good: Return files to caller, preserving API contract
// Contents should be stashed on parseResult/ast and returned as BundleResult entry
This approach ensures APIs remain testable, predictable, and compatible with existing toolchains and workflows.
When implementing code to handle configuration files like lockfiles or environment settings, carefully consider the trade-offs between direct serialization and template-based approaches. While direct serialization from data structures is often simpler and less error-prone, template-based generation may provide better control over formatting, whitespace sensitivity, and diffing capabilities. Document your reasoning when choosing an approach, especially when standard libraries have limitations (such as the Go YAML package’s limited whitespace control). Consider how the consuming tools will interpret the generated files and whether preservation of specific formatting is important for your use case.
Example:
// Template-based approach for better whitespace control
const pnpmLockfileTemplate = `lockfileVersion: {{ .Version }}
importers:
{{ range $key, $val := .Importers }}
{{ $key }}:
{{ displayProjectSnapshot $val }}
{{ end }}
packages:
{{ range $key, $val := .Packages }}
{{ $key }}:
{{ displayPackageSnapshot $val }}
{{ end }}{{ if (eq .Version 5.4) }}
{{ end }}`
When configuring .NET projects, always use the correct target framework elements and versions:
<TargetFramework> element when targeting a single framework:
```xml
2. Use the plural `<TargetFrameworks>` element only when targeting multiple frameworks:
```xml
<TargetFrameworks>netstandard2.0;net6.0</TargetFrameworks>
Always catch specific exception types rather than using general catch blocks. This improves error handling precision, enables targeted recovery strategies, and maintains consistency across your codebase.
When implementing error handling:
// Avoid:
try {
var httpStatusCode = await Connection.Delete(endpoint, new object(), AcceptHeaders.InvitationsApiPreview);
return httpStatusCode == HttpStatusCode.NoContent;
} catch {
return false; // Swallows ALL exceptions, including unexpected ones
}
// Preferred:
try {
var httpStatusCode = await Connection.Delete(endpoint, new object(), AcceptHeaders.InvitationsApiPreview);
return httpStatusCode == HttpStatusCode.NoContent;
} catch (NotFoundException) {
// Only handle the specific case we expect and understand
return false;
}
// When detecting specific error conditions, create custom exceptions:
if (body.Contains("secondary rate limit")) {
// Don't rely on string matching
throw new SecondaryRateLimitExceededException();
}
Catching specific exceptions ensures your error handling is predictable and that unexpected errors are properly propagated rather than silently ignored. This leads to more robust code that fails fast when encountering truly exceptional conditions.
When adding support for new platforms or architectures, thoroughly verify that networking functionality works correctly across different runtime environments and build configurations. This includes validating Go version requirements, cross-compilation toolchain compatibility, and runtime behavior differences.
Key verification steps:
Example from the discussions:
platform-linux-loong64:
@$(MAKE) --no-print-directory GOOS=linux GOARCH=loong64 NPMDIR=npm/esbuild-linux-loong64 platform-unixlike
Before adding this target, verify that Go 1.19+ is available and that any networking libraries used in the application are compatible with the loong64 architecture. Similarly, for Android ARM builds, ensure the Android SDK C compiler is properly configured for any networking code that requires CGO.
When documenting network-related features like URL handling, hyperlinks, or web protocols, prioritize user-understandable descriptions over technical implementation details. Users care about what functionality they gain, not the internal mechanics of how it works.
Instead of technical descriptions like “Removal of characters before the URL scheme now take UTF8 byte sizes into account”, use user-focused language like “Unicode characters at the beginning of URLs are now ignored”. This helps users understand the practical impact of network-related changes.
For network protocol features, focus on the capability being added rather than the protocol specifics. For example, “Escape sequence to set hyperlinks” is clearer than detailing the exact OSC sequence format in user-facing documentation.
Follow established patterns consistently throughout the codebase to improve readability and maintainability:
// Prefer: public string Title { get; private set; } ```
public ClassName() { }// Prefer: Assert.False(firstRefsPage.Any(x => secondRefsPage.Contains(x))); ```
Choose algorithms that correctly match the problem requirements and understand their computational properties and side effects. Avoid using overly general solutions (like regex) when simpler, more precise algorithms exist.
Key principles:
Match algorithm to problem domain: Use domain-specific algorithms rather than general-purpose ones when precision matters. For example, TypeScript path mapping requires prefix/suffix matching, not regex pattern matching.
Understand algorithmic side effects: Operations like p.findSymbol may have side effects (marking usage) that affect other parts of the system. Document and account for these effects.
Centralize complex algorithmic logic: Place intricate algorithms like collision resolution in dedicated, well-audited locations rather than scattering the complexity across multiple passes.
Example of incorrect algorithm selection:
// Incorrect: Using regex for simple pattern matching
if matched, err := regexp.MatchString("^"+key, path); matched && err == nil {
// This treats '*' as regex repetition, not literal asterisk
}
// Correct: Use prefix/suffix matching like TypeScript compiler
func isPatternMatch(prefix, suffix, candidate string) bool {
return len(candidate) >= len(prefix) + len(suffix) &&
strings.HasPrefix(candidate, prefix) &&
strings.HasSuffix(candidate, suffix)
}
Before implementing an algorithm, verify it handles edge cases correctly and matches the computational complexity requirements of your use case.
When processing Vue components, ensure parsing logic handles edge cases correctly and selects appropriate parsers safely. This includes proper validation of directive syntax and careful parser selection based on explicit language declarations.
Key considerations:
doSomething<T1 | T2>(param) vs (doSomething < T1) | (T2 > param))<script lang="ts"> is explicitly specifiedExample of problematic parsing:
// This should not filter out the empty first iterator
const left = `${[res.alias, res.iterator1, res.iterator2]
.filter(Boolean) // ❌ Wrong - removes meaningful empty values
.join(",")}`;
// For v-for="(,a,b) of 'abcd'" this incorrectly becomes "a,b" instead of ",a,b"
Proper validation should check for required components while preserving intentionally empty values in the syntax structure.
Ensure all testing-related identifiers, scripts, and messages use clear, descriptive names rather than abbreviations or overly specific terminology. This improves maintainability and reduces confusion for both developers and users.
For script names, prefer explicit over abbreviated versions:
// Good
"cypress:open": "ts-node ../../scripts/start.js --component-testing --project ${PWD}",
"cypress:run": "ts-node ../../scripts/start.js --component-testing --run-project ${PWD}",
// Avoid
"cy:open": "ts-node ../../scripts/start.js --component-testing --project ${PWD}",
"cy:run": "ts-node ../../scripts/start.js --component-testing --run-project ${PWD}",
For user-facing messages, use parameterized or generic terminology when possible to support multiple testing contexts:
// Good - flexible for different testing types
"text": "You can reconfigure the {testingType} testing settings for this project if you're experiencing issues with your Cypress configuration."
// Avoid - too specific
"text": "You can reconfigure the component testing settings for this project if you're experiencing issues with your Cypress configuration."
This approach makes testing tooling more discoverable and user-facing content more reusable across different testing scenarios.
Choose the most appropriate pattern for handling potentially undefined or null values. When designing types, prefer optional properties (?:) over nullable types (| null) when a value is conceptually “not yet computed” rather than explicitly null.
For runtime null handling, use modern JavaScript features like nullish coalescing and optional chaining with idiomatic truthy checks:
// Instead of nullable types with explicit initialization
class ModuleNode {
isSelfAccepting: boolean | null = null;
}
// Prefer optional types
class ModuleNode {
isSelfAccepting?: boolean;
}
// For runtime handling, use nullish coalescing
const listenOption = socket ?? { port, host: hostname };
// Use optional chaining with truthy checks
const rebase = pattern.match(/.*\/?node_modules\//)?.[0];
if (rebase) {
// Do something with rebase
}
These patterns make code more concise, readable, and align with modern JavaScript idioms while maintaining type safety.
Break down complex conditional logic, nested structures, and verbose syntax into smaller, well-named functions or more concise expressions. This improves code readability and maintainability.
Key practices:
Example of improvement:
// Instead of complex nested conditions:
if (err && err.showDiff !== false && err.expected !== undefined && _sameType(err.actual, err.expected)) {
// ...
}
// Extract into named functions:
const diffCanBeShown = (err) => err && err.showDiff !== false
const hasExpectedValue = (err) => err.expected !== undefined
const hasSameTypeValues = (err) => _sameType(err.actual, err.expected)
const showDiff = (err) => diffCanBeShown(err) && hasExpectedValue(err) && hasSameTypeValues(err)
Also prefer concise TypeScript syntax:
// Instead of: const docsMenuVariant: Ref<DocsMenuVariant> = ref('main')
const docsMenuVariant = ref<DocsMenuVariant>('main')
And use idiomatic JavaScript methods:
// Instead of: indexOf() !== -1
// Use: includes()
When implementing security policies like Content Security Policy (CSP), always include clear documentation explaining the reasoning behind each directive choice and any security trade-offs being made. This prevents confusion during code reviews and ensures team members understand the security implications.
For example, when using less secure CSP directives, document why they’re necessary:
<!--
Using 'unsafe-inline' instead of 'self' because we need to allow inline <script> tags.
Trade-off: 'self' would be more secure but throws errors for inline scripts.
This configuration fixes issue #3785 without reintroducing #19697.
-->
<meta http-equiv="Content-Security-Policy" content="script-src 'unsafe-inline'" />
This practice helps maintain security awareness across the team and provides context for future modifications to security configurations.
Identify and eliminate repeated expensive operations, particularly file system access, by implementing caching, batching, or data sharing strategies. When the same file or resource is accessed multiple times within a short timeframe, consider caching the result or restructuring the code to perform the operation once and reuse the data.
For example, instead of reading the same file multiple times for each test:
// Problematic: reads file for each test
export const getStudioDetails = async (fileDetails: FileDetails) => {
return {
studioExtended: await wasTestExtended(fileDetails).catch(() => false),
studioCreated: await wasTestCreated(fileDetails).catch(() => false),
}
}
Consider caching the file content or combining the operations:
// Better: read file once and share the data
export const getStudioDetails = async (fileDetails: FileDetails) => {
const fileContent = await readFileOnce(fileDetails);
return {
studioExtended: checkIfExtended(fileContent),
studioCreated: checkIfCreated(fileContent),
}
}
This is especially critical when operations scale with the number of tests or files, as the performance impact compounds significantly.
Use Vue 3 Composition API patterns that provide better performance, type safety, and maintainability. Prefer computed over watch + reactive assignment when deriving values from other reactive data. Use defineEmits instead of $emit in templates for type safety. Adopt modern defineProps<{}>() syntax over PropType casting for better TypeScript inference and performance. Consider watchEffect when you need watch with immediate: true.
Examples:
// ❌ Avoid watch + assignment pattern
const promptToShow = ref('')
watch(savedState, (newVal) => {
promptToShow.value = computePrompt(newVal)
})
// ✅ Use computed for derived values
const promptToShow = computed(() => {
return computePrompt(savedState.value)
})
// ❌ Avoid $emit in templates
@click="$emit('removeProject', props.gql.projectRoot)"
// ✅ Use defineEmits for type safety
const emit = defineEmits<{
(e: 'removeProject', path: string): void
}>()
@click="emit('removeProject', props.gql.projectRoot)"
// ❌ Avoid PropType casting
const props = defineProps({
gql: {
type: Object as PropType<PackagesListFragment>,
required: true
}
})
// ✅ Use generic syntax for better inference
const props = defineProps<{
gql: PackagesListFragment
}>()
// ✅ Use watchEffect for immediate watching
watchEffect(() => {
docsMenuVariant.value = props.forceOpenDocs ? 'ci1' : 'main'
})
These patterns reduce boilerplate, improve TypeScript performance in IDEs, provide better type safety, and align with Vue 3 best practices.
Establish and enforce consistent naming conventions across different contexts in your codebase. Teams should decide on specific patterns and use linting to maintain consistency rather than mixing approaches.
Key areas to standardize:
Props access: Choose either props.showBrowsers or destructured showBrowsers consistently throughout the codebase. As noted in discussions: “we should lint for one or the other” rather than mixing both approaches.
Component naming: Use PascalCase for custom Vue components (RouterLink) and kebab-case for native HTML elements and built-in Vue components (router-link). Avoid mixing casing styles within the same context.
GraphQL fragments: Adopt a consistent naming pattern like ComponentName_UniqueName for all fragments, even when there’s only one per component. This prevents naming conflicts and maintains predictability.
Example of inconsistent vs consistent patterns:
<!-- Inconsistent -->
<template>
<router-link :to="props.href"> <!-- mixing kebab-case component with props. access -->
<HeaderContent :show-browsers="showBrowsers" /> <!-- mixing destructured props -->
</router-link>
</template>
<!-- Consistent -->
<template>
<RouterLink :to="href"> <!-- PascalCase for custom components -->
<HeaderContent :show-browsers="showBrowsers" /> <!-- consistent props access -->
</RouterLink>
</template>
The goal is to eliminate decision fatigue and reduce cognitive load by having clear, lintable rules that the entire team follows consistently.
Choose names and aliases that clearly communicate their purpose and meaning rather than optimizing for brevity or perceived elegance. Avoid abbreviated aliases that obscure the actual location or purpose of code elements, and resist adding premature complexity like numerical suffixes unless multiple variants actually exist.
For example, prefer explicit paths like @packages/frontend-shared/src/gql-components over cryptic aliases like @cy/components that require developers to mentally map the alias to its actual location. Similarly, use simple names like ci until you actually need ci1 and ci2 - don’t add complexity in anticipation of future needs that may never materialize.
The goal is to make code self-documenting where a developer can understand what something is and where it comes from without needing to look up aliases or decipher naming conventions.
Write CSS that prioritizes maintainability and reduces the likelihood of conflicts or brittleness. This includes using semantic class names instead of raw HTML element selectors, and avoiding explicit z-index values when possible.
Raw HTML selectors like span:last-child button and span are more brittle and harder to understand than semantic class names. Similarly, explicit z-index values like z-index: 99999 can lead to stacking conflicts where developers “find themselves fighting with their own code on who’s on top.”
Instead, prefer:
Example of brittle pattern:
span:last-child button,
.play {
padding: 1px 10px;
}
.ui-blocker {
z-index: 99999; /* Explicit z-index can cause conflicts */
}
Better approach:
.header-action-button,
.play-button {
padding: 1px 10px;
}
.ui-blocker {
/* Rely on natural stacking order instead of explicit z-index */
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
Design GraphQL mutations to return meaningful objects rather than simple booleans, and use simple ID parameters instead of complex nested objects. This follows GraphQL best practices and enables proper client-side cache management.
Return Objects from Mutations:
Mutations should return the modified entity to enable Apollo Client’s normalized cache to update automatically. Returning just true or simple scalars requires manual cache updates.
// ❌ Avoid - returns boolean, requires manual cache updates
t.nonNull.field('addProject', {
type: 'Boolean',
async resolve(_root, args, ctx) {
await ctx.projects.addProject(args)
return true
}
})
// ✅ Prefer - returns Project object for automatic cache updates
t.nonNull.field('addProject', {
type: 'Project',
async resolve(_root, args, ctx) {
const project = await ctx.projects.addProject(args)
return project
}
})
Use Simple ID Parameters: Prefer simple ID arguments over complex nested objects to keep the API clean and leverage server-side knowledge of entity relationships.
// ❌ Avoid - complex nested object parameter
t.nonNull.field('setCurrentSpec', {
args: {
spec: nonNull(inputObjectType({ /* complex spec object */ }))
}
})
// ✅ Prefer - simple ID parameter
t.nonNull.field('setCurrentSpec', {
args: {
specId: nonNull(idArg())
}
})
This approach reduces API complexity, improves type safety, and follows GraphQL conventions for client-server communication.
Maintain consistent naming patterns across similar functionality while ensuring names accurately describe their current purpose and scope. When multiple options exist for the same feature, standardize on one clear option to avoid confusion in documentation and usage. Update variable names when their type or purpose changes, and use descriptive names that clearly indicate scope and function.
Examples:
--component instead of supporting both --component and --ct flagswritten to writtenChunkCount when changing from boolean to counter/__cypress/bundled to match existing conventionsdebugVerbose even when no non-verbose version existsThis prevents inconsistent documentation, reduces cognitive load for developers, and ensures the codebase remains predictable and maintainable.
Select log levels based on the intended audience and actionability of the message. Use debug for internal development information that helps with troubleshooting, warn or error for user-actionable issues, and avoid logging messages that add noise without providing value to the user.
Key principles:
debug logs for internal state and development informationExample:
// Good: Internal information for developers
debug('launch project')
// Good: User-actionable warning
logger.warn(stripIndent(msg))
// Avoid: Noise that users can't act on
console.warn(`Could not get the original source file from line "${line}"`)
When in doubt, prefer debug logs for internal information and reserve user-facing logs for messages that require user attention or action.
When dealing with async operations that depend on external systems (servers, backends, etc.), ensure proper synchronization to avoid race conditions. Don’t rely on client-side polling or workarounds when the root cause is improper async handling.
Key principles:
Example of proper async sequencing:
// Instead of client-side polling workarounds
async function start(openElectron) {
await initializeThings()
openElectron()
}
// Make functions async when they need to ensure completion
async function reset() {
await Cypress.backend("set:traffic:routing:reset")
}
This prevents race conditions where the UI renders before the backend is ready, or where operations proceed without confirming the previous step completed successfully.
Write specific, regression-proof test assertions that validate exact expected values rather than allowing ambiguous matches. Avoid assertions that could pass with incorrect but similar values.
Problems with weak assertions:
expect(a).eq(b) passes even if both are undefinedBetter assertion patterns:
// Instead of just comparing two potentially undefined values
expect(Cypress.currentTest.title).eq(cy.state('runnable').ctx.currentTest.title)
// Add type validation and literal value checks
expect(Cypress.currentTest.title)
.to.be.a('string')
.eq(cy.state('runnable').title)
.eq('returns current test runnable properties')
Key improvements:
.to.be.a('string') to ensure expected data typesThis approach makes tests more reliable by catching edge cases where both compared values might be incorrect in the same way, and provides clearer failure messages when assertions fail.
Always await functions that return promises to ensure proper asynchronous execution and avoid potential race conditions or unexpected behavior. When converting from promise chains to async/await, verify that all promise-returning function calls include the await keyword.
Common mistake: Calling a promise-returning function without await, which can lead to unhandled promises and timing issues.
// ❌ Incorrect - missing await
export const showDialogAndCreateSpec = async () => {
const cfg = openProject.getConfig()
const path = await showSaveDialog(cfg.integrationFolder)
if (path) {
createFile(path) // Missing await - promise not handled
}
}
// ✅ Correct - properly awaited
export const showDialogAndCreateSpec = async () => {
const cfg = openProject.getConfig()
const path = await showSaveDialog(cfg.integrationFolder)
if (path) {
await createFile(path) // Properly awaited
}
}
This is especially important when refactoring from promise chains (.then()) to async/await syntax, as it’s easy to overlook promise-returning functions that need to be awaited.
Always provide fallbacks when accessing properties or methods on values that could be undefined or null to prevent runtime errors. Use defensive programming patterns like logical OR operators, conditional checks, or nullish coalescing when available.
Examples of unsafe patterns:
// Unsafe - could throw if renderProps is undefined
const showMarkdown = computed(() => props.command.renderProps && props.command.renderProps.message)
// Unsafe - could throw if message/markdown is undefined
scaled: computed(() => (props.message || props.markdown).length > 100)
Examples of safe patterns:
// Safe - provides fallback value
const showMarkdown = computed(() => props.command.renderProps?.message ?? false)
// Or without optional chaining:
const showMarkdown = computed(() => props.command.renderProps && props.command.renderProps.message || false)
// Safe - provides empty string fallback
scaled: computed(() => (props.message || props.markdown || '').length > 100)
This prevents common runtime errors like “Cannot read property ‘x’ of undefined” and makes code more robust when dealing with optional or potentially missing data.
Always specify exact dependency versions in package.json files instead of using version ranges (^, ~) to ensure reproducible builds and prevent accidental upgrades that could introduce breaking changes.
When adding new dependencies or updating existing ones, pin to specific versions to maintain build consistency across environments. This is especially important for production applications where unexpected dependency updates could cause runtime issues.
Example:
// ❌ Avoid version ranges
"dependencies": {
"snap-shot-core": "^7.4.0",
"diff": "^4.0.1"
}
// ✅ Use exact versions
"dependencies": {
"snap-shot-core": "7.4.0",
"diff": "4.0.1"
}
Remember that configuration changes may require additional dependencies - for example, enabling "importHelpers": true in tsconfig.json requires adding tslib as an exact dependency. Always verify that configuration changes don’t introduce missing dependency requirements.
Avoid unnecessary test maintenance overhead by eliminating duplicate test coverage and implementing automated test update mechanisms. When the same functionality is already covered by equivalent tests (e.g., end-to-end tests that exercise the same code paths), remove redundant test implementations rather than maintaining multiple versions. Additionally, design test assertions and output systems to support automated updates rather than requiring manual copy-paste workflows.
For example, instead of maintaining both JavaScript and Go plugin tests when “the API calls in each JavaScript plugin are forwarded through a Go plugin,” keep only the more comprehensive end-to-end tests. Similarly, implement snapshot-style testing systems that can automatically update expected outputs rather than requiring developers to manually copy test results.
This approach reduces maintenance burden, prevents test drift between duplicate implementations, and allows developers to focus on meaningful test coverage rather than repetitive maintenance tasks.
Establish consistent patterns for API design, particularly for request/response formats and parameter structures. This improves predictability, type safety, and developer experience across the codebase.
For communication interfaces, use standardized payload structures:
{
type: 'success' | 'error',
data: any,
event: string
}
For method parameters, prefer explicit options objects over method chaining when configuration is complex:
// Preferred: explicit options
agent.log = (options) => {
if (options && options.snapshot === false) {
// handle configuration
}
}
// Instead of: method chaining
agent.snapshot(false).log()
This approach makes APIs more readable, self-documenting, and easier to extend without breaking existing functionality. Consistent patterns also enable better tooling support and type checking.
Ensure CI/CD pipeline documentation accurately reflects the complete workflow, including job dependencies, execution order, and all operations performed by each step. When documenting CI processes:
For example, when documenting a test job that runs multiple commands:
## CI Jobs
- `CI / syntax`: This is run first to check whether the PR passes `brew style` and `brew typecheck`. If this job fails, the following jobs will not run.
- `CI / test everything (macOS)`: This runs multiple tests including:
- `brew tests`
- `brew update-tests`
- `brew readall`
- `brew test-bot --only-formulae --test-default-formula`
- `brew doctor`
Complete documentation helps maintainers understand the full CI pipeline, troubleshoot failures effectively, and follow consistent processes when merging changes.
Security measures should be evaluated against realistic threat models to avoid creating a false sense of security. When implementing security controls like checksums, consider whether they actually protect against likely attack vectors.
For example, in package management systems that download from third-party sources:
# INSUFFICIENT SECURITY:
# The sha256 verification provides limited protection if the attacker can control both:
# - The download URL source
# - Version information being reported
# Better approach: Implement defense-in-depth with multiple complementary security controls
# - Digital signatures from trusted authorities
# - Reproducible builds to verify package contents
# - Monitoring for unexpected behavior or changes
Remember that sophisticated attackers target the weakest links in your security chain. If they can compromise one control (like a download URL), they can often compromise related controls (like version reporting), rendering single verification methods inadequate.
Follow consistent formatting and syntax patterns to improve code readability and maintainability. This includes using compact formatting for test blocks, proper quote usage, positive-first conditionals, and preferred syntax patterns.
Key formatting guidelines:
describe('errors', { defaultCommandTimeout: 50 }, () => {"foo" instead of 'foo\'if (state.initialBuildSucceed) { ... } else { ... }return (expression) instead of if (...) return true.catch() syntax over try/catch blocks for promise handling/* global jest */ at file top instead of inline eslint-disable-next-line no-undefThese patterns make code more readable and follow modern JavaScript conventions while reducing cognitive load for developers.
When using dynamic imports, implement timing controls and strategic naming to ensure reliable and efficient resource loading. Use minimal delays (like setTimeout with 0ms) to control initialization timing and prevent race conditions that could cause failures. Additionally, use descriptive chunk names with webpackChunkName comments to create readable, manageable bundles that improve system organization and API handling.
Example:
// Use timing control to ensure proper initialization
const importsToLoad = [() => {
return new Promise((resolve) => {
setTimeout(() => {
import(/* @vite-ignore */ specPath).then(resolve)
}, 0) // Use 0ms for next tick timing
})
}]
// Use descriptive chunk names for better organization
const eventManager = await import(/* webpackChunkName: "ctChunk-EventManager" */'./event-manager')
.then((module) => module.default)
This approach prevents resource loading failures while maintaining organized, performant code splitting that benefits both development and runtime performance.
Favor inline conditional rendering in JSX over extracting logic to variables before the return statement, as it maintains better flow control visibility and reduces cognitive overhead when reading components. Additionally, use descriptive variable names that clearly convey their purpose and state.
For conditional rendering, prefer:
return (
<div>
{state.specs.length < 1
? <NoSpec />
: <SpecList />
}
</div>
)
Over extracting to variables:
const specListContent = state.specs.length < 1
? <NoSpec />
: <SpecList />
return (
<div>
{specListContent}
</div>
)
The inline approach keeps the rendering logic visible in context, making it easier to understand what gets rendered without jumping between variable definitions. For variable naming, choose names that clearly indicate the variable’s role - for example, use isRunning instead of isLive when the variable represents whether a process is currently executing.
Extract complex inline code elements into separate functions, components, or constants to improve readability and maintainability. This includes hardcoded strings, complex event handlers, and lengthy JSX expressions.
Examples of what to extract:
// Instead of inline handler:
onClick={(e) => {
props.onClick(e, props.item)
onClick(e, props.item)
}}
// Extract to function:
function handleClick(e) {
props.onClick(e, props.item)
if (props.item.onClick) {
props.item.onClick(e, props.item)
}
}
This practice makes code more testable, reusable, and easier to understand by giving meaningful names to code blocks and reducing visual complexity in the main component logic.
Use widely accepted industry-standard names and conventions rather than descriptive but non-standard alternatives. This improves code readability and maintainability by leveraging established terminology that developers are already familiar with.
For components, prefer established UI terminology over descriptive names:
// Avoid descriptive but non-standard names
const UiBlocker = () => { /* ... */ }
// Prefer widely accepted industry terms
const Scrim = () => { /* ... */ }
For file extensions, use standard conventions consistently:
// Prefer standard extensions for new files
CollapseIcon.tsx // instead of CollapseIcon.jsx
This approach reduces cognitive load for developers who can immediately understand the purpose and behavior based on familiar naming patterns from the broader development community.
Use structured logging with object notation instead of string interpolation for debug messages to improve readability and provide better structured data. This approach makes logs more consistent and easier to parse, while also helping to consolidate related information into single log statements.
Instead of using string interpolation with multiple parameters:
debug("plugins file %s is default, check if folder %s exists", pluginsFile, path.dirname(pluginsFile))
Use structured logging with objects:
debug("checking if pluginsFile exists", { pluginsFile, dirName: path.dirname(pluginsFile) })
This format groups related data together, reduces the need for multiple debug statements, and makes the logs more readable. When possible, consolidate multiple related debug messages into fewer, more informative structured logs to avoid duplication across modules.
When designing API methods, prioritize intuitive usage patterns and backwards compatibility. Follow these guidelines:
// Bad - inconsistent parameter order
public Task
2. Use clear, singular property names for sub-clients:
```csharp
// Good
public IObservableTeamDiscussionsClient Discussion { get; }
// Bad
public IObservableTeamDiscussionsClient TeamDiscussion { get; }
This approach ensures APIs remain intuitive to use while maintaining compatibility for existing consumers.
When writing error messages or documentation related to network requests and cross-origin policies, use precise terminology that accurately describes the scope of the issue. Prefer “URL” over “domain” when the problem could involve any URL component (protocol, port, path, etc.), not just the domain name. Use proper technical terms like “origin” when discussing same-origin policy violations.
For example, instead of:
A cross origin error happens when your application navigates to a new superdomain which does not match the origin policy above.
Use:
A cross origin error happens when your application navigates to a new URL which does not match the origin policy above.
This precision helps developers understand that the issue isn’t limited to just domain changes but could involve protocol, port, or other URL components. Additionally, use proper grammar with articles (“a different origin” rather than “different origin”) and hyphenate compound technical terms (“same-origin URLs”) for clarity and consistency with web standards terminology.
When implementing security restrictions or policies, ensure error messages clearly explain what the security boundary is, why it exists, and what specifically triggered the violation. Vague or technical jargon can leave developers confused about security requirements.
Security error messages should include:
Example of improvement:
// Before: Vague message
"A cross origin error happens when your application navigates to a new superdomain"
// After: Clear and specific
"A cross origin error happens when your application navigates to a new domain which does not match the origin policy above.
Cypress does not allow you to navigate to different origin within a single test.
An origin is defined by protocol + host + port."
This approach helps developers understand security constraints and work within them effectively, rather than being blocked by cryptic error messages.
Write code that clearly communicates its intent through expressive method names and simplified control flow. Replace complex inline conditions with descriptive method calls that encapsulate the logic, and use early returns to reduce cyclomatic complexity and focus functions on their primary responsibility.
Key practices:
project.isBrowserState(Project.BROWSER_OPEN) instead of project.browserState === 'opened')Example:
// Before: Complex inline condition
if (project.browserState === 'opened' || project.browserState === 'opening') {
// main logic
}
// After: Expressive method encapsulation
if (project.isBrowserState(Project.BROWSER_OPENING, Project.BROWSER_OPEN)) {
// main logic
}
// Before: Nested conditional logic
function _closeBrowserBtn() {
if (this.props.project.browserState === 'opened') {
return (
<li className='close-browser'>
// button JSX
</li>
)
}
}
// After: Early return with expressive method
function _closeBrowserBtn() {
if (!this.props.project.isBrowserState(Project.BROWSER_OPEN)) return null
return (
<li className='close-browser'>
// button JSX
</li>
)
}
This approach makes code more readable, maintainable, and self-documenting while reducing complexity.
When designing or documenting API clients, always use the async/await pattern rather than blocking calls. Replace code that uses .GetAwaiter().GetResult() with proper async/await syntax to prevent potential deadlocks and improve application responsiveness.
Example:
// Instead of this:
Repository octokitRepo = ghClient.Repository.Get("octokit", "ocktokit.net").GetAwaiter().GetResult();
// Use this:
var octokitRepo = await ghClient.Repository.Get("octokit", "ocktokit.net");
Additionally, ensure method names clearly describe their API operation (e.g., ‘CreatePullRequestFromFork’ instead of ‘CreatePR’) to improve code readability and API usability.
When implementing algorithms that compare or process different data types, carefully consider the level of type strictness required for your use case. Overly strict type checking (like Object.prototype.toString) may prevent useful operations, while overly loose checking may produce meaningless results.
For diff algorithms and similar comparison operations, prefer typeof over Object.prototype.toString when you want to enable comparisons between objects of different classes but the same JavaScript type. This allows meaningful diffs between MouseEvent {clientX: 39, clientY: 50} and Object {clientX: 40, clientY: 50} since both are objects.
However, ensure your conditional logic properly handles mixed data types. When comparing strings to objects, verify that your algorithm gracefully handles or explicitly rejects such comparisons rather than producing confusing output.
# Too strict - prevents useful comparisons
_sameType = (a, b) ->
return objToString.call(a) is objToString.call(b)
# Better - allows comparisons between different object classes
_sameType = (a, b) ->
return typeof a is typeof b
Consider the downstream impact of your type comparison choice on the overall algorithm’s utility and user experience.
When a property or parameter represents an optional value that might be absent in requests or responses, use nullable types rather than non-nullable types with default values. This clearly distinguishes between “not set” and an explicit value, prevents sending unintended defaults in API requests, and properly handles missing values in API responses.
For boolean flags that are optional in API requests:
// INCORRECT: Will always send a value (false by default)
public bool MaintainerCanModify { get; set; }
// CORRECT: Only sent when explicitly set by the user
public bool? MaintainerCanModify { get; set; }
For enum-like values that might be absent in API responses:
// INCORRECT: Will cause issues when API returns null
public StringEnum<EmailVisibility> Visibility { get; protected set; }
// CORRECT: Properly handles missing values in responses
public StringEnum<EmailVisibility>? Visibility { get; protected set; }
This pattern also applies to optional fields in database models, DTOs, and any other context where a value might legitimately be absent. Using nullable types communicates intent clearly and prevents subtle bugs from default values being interpreted as explicit choices.
When making configuration changes that affect multiple platform-specific files, ensure all related configuration files are updated consistently and test the changes on each target platform.
Configuration changes often need to be replicated across platform-specific variants (e.g., alacritty.yml and alacritty_macos.yml). Failing to synchronize these files can lead to inconsistent behavior across platforms and user confusion.
Always identify and update all related configuration files when making changes. Additionally, verify that configuration changes work as expected on each target platform, as platform-specific behaviors can differ even with identical configuration syntax.
Example:
# alacritty.yml
key_bindings:
- { key: Equals, mods: Control, action: IncreaseFontSize }
- { key: Subtract, mods: Control, action: DecreaseFontSize }
# alacritty_macos.yml (must be updated consistently)
key_bindings:
- { key: Equals, mods: Command, action: IncreaseFontSize }
- { key: Subtract, mods: Command, action: DecreaseFontSize }
Test configuration changes on the actual target platforms rather than assuming cross-platform compatibility, as modifier keys and system behaviors can vary between operating systems.
Follow consistent naming conventions throughout the codebase to improve readability and maintainability:
// Good
IObservableOrganizationHooksClient Hook { get; }
// Not
IObservableOrganizationHooksClient Hooks { get; }
// Good
Task<string> GetSha1(string owner, string name, string reference);
// Not
Task<string> Sha1(string owner, string name, string reference);
// Good
Ensure.ArgumentNotNull(client, nameof(client));
// Not
Ensure.ArgumentNotNull(client, "client");
// Good - clearly identifies repository ID
Task
5. **For pull request operations, use 'number'** instead of 'id' to avoid confusion with the internal ID:
```csharp
// Good
IObservable<PullRequest> Get(string owner, string name, int number);
// Not
IObservable<PullRequest> Get(string owner, string name, int pullRequestId);
These conventions help maintain a consistent codebase, reduce confusion, and make the API more intuitive for consumers.
Always write assertions that verify specific, expected values rather than simple existence or boolean checks. This ensures tests validate exactly what you intend and provides clearer error messages when tests fail.
Do this:
// Use Assert.Equal to get both values when the test fails
Assert.Equal(2, issue.Assignees.Count);
Assert.Equal(_context.RepositoryOwner, closed.Assignees[0].Login);
Not this:
// Provides less helpful error messages
Assert.True(issue.Assignees.Count == 2);
Assert.True(closed.Assignees[0].Login == _context.RepositoryOwner);
When testing state changes, verify the specific new values rather than just checking the count:
// Verify the specific team that should be present after a change
Assert.Contains(restrictions, team => team.Name == contextOrgTeam2.TeamName);
// Rather than just checking the count which could be correct by coincidence
Assert.Equal(1, restrictions.Count);
In method tests, assert on exact return values, not just that a method was called. For object state assertions, verify the fields that should have changed rather than just checking if an object is non-null.
By being specific in your assertions, you:
Use abstraction layers to access configuration settings rather than accessing environment variables, feature flags, or other configuration sources directly. This improves maintainability by centralizing configuration logic, enabling validation, and simplifying testing.
Why it matters:
Implementation:
Instead of:
var organization = Environment.GetEnvironmentVariable("OCTOKIT_GITHUBORGANIZATION");
Prefer:
var organization = Helper.Organization; // Abstracted access to environment variable
For environment-specific code, use consistent preprocessor directives and centralize format strings:
var format =
#if !HAS_ENVIRONMENT
"{0} ({1}; {2}; {3}; Octokit {4})";
#else
"{0} ({1} {2}; {3}; {4}; Octokit {5})";
#endif
// Use format variable instead of duplicating the format string
When creating clients that require specific configuration constraints:
public EnterpriseSpecificClient(IApiConnection apiConnection)
{
// Validate configuration constraints early
if (!IsEnterpriseUrl(apiConnection.Connection.BaseUrl))
{
throw new InvalidOperationException(
"This client only works with GitHub Enterprise URLs.");
}
// Rest of constructor...
}
Names should clearly indicate their specific purpose and context, while maintaining correct capitalization of brand names and products.
When naming variables, parameters, or targets:
Examples:
GITHUBOWNER instead of GITOWNER when specifically referring to GitHub operationsGitHub not Github to maintain correct brand capitalizationThis practice improves code clarity, reduces confusion about a variable’s intended use, and presents a professional attention to detail in your codebase.