Awesome Reviewers

AI Agents & Assistants

Agent loops, tool calling, prompt and context assembly, agent SDKs and coding assistants.

774 instructions from 49 repositories. Last updated 2026-07-29.


Secure Boundary Enforcement

Standard: at every trust boundary, enforce security invariants in a way that cannot be skipped by flags, parsing edge cases, alternate code paths, or serialization differences.

Checklist (apply consistently): 1) Feature flags must not become bypass switches

2) Validate identifiers and map them safely to filesystem/network usage

Example (route boundary):

function assertSessionId(raw: unknown): string {
  if (typeof raw !== 'string') throw new Error('invalid');
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(raw))
    throw new Error('invalid');
  return raw;
}

3) Handle untrusted filesystem objects safely (symlinks/TOCTOU)

4) Sanitize all outputs on every path (not just the happy path)

Example (cancel path must sanitize like append):

await finalize(segmentId,
  sanitizeStreamingImageMarkers(record.content),
  'Cancelled',
  false,
);

5) Authorization/auth token propagation must be end-to-end

6) Confidentiality: treat platform “internal” flags as security labels

7) Parsing/regex guards must be robust to escape and grammar edge cases

8) Enforce sender-policy and consistent untrusted-data framing before aggregation

9) Don’t trust carriers written by the audited execution

This standard is meant to be a practical code-review rubric: when you see “allow/skip/early return/regex parse/check-then-use”, require that the security invariant still holds and that untrusted data cannot reach sinks (filesystem paths, network endpoints, subprocess argv, UI/LLM text, or public replies) without the corresponding validation/sanitization/authorization guarantees.


Test critical branches

When code adds/changes behavior (UI logic, URL rewriting, state-merge rules, keyboard/pointer guards, or error-recovery flows), ensure tests cover (1) the behavior itself (not just indirectly), (2) the negative guard cases that prevent regressions, and (3) the full interaction path users trigger.

Practical rules: 1) Lock shipped behavior with direct tests

2) Add negative tests for safety guards

3) For UI, test “click/trigger → menu/content/action”

4) Keep test selectors unique and stable

Example (Vitest):

import { describe, it, expect, vi } from 'vitest';

// Ensure both guard paths and the interaction path are tested.
describe('Pointer guard + action', () => {
  it('ignores non-primary pointer in hold mode', () => {
    // render component with hold mode; use user-event/pointer helper
    // pointer(button, 'pointerdown', pointerId=1, mouseButton=2)
    // expect(start).not.toHaveBeenCalled();
    expect(true).toBe(true);
  });

  it('opens overflow menu and executes host action', async () => {
    const onShare = vi.fn();
    // render PaneHeaderActions with a host action
    // force collapse widths
    // click overflow trigger
    // expect(menu items include 'Share')
    // click menu item -> expect(onShare).toHaveBeenCalledTimes(1)
    expect(onShare).toHaveBeenCalledTimes(0);
  });
});

Adopting this standard prevents the recurring issues seen across discussions: untested shipped branches, missing guard negatives, interaction paths that stop short of what users do, and fragile test selector collisions.


Branch-Exact Test Coverage

Make workflow/test suites “branch-complete and predicate-exact”: every reachable case arm and every required gating condition must be exercised and asserted, with environment-correct shims/guards.

Apply this standard: 1) Table-driven mapping tests must include every reachable branch (don’t rely on bijection checks only over the listed subset). If a case arm exists in the implementation, it must appear in the ARMS/fixtures list. 2) Ensure mocks/fixtures actually enter the new code path. If the PR adds an if/mapping branch, add a test where that branch evaluates true (or explicitly covers each comparison outcome). 3) Assert the full predicate, not just a prefix. If the gate is A && B && C, your test should check that the produced script/body contains all three conditions (missing one enables false-green). 4) Add OS/CI guards for end-to-end tests that rely on POSIX behavior or GNU tools. Use itOnUnix or darwin-only shims for sed -i and avoid shebang/shim issues on Windows merge-queue. 5) For timing/loop bugs, construct inputs so the code reaches the failing region (e.g., ensure a retry loop re-enters after the deadline check).

Example patterns:

If you follow these rules, regressions like “missing untested arms,” “new branch never executed,” “gate predicate weakened,” and “POSIX-only shims failing on Windows/macOS” are far less likely to slip through CI.


Keep Docs Accurate

Adopt a rule that comments/JSDoc/API docs must be both correct and useful at the point of use—never misleading, stale, or attached to the wrong symbol.

Apply this checklist:

Example: document generator consumption when yielding views into a reused buffer

async function* readFileHandleChunks(fileHandle: FileHandle, sourceSize: number): AsyncGenerator<Buffer> {
  const highWaterMark = 512 * 1024;
  const buffer = Buffer.allocUnsafe(highWaterMark);
  let position = 0;
  while (position < sourceSize) {
    const bytesRead = (await fileHandle.read(buffer, 0, Math.min(highWaterMark, sourceSize - position), position)).bytesRead;
    if (bytesRead === 0) return;
    position += bytesRead;

    // CONTRACT: This is a view into a reused underlying buffer.
    // Consumers must synchronously copy/consume the bytes before the next `yield`.
    yield buffer.subarray(0, bytesRead);
  }
}

If you make a behavioral change (output strings, semantics, validation rules, or i18n keys), treat documentation/comment updates as part of the same change set—otherwise the next developer will be guided by false information.


Defense-in-depth Security Guardrails

When handling security-sensitive interactions (authz/ownership, network callbacks, and untrusted execution), apply defense-in-depth at the boundaries: be precise about guarantees, bind authorization to explicit identities at creation time, validate inbound payloads before side effects, and isolate both execution and filesystem writes.

Practical rules: 1) Don’t overstate bypass behavior

2) Bind authorization explicitly; require exact-match on callbacks

3) Validate callback payload structure against stored state before calling responders

4) Only allow interactive actions for eligible inbound-human turns

5) Sandbox untrusted code with isolation parity; keep metadata out of the sandbox

6) Never write trusted outputs through untrusted worktrees

7) Constrain PR-facing writes to a single authorized path

Example (callback ingress validation pattern):

// 1) Owner-only: storedKey was recorded at card creation time.
const ok = normalizeOwner(callback.user) === storedKey;
if (!ok) return failClosed();

// 2) Answer-key defense-in-depth: indices must match stored questions.
const keys = Object.keys(payload.answers ?? {});
const valid = keys.every(k => {
  const i = Number(k);
  return Number.isInteger(i) && i >= 0 && i < storedQuestions.length;
});
if (!valid) return failClosed();

// 3) Only now call the responder/settlement.
await responder({ answers: payload.answers, ...otherFields });

Checklist your team can apply to any “interactive callback / bypass flag / untrusted execution” change: (authz binding) + (payload validation) + (eligibility definition) + (sandbox/credential boundaries) + (safe output path policy) + (single allowed write path).


Consistent Config Gates

When behavior is driven by config/flags (timeouts, scopes, feature gates, safe-mode), ensure every code path uses the same authoritative inputs and does not silently degrade.

Standards 1) No hardcoded environment overrides for timing: tool-call/polling waits must use env-aware defaults (or an explicitly justified env-aware formula), not fixed “one size fits all” timeouts. 2) Single source of truth for gates/flags: default parameter values must reference the current config gate accessor; avoid stale/legacy getters that can silently change semantics. 3) Scope correctness (and honesty): enforcement logic and user-facing warnings must match the settings schema/docs, including trusted scopes (e.g., SystemDefaults). 4) No machine-global security gates via per-workspace overrides: if a setting is intended to be consistent across the host, either ignore workspace scope for it or provide a deployment-level env var mechanism; otherwise mixed behavior will occur. 5) Mode parity (safe mode / special modes): status/reporting endpoints must use the same disablement and enforcement logic as execution paths. 6) Schema validity per version: fields that are dead in a given version must be removed from that version’s strict schema or explicitly reserved/documented. 7) Avoid global mutable config side effects: if you temporarily override module-level config (e.g., API host), restore it in a finally block.

Example: env-aware timeout instead of hardcoded

const toolCall = await rig.waitForAnyToolCall(
  ['write_file', 'edit'],
  rig.getDefaultTimeout(),
);

Example: restore overridden host/config

const prev = getGhHost();
try {
  setGhHost(window.host ?? undefined);
  // ... audit calls ...
} finally {
  setGhHost(prev);
}

Contract-Driven Workflow Testing

Workflow logic changes can silently ship if tests don’t observe the exact contract your users/ops depend on. Adopt this checklist when writing/modifying tests around GitHub Actions scripts/workflows:

1) Assert the real user-visible contract

2) Make stubs/fakes record critical invariants

3) Drive every critical branch with fixtures

4) Scope assertions to the correct job/step

Example pattern (branch + contract + invariant):

This approach prevents the three common silent-failure modes shown in review: (a) tests only look at coarse substrings, (b) stubs discard the changed parameter so nothing is asserted, and (c) fixtures never reach the branch that would break in production.


Avoid Drift Constants

When code relies on values or logic that can diverge from the rest of the system (CSS/layout, shared pagination sizes, status-to-UI rules, helper behavior), prefer a single source of truth.

Apply these rules:

Example (centralized status mapping + constants):

const TASK_STATUS_CONFIG = {
  completed: { labelKey: 'system.taskCompleted', tone: 'success', Icon: CircleCheckIcon },
  failed: { labelKey: 'system.taskFailed', tone: 'error', Icon: CircleXIcon },
  cancelled: { labelKey: 'system.taskCancelled', tone: 'neutral', Icon: CircleMinusIcon },
} as const;

const statusConfig =
  (taskStatus && TASK_STATUS_CONFIG[taskStatus as keyof typeof TASK_STATUS_CONFIG]) ??
  { labelKey: 'system.taskNotification', tone: 'neutral', Icon: InfoIcon };

const page = await workspace.client.listWorkspaceSessions(cwd, {
  pageSize: SESSION_LIST_PAGE_SIZE,
});

const style = getComputedStyle(header);
const headerGap = parseFloat(style.gap) || 0;

This reduces silent UI breakage when constants, CSS, or helper behavior change over time.


Mutation-Effective Testing

Ensure your tests are mutation-effective: they must fail when the implementation changes in ways that break intended behavior. Avoid vacuous assertions, and don’t confuse “a test exists” with “the test would catch the real bug.”

Practical standards: 1) Pin the observable contract, not a computed tautology

2) Cover the actual branch that enforces safety

3) Add boundary and shape variants where logic branches

4) Use an “equivalent mutant” check before escalating severity

Example: avoid a vacuous “either/or” success assertion

// Wrong pattern (can pass on silent tool failure):
expect(toolCall || updated).toBe(true);

// Mutation-effective pattern:
if (toolCall) {
  expect(updated, 'file must update when tool was called').toBe(true);
}
expect(toolCall || updated, 'must succeed via tool-call or correct content').toBe(true);

Example: test exact boundaries

// Instead of only “over limit” and “under limit”, also test equality.
expect(validateReason('x'.repeat(8000))).toBe(true);
expect(validateReason('x'.repeat(8001))).toBe(false);

Example: test alternate error shapes

it('treats ApiError-shaped quota exhaustion as exhausted', () => {
  const err = { error: { code: 429, message: 'quota exhausted', status: 'RESOURCE_EXHAUSTED' } };
  expect(isQuotaExhaustedError(err)).toBe(true);
});

Adopt this as a review checklist for the Testing category:


Capability-Aware Interface Contracts

When designing client-facing interfaces (request payloads, component props, or render-slot “host action” APIs), treat optional features and host-provided children as contracts—not assumptions.

Apply these rules: 1) Capability-gate request fields: Only send optional parameters when the server/daemon advertises support. Keep gating consistent across all call sites. 2) Don’t rely on opaque host forwarding: If your component needs to identify/trigger host actions after re-parenting (e.g., overflow menu), don’t depend on injected props/selectors being forwarded by arbitrary ReactNodes. Use wrappers, structured action descriptors (id/label/callback), or require/tightly type a forwarding contract (documented + enforced). 3) Keep shared state props consistent: If sibling controls are disabled/enabled based on the same state (e.g., approval pending), pass the computed value through—avoid hardcoded props. 4) Make UX fallbacks explicit: Avoid hardcoded non-localized labels and ensure accessible naming is produced from contract inputs (e.g., prefer aria-label/title, and don’t create unlabeled menu items from icon-only children).

Example (capability-gated request param):

const params: any = {
  pageSize: SESSION_LIST_PAGE_SIZE,
  archiveState: 'active',
};
if (capabilities.session_source_metadata) {
  params.sourceType = WEB_SHELL_SESSION_SOURCE_TYPE;
}
await listWorkspaceSessions(params);

Example (avoid opaque render-slot assumptions—use descriptors instead of ReactNode host actions):

type PaneAction = { id: string; label: string; onSelect: () => void };

function PaneHeaderActions({ actions }: { actions: PaneAction[] }) {
  return (
    <DropdownMenu>
      {actions.map(a => (
        <DropdownMenuItem key={a.id} onSelect={a.onSelect}>
          {a.label}
        </DropdownMenuItem>
      ))}
    </DropdownMenu>
  );
}

API Call Correctness

When automating GitHub (or similar) APIs from CI/workflows, treat API access like production client code: make it correct, complete, and safely reconcilable.

Standards 1) Use the approved API client/tooling

2) Never assume list endpoints fit in one page

3) Ensure query filters match the user-facing intent

4) Reconcile managed state only where provenance is knowable

Example pattern

set -euo pipefail

# 1) Prefer gh api over curl
# gh api "repos/$GITHUB_REPOSITORY/releases/tags/$RELEASE_TAG" > release.json

# 2) Paginate list results
reviewed_users="$(gh api --paginate "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/reviews?per_page=100" \
  --jq '[.[].user.login]')"

# 3) Apply filters that match inputs (conceptual)
# Ensure both issues and PRs use since/updatedAt bounds when hours is provided.

# 4) Safe reconciliation (conceptual)
# Only remove reviewers that were previously added by *this* workflow run.
# managed="$(...)"  # compute current requested_reviewers
# owned="$(...)"    # reviewers your workflow previously managed (tracked/provable)
# desired_owned="$(...)" # desired within owned set
# new_managed = (managed - owned) + desired_owned

Applying these rules prevents silent coverage gaps, incorrect reconciliation churn, and maintenance drift in authentication/versioning across API calls.


Warn on silent failures

In automation scripts/workflows, never fail or skip important work silently. If a condition decides to omit a capability/flag, or if a command fails with diagnostics discarded or a sentinel fallback is used, emit an explicit warning (or notice) that includes the relevant inputs and captured error output.

Apply this especially to:

Example patterns:

# 1) Conditional skip with warning
if [[ -n "$PREVIOUS_RELEASE_TAG" ]] && git merge-base --is-ancestor "$PREVIOUS_RELEASE_TAG" HEAD; then
  NOTES_START_TAG_FLAG+=(--notes-start-tag "$PREVIOUS_RELEASE_TAG")
elif [[ -n "$PREVIOUS_RELEASE_TAG" ]]; then
  echo "::warning::PREVIOUS_RELEASE_TAG ($PREVIOUS_RELEASE_TAG) is not an ancestor of HEAD; omitting --notes-start-tag"
fi

# 2) Don’t discard stderr; surface it
result="$(gh api graphql -f query="mutation { minimizeComment(input: {subjectId: \"${node_id}\", classifier: OFF_TOPIC}) { minimizedComment { isMinimized } } }" \
  --jq '.data.minimizeComment.minimizedComment.isMinimized' 2>&1)" || true
if [[ "$result" != "true" ]]; then
  echo "::warning::Failed to minimize ${node_id}: ${result}"
fi

# 3) Log computed/fallback values
RUNNER_UID="$(stat -c '%u' "$RUNNER_TEMP" 2>/dev/null || stat -f '%u' "$RUNNER_TEMP" 2>/dev/null || echo 0)"
RUNNER_GID="$(stat -c '%g' "$RUNNER_TEMP" 2>/dev/null || stat -f '%g' "$RUNNER_TEMP" 2>/dev/null || echo 0)"
echo "Ownership restoration: RUNNER_UID=$RUNNER_UID, RUNNER_GID=$RUNNER_GID"

Outcome: operators/oncall can immediately tell whether a path was intentionally skipped, what input caused it, and what underlying command error occurred—reducing 3AM guesswork.


Ensure CI-tested Workflows

All CI/CD-related script/workflow tests must be executed in CI, and they must assert the behaviors that matter in production—especially fail-closed security gates and correct step ordering.

Apply it as a checklist: 1) Wire tests into CI: if you have scripts/tests/*.test.js (or npm run test:scripts), add a workflow step that runs it. Don’t rely on developers running tests locally. 2) Test logic, not strings alone: for security-sensitive workflow gating, include negative/deny scenarios and verify the intended allow/deny behavior (and any explanation/telemetry flags). 3) Assert ordering, not just presence: when workflow steps sweep/cleanup temporary dirs or delete symlinks, verify cleanup happens after any artifact staging/copying that must dereference symlinks, and before the final launch/upload step.

Example (ordering assertion pattern):

const sweep = "find tmp -maxdepth 2 -type d -name '*-verify-*' -exec rm -rf {} +";
const stepText = getRunStepText(); // however your test builds/extracts it

const cpIndex = stepText.indexOf('cp -r');
const sweepIndex = stepText.indexOf(sweep);
expect(cpIndex).toBeGreaterThan(-1);
expect(sweepIndex).toBeGreaterThan(-1);
expect(cpIndex).toBeLessThan(sweepIndex); // fail if deletion moves earlier

This prevents regressions where CI wiring is missing and prevents “false green” tests where commands exist but run in the wrong order or weaken fail-closed gating.


Fail-safe Error Handling

Use fail-safe error handling everywhere in long-running / retrying flows: cleanup must be guaranteed, state/cursors must follow the intended retry semantics, and errors must remain diagnosable.

Apply these rules: 1) Cleanup in finally, not best-effort.

2) Decide per error kind: retry, terminal-skip, or bubble.

3) Never “silently succeed” after a failed dispatch.

4) Preserve diagnostics.

5) Classify timeouts/cancellations/quotas correctly.

Example pattern (cursor + fail-safe dispatch):

async function processBatch(items: Item[], cursor: Cursor) {
  let firstError: unknown;
  for (const item of items) {
    try {
      const ok = await dispatch(item);
      if (ok) cursor.markHandled(item.id);
      // advance cursor for success (or terminal skip)
    } catch (err) {
      if (isTerminal(err)) {
        // skip permanently but advance cursor so you don’t wedge
        cursor.markHandled(item.id);
        continue;
      }
      // retryable: do NOT advance cursor/dedup keys
      firstError ??= err;
    }
  }
  if (firstError) throw firstError;
  cursor.advanceToLatest();
  await cursor.save();
}

function isTerminal(err: unknown): boolean {
  // 404/410 patterns; also treat auth/permission without retry-after as terminal
  return err instanceof HttpError && (err.status === 404 || err.status === 410);
}

This standard prevents the common failure modes seen across the discussions: orphaned state from missing cleanup, lost messages from swallowing/“marking handled” on failed dispatch, infinite poll livelocks from not advancing cursor, and operator-blind failures from lost error context.


Trusted Error Handling

Use strict, non-silent error handling and evidence gating across CI scripts and publish steps—especially when untrusted inputs and reruns are involved.

Apply these rules: 1) Never hide failing diagnostics

2) Make “no match/empty input” non-fatal under set -e

3) Validate output marshalling before downstream parsing

4) Treat pipelines as a set of outcomes

5) Bound all “read/truncate” operations to avoid SIGPIPE under pipefail

6) Gate substantive/terminal publish updates on validated artifacts

7) Classify infra vs PR failures using trusted signals only

Illustrative bash pattern (combine rules 2,4,6):

set -euo pipefail

# 1) empty-match is expected
BLOCKED_USERS="$(grep -vE '^\s*#' blocklist | ... | sort -u || true)"

# 2) pipeline status: capture both stages
set +e
timeout 25m run_agent | tee output.jsonl
PIPE_STATUS=(${PIPESTATUS[@]})
AGENT_CODE=${PIPE_STATUS[0]}
TEE_CODE=${PIPE_STATUS[1]:-0}
set -e

verdict='pass'
if [ "$AGENT_CODE" -ne 0 ] || [ "$TEE_CODE" -ne 0 ]; then
  verdict='infra-error'
fi

# 3) only publish substantive if report exists
if [ "$verdict" = 'pass' ] && [ -f tmp/verify-*/report.md ]; then
  publish_substantive
else
  publish_weak_results_unavailable
fi

Outcome: fewer silent CI failures, correct publish/evidence preservation across reruns, and accurate infra-vs-PR labeling so developers don’t waste time rerunning code when the true problem was infrastructure (or the opposite).


Doc accuracy and conformance

Require every documentation change to pass two gates: (1) strict doc-schema conformance, and (2) factual/behavioral accuracy against the implementation and shipped artifacts.

Gate 1: Conformance

Gate 2: Accuracy & consistency

Example checklist (apply to every PR):

  1. Does the doc (or skill SKILL.md) meet all formatting/limit rules (one-sentence/≤60-char description, required sections, required metadata)?
  2. Do all commands match what is installed/configured in the same patch?
  3. Are any steps tool-scope-specific (CLI vs gateway) and documented accordingly?
  4. Are ports/URLs/paths consistent with the actual runtime and build artifacts?
  5. Are templating/rendering claims precise (including nested objects)?
  6. Do capability/mode descriptions match the actual implementation behavior?
  7. Are install/discovery instructions aligned with where the runtime actually scans?

If any item fails, the doc must be corrected (or the claim narrowed) before merge.


Boundary Hardening Rules

Treat every transition from “untrusted / scoped data” into a sensitive sink (shell execution, subprocess credentials, HTTP fetch, filesystem writes, and API-triggered work) as a security seam. Enforce fail-closed policy at that seam:

Example pattern (auth + safe command execution):

async def handler(self, request):
    auth_err = self._check_auth(request)
    if auth_err:
        return auth_err

    body = await request.json()
    user_supplied = str(body.get("command_args", ""))

    # Prefer argv list-mode
    argv = ["some-binary", "--arg", user_supplied]  # no shell
    # subprocess.run(argv, shell=False, check=True, ...)

    return web.json_response({"ok": True})

Adopting this “seam-first, fail-closed” standard prevents common regressions: injected shell tokens, secret-scope bypasses, unguarded public triggers, and redirect-based SSRF/TOCTOU.


Nonblocking Concurrency Rules

Establish a single concurrency standard: in async code, never block the event loop; in multi-thread/state-machine code, make ownership and cancellation atomic; and in cleanup/shutdown, use bounded, interrupt-friendly paths.

1) Keep async nonblocking

GOOD

result = await asyncio.to_thread(subprocess.run, […], timeout=60)

or

result = await adapter._run_blocking(func, *args)


2) Re-check cancellation/flags after waits
- If a worker can be paused in `Event.wait()` (or similar), it must re-check the controlling mode/flag at every boundary where it could restart capture/playback/processing.
- Pattern:
```py
await voice_done.wait()
if cli_ref._voice_continuous is False:
    return  # cancel boundary

3) Lock/claim correctly; snapshot atomically

4) Shutdown/cleanup must be bounded and interrupt-friendly

BETTER: cancel first, then bounded wait, then allow interrupt to proceed

pool.shutdown(wait=False, cancel_futures=True)

or wait with a timeout in your own logic


5) Add regression coverage for the real concurrency boundary
- For cross-thread queueing (e.g., `put_threadsafe()`), tests must involve a real worker thread, not only same-loop calls.
- For ownership/leases and cross-process locks, add OS-process regressions (where supported) to validate the intended guard behavior.

---

## Security Invariants Testing

<!-- source: QwenLM/qwen-code | topic: Security | language: Yaml | updated: 2026-07-28 -->


Treat CI/workflow security like production security code: define explicit invariants, enforce them defensively, and lock them with executable regression tests—especially in workflows that run in privileged contexts (e.g., pull_request_target) or execute untrusted PR code.

Apply these rules:
1) Pin third-party actions by immutable SHA
- Never use mutable tags (e.g., actions/cache@v4) in privileged contexts.
- Require the same “40-char SHA pin” convention for all actions.

2) Fail-closed authorization and principal resolution
- Gate execution on the correct identity (e.g., PR author if that’s the executed code path).
- Reject on missing principal, missing/empty permissions, 404s, or any API failure.
- If a run waits in a queue, re-check permissions immediately before executing.
- Pin the authorized head OID and refuse to run if checkout HEAD differs.

3) Credential minimization and strict scoping
- Keep tokens out of environments where untrusted code runs.
- Use step-level env only for the steps that need them.
- For pull_request_target checkouts: use persist-credentials: false.

4) Prevent control/data-plane poisoning
- Never select “previous report” or “running status” purely by prose/substring; use dedicated machine markers.
- For agent-produced reports: validate structured inputs (e.g., totals consistency) and HTML-escape untrusted content.
- Add executable tests for escaping and truncation behavior.

5) Filesystem hardening for self-hosted/persistent workspaces
- Assume symlinks and prior run state can be adversarial.
- Use symlink-safe deletion (unlink entries without following) and canonicalize any delete targets to remain inside the workspace.
- Ensure cleanup happens both before and after untrusted execution, with regression tests that fail when safety guards are removed.

6) Add/extend executable regression tests for invariants
- If a security invariant exists (repo guard, persist-credentials, cache restore-only, marker usage, escaping implementation, symlink-safe cleanup, re-auth/head pinning), it must be asserted by an automated workflow test.

Minimal examples (adapt patterns):

Action pinning:
```yaml
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.x.y pinned

Avoid embedding step outputs directly into shell:

- name: Record receipt
  env:
    POOL_RUN_ID: '${{ steps.dispatch.outputs.run_id }}'
  run: |
    printf '%s\n' "Pool run: $POOL_RUN_ID" >> "$GITHUB_STEP_SUMMARY"

Fail-closed principal handling (pattern):

# deny on missing/empty principal or permission API failures
if [ -z "$PR_AUTHOR" ] || ! permission="$permission_api_result"; then
  echo "decision=skip" >> "$GITHUB_OUTPUT"
  exit 0
fi
case "$permission" in
  admin|maintain|write) : ;;
  *) echo "decision=skip" >> "$GITHUB_OUTPUT"; exit 0 ;;
esac

Run the above as a checklist for every security-critical workflow change: if you can’t test the invariant, you don’t truly have one.


Single Source Helpers

When code review finds duplicated logic or repeated formatting/constants, treat it as a “single source of truth” violation. Factor shared logic into a helper/module and reuse it everywhere; avoid hardcoded literals where an existing helper/constant exists; and keep established idioms consistent.

Guidelines:

Example (helper extraction):

// helpers.ts
export function extractParentToolNames(generationConfig: unknown): string[] {
  // ... shared extraction logic ...
  return names;
}

// call sites
const names = extractParentToolNames(generationConfig);

Example (constant for repeated literals in tests):

const INITIAL_CONTENT = 'original content';
expect(input.content).not.toBe(INITIAL_CONTENT);

Workflow State Hygiene

CI/CD workflows should enforce state invariants across steps, runs, and runners: later steps must only execute when earlier phases truly produced a valid outcome, and all per-run state must be cleaned/flushed and permission-safe—especially on persistent self-hosted runners.

Apply these rules:

1) Gate downstream steps on all relevant phase outputs

# good: push requires gate=fixed AND verify != no-fixes
- name: Push and open PR
  if: ${{ steps.gate.outputs.result == 'fixes' && steps.verify.outputs.result != 'no-fixes' }}

2) Keep published artifacts consistent after reverts/aborts

3) Flush per-run temp/state on persistent runners

rm -rf "$RUNNER_TEMP/verify-results" "$RUNNER_TEMP/verify-context" 2>/dev/null || true
mkdir -p "$RUNNER_TEMP/verify-results" "$RUNNER_TEMP/verify-context"

4) Restore both ownership and write permissions after hardening

chown -R "$RUNNER_UID:$RUNNER_GID" "$GITHUB_WORKSPACE" || true
chmod -R u+rwX "$GITHUB_WORKSPACE" || true

5) Make workflow behavior robust to cache misses and checkout edge-cases

6) Prevent CI/resource hangs with explicit bounds

7) Keep concurrency predicates exact

If your workflow cannot be proven under: (a) cancellations, (b) persistent runner reuse, (c) cache misses, and (d) permission/mode changes, it’s a CI reliability issue—fix it with the invariants above before merging.


Accurate Recovery Error Handling

Coding standard for recovery/error paths: make failure and recovery behavior truthful, gated, and user-consistent.

Apply this rule set: 1) Ground messages and state on authoritative runtime outcomes (avoid predicates/flags that can drift from behavior). If the only way to know is to attempt (e.g., reset/clear), attempt and then report based on the result. 2) Choose degradation vs failure by comparing which one is less misleading to the user/UI.

Illustrative pattern (retry gating + bounded empty fallback):

if provider_errored || cancel_token.is_cancelled() {
    surface_error(provider_err);
    return;
}

let visible_content_streamed = last_assistant_text_not_empty || surfaced_thinking_in_turn || streamed_images;
if visible_content_streamed {
    // Avoid duplicate/incoherent resend.
    surface_error(provider_err);
    return;
}

let empty_response = no_tools_called && last_assistant_text.is_empty();
if empty_response {
    if empty_turn_retries < MAX_EMPTY_TURN_RETRIES {
        empty_turn_retries += 1;
        warn!("Empty provider response; retrying {}/{}", empty_turn_retries, MAX_EMPTY_TURN_RETRIES);
        messages_to_add.clear(); // don’t persist empty turn
        continue;
    }
    // After retries, surface a real message.
    let msg = Message::assistant().with_text(EMPTY_TURN_MESSAGE);
    yield AgentEvent::Message(msg.clone());
    messages_to_add.push(msg);
}

Explicit API Contracts

When API behavior depends on client/provider capabilities, request-field validity, or protocol ordering, implement it via explicit contracts—not heuristics—and ensure the exposed responses match the runtime’s effective configuration.

Apply these rules: 1) Capability-first (no guessing). If the server needs client terminal/shell dialect, OS/execution context, or other environmental details, require them via a typed capability during initialization; keep server-local inference only as a backward-compatible fallback. 2) Schema-correct request emission. Only send provider-specific fields (or attachment shapes) to the endpoints/models that accept them. Prefer Option/guarded emission over “best effort” extra fields. 3) Normalize then expose. If you build a local ModelConfig/limits for an endpoint, ensure the returned API view matches what the runtime actually uses after provider normalization. 4) Stable machine semantics. For machine-readable modes, keep output purely structured; for human modes, separate prose from metadata. Ensure error/status/stop_reason are consistent. 5) Tests that pin ordering. When correctness relies on evaluation/handling order (e.g., deciding which error to return), add table-driven tests that lock the intended sequence.

Example pattern (capabilities + fallback):

// During initialize: client-provided typed capability
struct ClientCapabilities {
    // e.g. typed goose initialize metadata
    terminal_shell: Option<TerminalShellCapability>,
}

// On terminal/create: use capability; fallback only for legacy clients
fn terminal_shell_command(cap: &ClientCapabilities) -> (String, Vec<String>) {
    if let Some(c) = &cap.terminal_shell {
        (c.executable.clone(), c.args_prefix.clone())
    } else {
        // Backward-compatible fallback (server-owned)
        (server_default_shell(), vec![])
    }
}

Outcome: fewer cross-provider breakages, fewer “works in one mode” inconsistencies, and API responses that reliably reflect the behavior clients will observe at runtime.


Config source alignment

Behavioral configuration must be documented and wired through the supported config system, with examples matching the actual runtime resolution.

Apply these rules: 1) Non-secret settings → config.yaml

2) .env is secrets-only

3) Docs must match real default resolution

4) Installation/runtime paths must be accurate

5) Avoid documenting unsupported keys until implemented

Example (~/.hermes/config.yaml):

# Non-secret behavior
kairos:
  enabled: true
  schedule: "weekly"

terminal:
  shell_init_files: []   # explicit list replaces OS defaults

Example (.env):

OPENAI_API_KEY=***
# secrets only

Bound Hot-Loop Work

Default to explicit resource budgets and ensure they’re actually enforced.

Apply these rules in code review: 1) Bound inputs and remote pagination

2) Eliminate repeated expensive work in hot loops

3) Make enforcement observable/tested

Example (bounded pagination + draining):

const todos = await this.api.TodoLists.all({
  state: 'pending',
  perPage: 100,
  maxPages: 5,
});

for (const todo of todos) {
  if (unsupported(todo)) {
    // must drain/skipped items to avoid re-fetch forever
    await this.api.TodoLists.done({ todoId: todo.id });
    continue;
  }
  await this.process(todo);
  await this.api.TodoLists.done({ todoId: todo.id });
}

Example (memoize stable resolved roots):

// once per config/session
const resolvedPinnedRoots = memoryRoots.map((root) =>
  realpathExistingOrNew(path.resolve(root, AUTO_MEMORY_PINNED_DIRNAME)),
);

function isProtectedPinnedMemoryPath(resolvedCandidate: string|undefined, literalCandidate: string) {
  return memoryRoots.some((_, i) =>
    isWithinRootCaseInsensitive(literalCandidate, literalPinnedRoots[i]) ||
    (resolvedCandidate && resolvedPinnedRoots[i] &&
      isWithinRootCaseInsensitive(resolvedCandidate, resolvedPinnedRoots[i]!))
  );
}

4) Don’t endorse unverifiable perf claims


Bound async waits

In async/concurrent code, always make cancellation/timeout behavior correct, deterministic, and safe against stale work.

Coding standard 1) Bound the full operation: put tokio::time::timeout around the entire request/handshake/startup sequence that must not hang (including setup/config/mode steps). 2) Cancel/cleanup what you own: if a timed-out Future is dropped, ensure any spawned process/task owned by that component is cleaned up via kill_on_drop(true) or cancellation-aware control messages. Also propagate cancellation tokens into nested operations. 3) Race stream polling vs cancellation: don’t rely on stream.next().await to return on cancel; use tokio::select! and forward provider.cancel(...). Ensure cancel forwarding still happens even if the consumer drops the stream. 4) Reject stale updates: when superseding sessions/providers, use a generation key (e.g., active_session_id) set only after successful setup; drop notifications/updates whose id doesn’t match. Abort/clear old notification receiver tasks on provider recreation. 5) Don’t lose ordered protocol messages: use awaited send() (not lossy try_send) for ordered streams where sequence/termination matters.

Pattern (timeout + cancellation forwarding + stale filtering)

use tokio::{select, time};

let models = time::timeout(SUPPORTED_MODELS_TIMEOUT, async {
    let provider = create_provider().await?;
    provider.fetch_supported_models().await
}).await??;

// In an event loop handling session notifications:
let active_session_id = /* set only after successful session/new */;
while let Some(update) = rx.recv().await {
    if update.session_id != active_session_id { continue; }
    handle_update(update);
}

// In a provider reply loop:
loop {
    let next = select! {
        biased;
        _ = cancel_token.cancelled() => {
            provider.cancel(&session_id).await;
            break;
        }
        msg = stream.next() => msg,
    };
    if next.is_none() { break; }
    handle_msg(next.unwrap());
}

Adopting this standard prevents: (a) hung handshakes that outlive the caller, (b) orphaned child processes after timeout, (c) “cancel didn’t stop backend” bugs, (d) stale session/provider updates corrupting state, and (e) ordering/termination regressions in protocol streams.


Behavioral Regression Testing

When adding or modifying tests, favor behavioral contract coverage over brittle implementation/shape checks.

Apply these rules:

Example pattern (deterministic time):

class FakeTime:
    def __init__(self, real_time, start=1000.0):
        self._real = real_time
        self._now = start
    def monotonic(self):
        return self._now
    def advance(self, seconds):
        self._now += seconds
    def __getattr__(self, name):
        return getattr(self._real, name)

def test_silence_threshold(monkeypatch):
    import time as real_time
    fake = FakeTime(real_time)
    monkeypatch.setattr("tools.voice_mode.time", fake)
    # drive the timeline deterministically
    fake.advance(0.05)
    # assert state transitions...

This approach makes tests resilient to harmless refactors while still catching real regressions in control flow, branching, and platform-dependent behavior.


Null-Safe Parsing

Enforce null/optional safety at every boundary: treat external API data and persisted JSON as untrusted, validate before dereferencing, and ensure normalization/parsing preserves only values that satisfy the declared type contract. Never let invalid optional fields “leak through” via ...raw spreads or falsy-based numeric checks; degraded modes must remain structurally consistent so downstream consumers don’t misinterpret missing facts.

Practical rules:

Example (safe normalization + “never throws”):

type Out = { hostAuthToken?: string };

function stringOrUndefined(v: unknown): string | undefined {
  return typeof v === 'string' ? v : undefined;
}

export function normalizeWorker(raw: unknown): Out {
  if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {};
  const r = raw as Record<string, unknown>;
  // Do NOT `return { ...raw, ... }` (it can leak wrong-typed optional fields).
  return {
    hostAuthToken: stringOrUndefined(r.hostAuthToken),
  };
}

export function parseReceiptIds(raw: string): number[] {
  try {
    const parsed = JSON.parse(raw);
    if (parsed === null || typeof parsed !== 'object') return [];
    const o = parsed as Record<string, unknown>;
    const ids = Array.isArray(o.reviewIds)
      ? o.reviewIds
      : typeof o.reviewId === 'number'
        ? [o.reviewId]
        : [];
    return ids.filter((x): x is number => typeof x === 'number' && Number.isInteger(x));
  } catch {
    return [];
  }
}

Applying this will prevent both crash-on-null (wedge/stall) and silent misclassification (wrong “clean” or “unknown” signals).


Correct Dedup Cache Keys

When implementing cursor-based dedup/caching for event dispatch, ensure the dedup “key space” matches the real uniqueness of what you’re trying to prevent:

Practical template:

// 1) Dedup key must change when the triggering content changes.
const notifKey = `${notification.id}|${notification.updated_at}`; // not just notification.id

if (this.isDispatched(this.cursor.dispatchedNotifications, notifKey)) return;

// 2) Dispatch
await this.handleInbound(envelope);

// 3) Persist dedup keys for the exact items you dispatched
this.recordDispatched('dispatchedComments', dedupKey);
this.recordDispatched('dispatchedBodies', `${chatId}|${threadId}`);
this.recordDispatched('dispatchedEvents', triggerKey);

// 4) When re-discovering triggers, include both bounds
const event = events.findLast((candidate) => {
  const t = candidate.created_at;
  return t && t <= ctx.maxUpdatedAt && t > ctx.windowSince;
});

Acceptance checklist for reviews: 1) Every dispatch path has a corresponding, persisted dedup record (comments/bodies/events) on success. 2) Dedup keys include all dimensions needed to distinguish distinct “things to dispatch.” 3) Trigger search uses the same window bounds as the comment/body fetch logic. 4) Cursor trimming covers every dedup bucket you rely on. 5) HTTP read/caching headers are only applied on non-error response branches (or explicitly proven safe).


Hot Path Efficiency

Default to “do the minimum possible work per hot-path update.”

Apply these checks: 1) Early-exit before side effects

2) Keep props/callbacks stable during streaming

3) Don’t recreate observers/effects due to irrelevant dependencies

4) Throttle at the right stage + memoize expensive transforms

5) Detect changes against consistent baselines

Example (stable handler + throttled transform):

const handleRightPanelOpen = useCallback((request: TurnOutputOpenRequest) => {
  if (request.kind === 'subagent') {
    onRightPanelOpen?.({ /* ... */ });
  }
}, [onRightPanelOpen]);

const throttledContent = useThrottledValue(content ?? '', isStreaming);
const renderedContent = useMemo(() => {
  if (throttledContent && source && sourceMarkdown?.transformMarkdown) {
    return sourceMarkdown.transformMarkdown(throttledContent, { source });
  }
  return throttledContent;
}, [throttledContent, source, sourceMarkdown?.transformMarkdown]);

Use this standard to review PRs that touch streaming, parsing, rendering, observers, and settings-change detection.


Cache Scope and Keys

When adding or modifying caching/deduplication, ensure the cache identity (routing + key + scope) matches the exact contract where reuse is valid.

Key rules:

Example (mode-gated dedupe key):

def should_dedupe(event_guid: str, *, use_socketio: bool) -> bool:
    # Dedupe only applies to Socket.IO duplicate suppression.
    return use_socketio and bool(event_guid)

Example (scoped config cache):

_config_cache_by_home = {}

def load_audit_config_scoped(hermes_home: str) -> dict:
    key = hermes_home
    if key in _config_cache_by_home:
        return dict(_config_cache_by_home[key])
    cfg = compute_cfg(hermes_home)
    _config_cache_by_home[key] = cfg
    return dict(cfg)

Example (signature compatibility without secret material):

Apply these checks during code review: “Is this cache used by multiple call paths/modes? If so, is reuse gated correctly and does the key include all compatibility dimensions? Is the cache bounded and scoped to the correct profile/lifecycle?”


Atomic Exact-Run Cancellation

When implementing concurrent async workflows with callbacks (Stop/Submit/Cancel, permission settlement, card actions), make the operation safe against stale/foreign/parallel events by using atomic identity validation plus a synchronous “claim” before any awaited side effects.

Apply these rules:

Example (pattern for exact-run Stop):

async function cancelRunFromCard(expectedRunId: string, ownerKey: OwnerKey): Promise<boolean> {
  // 1) parse/validate owner + callback identity (no awaits yet)
  if (!isOwnerMatch(ownerKey)) return false;

  // 2) synchronous claim of the current live record
  const active = getCurrentActivePrompt(); // atomic read
  if (!active || active.runId !== expectedRunId) return false;
  const claim = tryClaim(active); // must be synchronous
  if (!claim) return false;

  // 3) only now do awaited side effects
  const ok = await channelBase.cancelExactRun(active.sessionId, expectedRunId);
  if (ok) {
    blockNewStreamingChunks(active.runId);
    commitStoppedProjection();
    claim.releaseSuccess();
  } else {
    claim.release(); // keep card active for retry
  }
  return ok;
}

Adopt this as a standard for any callback-driven cancellation/submission path so parallel runs and near-simultaneous callbacks cannot corrupt state or show incorrect success to users.


Atomic Reservation And Recheck

When adding concurrency behavior (locks, in-flight guards, timeouts, retries, sampling), ensure three properties:

1) Atomic “check-and-act” before any await (avoid TOCTOU)

2) Revalidate decisions against a fresh snapshot (avoid stale-snapshot races)

3) Cleanup must drain/await in-flight work even on failure (avoid teardown ordering bugs)

Practical patterns

A) Atomic in-flight reservation

const inFlight = new Set<string>();

async function createSession(id: string) {
  // synchronous check-and-add before any await
  if (inFlight.has(id)) throw new Error('409 conflict');
  inFlight.add(id);
  try {
    // do awaits/spawn here
    await doWork();
  } finally {
    inFlight.delete(id);
  }
}

B) Generation guard for out-of-order async completion

let gen = 0;
const lastApplied = { current: -1 };

async function refresh() {
  const myGen = ++gen;
  const value = await compute();
  if (myGen !== gen) return;         // stale completion
  if (lastApplied.current !== myGen) {
    lastApplied.current = myGen;
    setState(value);
  }
}

C) Double-sample + drift flag

const headBefore = await getPrHead();
const comments = await fetchAllComments();
const headAfter = await getPrHead();
const drift = headBefore !== headAfter;
// If drift, mark threads as staleWorktree or fail-closed.

D) Drain async writes in finally

let outputWrites = Promise.resolve();

try {
  await pumpInputToPty();
  await outputWrites;
  return;
} finally {
  // ensure pending writes finish or are cancelled before teardown
  await outputWrites.catch(() => {});
}

If any change touches session creation, process spawning, locks/reservations, per-attempt retries, terminal/IO pipelines, or sampling across async boundaries, apply this checklist and add regression tests for the “race-changed-decision” branches—not just the happy path.


Scoped API Contract

When implementing API-facing features, ensure request/response contracts are consistent across all code paths, correctly shaped for the upstream/downstream API, and complete under pagination/time-windowing.

Rules: 1) Keep serialization/parsing round-trips structurally identical

2) Validate upstream API method signatures and data fields

3) Make state transitions scope-safe; don’t mix per-item windows with global cursor side effects

4) Ensure pagination/windowing is complete (no permanent omission)

Example patterns:

export function parseSessionId(pathname: string) { // Mirror writer: anchor to the last occurrence if writer used last-match logic. return pathname.match(/\/session\/([^/]+)\/?$/)?.[1]; }

// Test: expect(parseSessionId(buildSessionPathname(‘/app/session/’, ‘real-id’))) === ‘real-id’

- Avoid wrong-typed external calls by removing casts and using correct method signatures:
```ts
// Prefer typed signatures; do not do api.Issues.show(chatId, { issueIId: ... })
// If SDK says show(issueId, { projectId }), pass issueId as number and projectId as string.

Adopting these rules prevents silent drops, permanent omissions, and contract drift—common failure modes in API integration code.


Action slot invariants

When building React “action slot” containers (inline vs overflow menus, responsive headers, hold/click controls), enforce these invariants:

1) Preserve host mount semantics

2) Preserve DOM identity for event guarantees

3) Normalize host output before applying asChild/DOM-level props

4) Use the menu framework’s item components for accessibility + behavior

5) Don’t rely on custom components forwarding unknown props

Example pattern (flatten + menu items + safe wrappers, no Fragment targets):

import { Children, Fragment, isValidElement, useMemo } from 'react';

function flattenToElements(node: React.ReactNode) {
  const out: React.ReactElement[] = [];
  for (const child of Children.toArray(node)) {
    if (!isValidElement(child)) continue;
    if (child.type === Fragment) {
      out.push(...flattenToElements((child.props as any).children));
    } else {
      out.push(child);
    }
  }
  return out;
}

function OverflowMenu({ children }: { children: React.ReactNode }) {
  const elements = useMemo(() => flattenToElements(children), [children]);

  return (
    <DropdownMenuContent>
      {elements.map((el, i) => (
        <DropdownMenuItem key={el.key ?? i} asChild>
          <span style={{ display: 'contents' }} data-action-index={String(i)}>
            {el}
          </span>
        </DropdownMenuItem>
      ))}
    </DropdownMenuContent>
  );
}

Applying these rules prevents: duplicated subscriptions (double mount), broken menu roles/keyboard behavior (raw children), invalid DOM prop application to Fragments, click-proxy failures from missing prop forwarding, and interaction bugs from DOM identity changes during state transitions.


CI Verification Contracts

CI/CD verification steps must produce truthful, reproducible, human-visible evidence under hard environment constraints (time, filesystem, available tools, git history). Concretely:

1) Keep evidence visible across stages

2) Make verification rerunnable (idempotent cleanup)

Example (safe worktree lifecycle):

# use a directory name that matches cleanup patterns (or remove explicitly)
git worktree add tmp/base-verify-tree HEAD^1
# ... run A/B ...
# always remove what you registered
git worktree remove --force tmp/base-verify-tree

3) Don’t promise evidence you can’t obtain

4) Run only gates your container can actually run; avoid mutating the PR tree

5) Validate controls don’t accidentally execute head code

6) Follow-up reports must snapshot the newest substantive evidence

Applying these rules prevents CI/CD from silently hiding failures, failing reruns due to stale artifacts, overstating verification certainty, or producing non-comparable A/B results—raising reliability of automated gates and maintainer trust in the evidence.


Error semantics invariants

When handling failures, treat “what happened” as a precise, testable contract—not an interpretation. Ensure (1) classification predicates are exact and consistent across docs+code, (2) failure causes are not overloaded, (3) cleanup/settlement invariants prevent stranded states, and (4) adapter/step contracts are enforced with safe fallbacks.

Apply these rules:

1) Freeze exact recovery predicates (spec == code)

2) Carry failure cause explicitly; never infer from an overloaded signal

3) Enforce exactly-once settlement and all parallel invariants

4) Validate “handled”/“presented” contracts; on violation, fall back to safe path

Example (pseudocode)

// 1) Exact error classification predicate
function classifyNoMatches(rg: { exitCode: number; stdout: string; stderr: string }) {
  // NO MATCHES only when exitCode==1 and stderr is empty.
  // (Do not key off stdout; JSON modes may emit stdout summaries.)
  if (rg.exitCode === 1 && rg.stderr.length === 0) return 'no_matches';
  return 'not_no_matches';
}

// 2) Adapter contract enforcement
async function presentWithContract(ctx: {
  presentUserInputRequest: () => Promise<'presented'|'handled'|'unsupported'>;
  respondMustBeCalledForHandled: () => void;
}) {
  let respondCalled = false;
  const wrappedRespond = () => { respondCalled = true; ctx.respondMustBeCalledForHandled(); };

  const result = await ctx.presentUserInputRequest(/* uses wrappedRespond */);

  if (result === 'handled' && !respondCalled) {
    // Contract broken: fall through to existing permission formatter/sender.
    return 'unsupported';
  }
  return result;
}

// 3) Typed settlement reasons (conceptual)
// settlementSignal.reason must distinguish answered_elsewhere vs request_cancelled/run_cancelled/expired.

Checklist before merge


Sorted Selection Safety

When code decides “latest/first/anchor” behavior (events, schedule steps, URL/mention parsing), it must be deterministic by construction: sort inputs by the relevant timestamp/field before using positional selection (e.g., findLast), use dedup keys at the correct granularity to avoid permanent suppression, and make regex/parsers unambiguous with correct anchors/lookarounds for the target grammar.

Apply this standard: 1) Sort before positional selection

// Before selecting the most recent matching event
const events = await listEvents(...);
// Sort explicitly by created_at (or the actual field you reason about)
events.sort((a, b) => (a.created_at || '').localeCompare(b.created_at || ''));

const event = events.findLast((candidate) => {
  // apply your temporal/logic predicates against candidate.created_at
  return candidate.created_at && candidate.created_at > lowerBound;
});

2) Dedup keys must match the true identity of the unit being deduped

const notifKey = `${notification.id}|${notification.updated_at}`;
if (isDispatched(dispatchedNotifications, notifKey)) continue;

3) Regex/parsers: align grammar assumptions on both parse and emit sides

Why: Without these properties, seemingly small changes (different pagination alignment, an extra character allowed by a platform, or a dedup key that’s too coarse) turn into permanent missing triggers, duplicate dispatches, or wrong attribution.


Typed API Contracts

When introducing or changing an API seam (hooks, callback payloads, lifecycle state transitions), require an explicit, end-to-end, type-safe contract that matches implementation and documentation.

Checklist:

Example pattern (typed settlement wrapper):

type UserInputSettlementReason =
  | 'resolved_outside_card'
  | 'request_cancelled'
  | 'run_cancelled'
  | 'expired';

function setSettlementReason(signal: AbortSignal, reason: UserInputSettlementReason) {
  // avoid writing to any-typed fields directly; centralize the mapping
  (signal as any).__settlementReason = reason;
}

Example contract sketch (adapter-facing context):

interface ChannelUserInputRequestContext {
  requestId: string;
  sessionId: string;
  runId: string;
  target: SessionTarget;
  ownerId: string;
  request: PermissionRequestEvent['request'];
  settlementSignal: AbortSignal;
  respond(response: { /* RequestPermissionResponse + optional answers */ }): Promise<boolean>;
}

If any of the above can’t be satisfied, treat it as an API design bug: either the contract is incomplete, the correlation is not end-to-end, the semantics are not type-safe, or the documentation/API surface are out of sync.


Deterministic Set Reconciliation

When you correlate agent outputs, commit history, or prior workflow state across time, avoid fuzzy matching and “best-effort” heuristics. Instead: 1) Associate via stable identifiers (IDs), not text substrings. 2) Treat reviewer/record collections as sets and reconcile them with drift awareness (manually dismissed items must be excluded even if they never reviewed). 3) Persist the right state invariant for future runs—don’t overwrite marker state with post-drift values that erase manual decisions. 4) Use precise selectors for markers/reports (e.g., startswith(marker) and a dedicated “substantive report” marker), not “newest non-running”.

Example (stable association + precise marker selection):

# Commit message should include fix.id (written by the agent)
# Then drop matching becomes exact.
# e.g., msg contains(fix.id) rather than 30-char substring.
node -e '...
  const droppedMsgs = process.env.DROPPED_MSGS.split("\n");
  f.fixes = f.fixes.filter(fix => !droppedMsgs.some(msg => msg.includes(fix.id)));
'

Example (drift-aware desired-set update):

# prev_desired = what you previously intended *before* drift
# current = actually requested now
# reviewed = who already submitted a review
# Exclude manual dismissals: reviewers in prev_desired but not in current and not in reviewed.
drift=$(jq -cn --argjson p "$prev_desired" --argjson c "$current" --argjson r "$reviewed" '$p - $c - $r')
desired=$(jq -cn --argjson d "$desired" --argjson drift "$drift" '$d - $drift | sort')
# IMPORTANT: write marker using pre-drift desired, not the post-drift one.
marker_body="${marker} {\"desired\":$pre_drift_desired} -->"

Operational rule: if a matching/reconciliation step can plausibly pick the wrong entity due to wording, ordering, or manual UI actions, treat that as an algorithmic correctness failure—tighten inputs (IDs/markers), and tighten set logic (invariants + drift).


Success Contract Error Handling

Define a single “success contract” for each step: only report ok/success if the operation is actually accepted; for optional steps, convert failures into a structured soft-skip (but still record a diagnostic reason).

Apply these rules: 1) Optional work ⇒ soft-skip with reason

2) Required work ⇒ hard-fail

3) API writes ⇒ treat provider error channels as failures

Example (optional step soft-skip)

async function stageBrowser({ hasNode, skipReasonRef, SkipChromium }) {
  if (!hasNode) {
    skipReasonRef.value = 'Node.js unavailable; optional browser tooling skipped';
    return { skipped: true };
  }
  try {
    await InstallAgentBrowser({ SkipChromium });
    return { skipped: false };
  } catch (e) {
    skipReasonRef.value = `agent-browser install failed: ${String(e?.message || e)}`;
    // Do NOT rethrow: optional degradation
    return { skipped: true };
  }
}

Example (GraphQL mutation userErrors)

async function applyMutationOrFail(client, mutation, variables) {
  const data = await gql(client, mutation, variables);
  const result = data?.[/* mutation root field */] || data;
  const userErrors = result?.userErrors || [];
  if (userErrors.length) {
    throw new Error(`Mutation rejected by API: ${JSON.stringify(userErrors)}`);
  }
  // Optionally verify returned fields match the approved inputs here.
  return result;
}

Outcome: fewer false “ok:true” results, predictable graceful degradation for optional features, and consistent diagnostics when failures happen.


Configuration drift prevention

Prevent inconsistencies between configuration sources of truth (build config, extension manifests, and package metadata) that cause IDE/runtime surprises.

Apply these rules when adding/updating any package/extension:

1) Mirror required build configuration options across comparable packages

Example (tsconfig.json):

{
  "extends": "../../../tsconfig.json",
  "compilerOptions": {
    "declarationMap": true,
    "outDir": "dist",
    "rootDir": "src"
  }
}

2) Make manifest tool exposure explicit

3) Declare or clearly document required env/config

4) Keep version sources in sync

Net effect: consistent IDE navigation, predictable runtime behavior, and fewer “it works on my machine”/dirty lockfile/version drift issues.


Documentation consistency

Documentation and doc-driven instructions must stay truthful and self-consistent with the underlying code and the document’s structure.

Apply this checklist when writing or editing docs/specs/templates:

  1. Match the real code scope: if a section claims something is “Correct” or “stored in X,” confirm the referenced symbol/function/path actually exists and is used within the stated directory/runtime.
  2. Avoid stale or positional cross-references: don’t say “tables above”/“item 7” when the document is reorganized. Prefer stable anchors like section/table names, or update directional wording whenever content moves.
  3. State claims at the right strength: if a metric only bounds an effect (not isolates it), phrase it as an upper bound / diagnostic rather than an estimate of a specific subsystem.
  4. Keep behavior descriptions aligned: ensure wording about failure modes and side effects matches the implementation (e.g., “fails rather than drops” vs the actual “fails and drops”).
  5. Use concrete evidence when relevant (function names, file paths, or file:line quotes) so a reader or scan tool can verify the claim.

Example pattern (robust cross-reference):


Explicit null fallbacks

When handling null/undefined, be explicit about intent:

Example (routing fallback):

const reportedWorkspaceCwd = connection.sessionId
  ? connection.workspaceCwd
  : (selectedWorkspaceCwd ?? primaryWorkspaceCwd);
// If selectedWorkspaceCwd is undefined, fall back to primaryWorkspaceCwd—not a stale connection.workspaceCwd.

Example (exhaustive switch):

switch (checks) {
  case 'passing': return ...;
  case 'failing': return ...;
  case 'none': return null;
  default: {
    const _exhaustive: never = checks;
    return null;
  }
}

Example (test nullability):

expect(latestChatEditorProps.disabled).toBe(false); // not undefined

Guard Async Reentry

Any UI/logic that performs async work must be resilient to rapid user actions and intermediate async states: prevent re-entry, ensure callbacks use the latest intended state, and avoid losing results/errors when components unmount.

Apply these rules: 1) Guard against re-entry in async handlers

const submit = async (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault();
  if (saving || reloading) return; // prevent duplicate onEnter/rapid submit
  setSaving(true);
  try {
    await onSave(/*...*/);
  } finally {
    setSaving(false);
  }
};

2) Prevent concurrent requests

3) Make timing/streaming callbacks use “latest” state, and verify with tests

4) Be lifecycle-safe for in-flight operations

5) Handle “connecting/pending” phases deterministically

This standard targets the real failure modes described: stale/incorrect final results from scheduled callbacks, duplicated async calls (and conflicting revisions), lost errors due to unmount during pending work, and dropped actions when release happens before the underlying connection is ready.


Publish-safe dependency ranges

When CI/CD builds and release automation publish or test packages from a monorepo, inter-workspace dependency specs and lockfile contents must stay publish-safe and CI-consistent.

Standards 1) No unresolvable workspace paths in published deps

2) Use publish-time-resolved specs

3) Keep lockfile aligned with manifests

4) If CI starts running new workspaces, ensure reporting is wired

Example (recommended inter-workspace dependency style)

{
  "dependencies": {
    "@qwen-code/channel-base": "workspace:*"
  }
}

Operational checklist for PRs affecting release/CI


Config Defaults And Overrides

When introducing or changing configuration options, treat the canonical config defaults and override policy as the single source of truth across runtime and provisioning.

Apply this standard: 1) Register every new (or newly-documented) key in the canonical DEFAULT_CONFIG used by the loader—do not rely on *.example files to define runtime behavior. 2) Verify merge semantics with regression tests:

Minimal pattern for (1)-(2):

# hermes_cli/config.py
DEFAULT_CONFIG = {
  "agent": {
    "claude_agent_sdk": {
      "streaming": False,
      "allow_metered_key": False,
      "append_file": "",
    },
  },
}

# tests should assert:
# - deep-merge fills missing blocks/keys from DEFAULT_CONFIG
# - explicit user values in config.yaml remain unchanged
# - loader output matches canonical defaults exactly

For (4), ensure provisioning stages mirror runtime policy (e.g., read disabled toolsets from the existing config.yaml and skip the install step with a clear skipped reason when the toolset is disabled).


Minimize expensive API calls

When your code depends on GitHub (or other remote) APIs, pagination and per-item mutations are often the dominant performance cost. Structure workflows/scripts to avoid redundant full scans and to prevent N+1 API patterns unless the workload is provably small.

Apply this standard:

Example pattern (avoid re-paginating; pass comment_id forward):

- name: Post status comment
  id: post_status
  if: ${{ always() }}
  run: |
    set -euo pipefail
    MARKER='<!-- autofix-status -->'
    # Locate or create status comment, then output its id
    STATUS_ID=$(gh api "repos/${REPO}/issues/${PR}/comments" --paginate \
      | jq -rs --arg m "$MARKER" --arg ab "$AUTOFIX_BOT" \
        '[.[][] | select((.user.login // "") == $ab) | select((.body // "") | contains($m))] | last | .id // empty')
    if [[ -z "$STATUS_ID" ]]; then
      STATUS_ID=$(gh api "repos/${REPO}/issues/${PR}/comments" -f body="..." --jq '.id')
    else
      gh api --method PATCH "repos/${REPO}/issues/comments/${STATUS_ID}" -f body="..." >/dev/null
    fi
    echo "comment_id=$STATUS_ID" >> "$GITHUB_OUTPUT"

- name: Finalize
  if: ${{ always() }}
  run: |
    set -euo pipefail
    STATUS_ID='${{ steps.post_status.outputs.comment_id }}'
    # Use STATUS_ID directly; do NOT re-run --paginate here.
    echo "Using status comment id: $STATUS_ID"

This reduces execution time, API usage, and flakiness from rate limits—especially across repeated rounds or high-comment PRs.


Single Source Config

Ensure workflow configuration (env vars, inputs, config lists) has a single authoritative definition and a clearly documented consumer.

Apply this when editing GitHub Actions/workflow configs or config-driven automation:

Example (pattern): derive the maintainer list once and reuse it, instead of duplicating:

- name: Classify
  id: classify
  run: |
    # router outputs JSON including full maintainer list
    result="$(node router.mjs ... )"
    echo "maintainers=$(echo "$result" | jq -c '.maintainers')" >> "$GITHUB_OUTPUT"

- name: Apply review requests
  env:
    MAINTAINERS: '${{ steps.classify.outputs.maintainers }}'
  run: |
    # use MAINTAINERS as the single source of truth
    node apply.mjs --maintainers "$MAINTAINERS"

This prevents drift, makes changes predictable, and avoids confusing behavior caused by precedence/overrides or unused settings.


API Config Consistency

Declarative API/provider configurations must be internally consistent with (a) the canonical identifiers used by the model registry/discovery layer and (b) the request-building logic that actually emits fields for the selected engine/path. This prevents mismatches, silent capability drops, and confusing “it’s configured but doesn’t work” behavior.

Apply these checks when adding/updating provider JSON: 1) Canonicalize model IDs

2) Make capability flags truthful

Example pattern (canonical ID + truthful capability):

{
  "name": "example-provider",
  "engine": "openai",
  "api_key_env": "EXAMPLE_TOKEN",
  "models": [
    {
      "name": "vendor/Canonical-Model-ID", 
      "context_limit": 123456,
      "reasoning": true
      /* reasoning is only true if the request builder emits the needed field for this model path */
    }
  ]
}

If you’re unsure whether a capability is emitted for a given model/engine path, prefer “capability off” over a misleading on-flag, or implement the necessary request-layer support (with a clear, testable mapping).


Deterministic Set Logic

When implementing set-based selection/reconciliation algorithms, ensure (1) deterministic outcomes and (2) invariant-preserving persisted state across runs.

A. Deterministic tie-breaking (order-independent “argmax”) If you pick a “best” owner based on computed scores, explicitly define what happens when scores are equal—do not rely on Map/array iteration order.

function pickBestOwner(scores) {
  let best = null;
  let bestScore = -Infinity;
  for (const [owner, score] of scores) {
    if (score > bestScore) {
      best = owner;
      bestScore = score;
    } else if (score === bestScore) {
      // deterministic tie-break (example: lexical)
      if (best === null || owner < best) best = owner;
    }
  }
  return best;
}

B. Persist the canonical desired set (not a derived delta) In multi-run reconciliation (markers/comments, requested reviewers, etc.), persisted state must represent the canonical target. If you persist a filtered/derived view (e.g., desired - reviewed), later runs can lose elements and permanently drift from the intended target.

// Canonical marker persistence: store full desired, not effectiveDesired.
const newMarkerBody = `${MARKER} {"desired":${JSON.stringify([...desired].sort())}} -->`;

Checklist for PRs in this area


Graceful Failure Handling

When an action depends on daemon capabilities or other availability checks, never fail silently or hard-fail the whole UI. Instead: (1) gate capability-dependent parameters/requests so missing capabilities degrade gracefully, and (2) treat dependency outcomes as real failures—don’t return “handled/success” if the operation wasn’t actually performed; surface a user-visible toast/message.

Practical rules:

Example (combined pattern):

if (directive.toLowerCase() === 'sider') {
  const ok = createSideTask();
  if (!ok) pushToast('warning', t('sideTask.unavailable'));
  return true;
}

const listOpts: any = { /* ... */ };
if (hasCapability('session_source_metadata')) {
  listOpts.sourceType = WEB_SHELL_SESSION_SOURCE_TYPE;
}
// If capability is missing, omit sourceType to prevent request-wide failure.

I18n Translation Policy

Treat every newly added user-facing string key as a documentation/UX contract for all supported locales.

When you add t() keys: 1) Classify the keys against the project’s translation policy (e.g., MUST_TRANSLATE_KEYS). 2) If the key is required: add translations in all required locale files in the same PR. 3) If the key is intentionally allowed to fall back (not in MUST_TRANSLATE_KEYS): don’t rely on “CI is green” silently—add an explicit maintainer note and create/track a follow-up “translation pass” issue (prioritize locales, define a quality gate, and link it in the PR). 4) Double-check the locales that are expected to be complete (e.g., full parity locales). Untranslated strings there should be fixed immediately.

This prevents users from seeing raw English fallback text (even though it won’t crash), while still supporting deliberate rollout decisions.

Example (process pattern):

// 1) Add new keys to the i18n source
export default {
  'Set Default Model': 'Set Default Model',
  // ...
}

// 2) In the PR description / follow-up tracking, state which case applies:
// - Required locales: <list> (translations added)
// - Optional fallback: <list> (link a follow-up translation pass)
// - Rationale: key intentionally excluded from MUST_TRANSLATE_KEYS

Rule of thumb: if users in a locale will see English instead of the intended language, the PR must either include the translations or explicitly schedule a translation pass with owners and scope.


Validate Configuration Contracts

Configuration docs/examples and runtime behavior must stay aligned, and configuration must be explicit and validated.

Apply two rules: 1) No silent no-ops: If a config field is accepted by schema/docs, it must actually affect runtime behavior—or be removed from examples and clearly documented as unused/ignored. Add validation/tests that cover example payloads to prevent “looks supported but isn’t” failures. 2) No ambiguous defaults: For critical targets derived from environment/remotes (repo selection, workspace selection, endpoints), do not guess from generic names like origin. Require explicit config/flags (e.g., --repo owner/name) and validate structure (e.g., the remote URL must match the intended owner/repo). If missing/ambiguous, fail fast with a clear error or ask rather than continuing.

Example pattern:

// Ensure only the actually-used field controls behavior
const timeoutMs = config.autoRecall?.timeoutMs; // not config.timeoutMs
assertNumber(timeoutMs, 'autoRecall.timeoutMs is required');

// Ensure repo selection is explicit and validated
function pickRepo(requiredOwnerRepo: string, remotes: Record<string, string>) {
  if (!requiredOwnerRepo) throw new Error('Provide --repo owner/name');
  for (const url of Object.values(remotes)) {
    if (urlIncludesOwnerRepo(url, requiredOwnerRepo)) return requiredOwnerRepo;
  }
  throw new Error('No remote matches the intended --repo owner/name');
}

Result: admins/users get predictable configuration behavior, and tooling won’t act on the wrong repo or silently ignore intended settings.


Scrub Tokens From URLs

Sensitive authentication tokens must not remain in the browser URL after they are consumed. Tokens in query parameters (?token=) will leak via browser history, server access logs, and Referer headers when users navigate away; removing URL fragments alone is insufficient if ?token= is supported.

Apply this standard by:

Example pattern:

function replaceStandaloneSessionUrl(url: URL) {
  // ... logic that extracts token from url.searchParams

  // After token is consumed, remove it from the address bar
  if (!import.meta.env.DEV) {
    url.searchParams.delete('token');
    url.searchParams.delete('daemon');
  }

  // ... continue with navigation/state update
}

Bounded Hot-Path Work

In performance-sensitive hot paths, ensure you (1) don’t repeat expensive work, (2) keep async/event-loop paths non-blocking, (3) bound external operations with finite timeouts, and (4) avoid unnecessary computation/materialization by prefiltering queries and projecting only what’s needed.

Practical rules:

Example pattern (reused probe + bounded subprocess):

async def send_audio(path, upload_fn, send_msg_fn, ffprobe_fn):
    # Probe once (prefer an async-friendly ffprobe wrapper if available)
    duration_ms = await ffprobe_fn(path, timeout=10.0)  # must be bounded

    # Upload using the same duration metadata
    media_id = await upload_fn(path, metadata={"duration_ms": duration_ms})

    # Reuse for message payload (no second probe)
    return await send_msg_fn(media_id, metadata={"duration_ms": duration_ms})

Checklist to apply during review:


Robust error propagation

When handling failures, ensure you (a) don’t lose the real root cause, (b) never introduce new exceptions while trying to report one, and (c) keep graceful degradation both implemented and tested.

Apply these rules:

Example pattern (scope-safe + preserve cause):

function deadlineError(lastError) {
  return new Error(
    `Model generation time budget exhausted: ${lastError?.message ?? 'unknown error'}`,
    { cause: lastError },
  );
}

let lastError;
for (;;) {
  if (Date.now() >= deadline) throw deadlineError(lastError);
  try {
    // ...
  } catch (e) {
    lastError = e;
    // retry / backoff
  }
}

Checklist for review: 1) Are all error sources checked (not just stdout/text)? 2) Can any error-reporting path throw a new exception (scope/ReferenceError)? 3) Do wrapped errors include { cause }? 4) Are control-flow decisions based on stable identifiers (constants), not rewordable strings? 5) Are fallback/best-effort behaviors covered by assertions in tests? 6) Is error-message construction centralized to avoid drift?


Deterministic normalization predicates

When transforming, sorting, deduplicating, or merging structured data, ensure comparisons use domain-correct semantics and identity signals are preserved.

Apply these rules: 1) Parse before comparing/sorting. Convert timestamp/typed fields into domain types (e.g., RFC3339 → instant) rather than relying on raw string/lexical order. When values may be missing/unparseable, still produce deterministic output with an explicit tie-breaker. 2) Canonicalize keys used for dedup/join. If two inputs can represent the same logical entity via different encodings (paths with ../symlinks, dot vs bracket notation, root vs nested identifiers), normalize them before using them in a HashSet/map key. 3) Keep boundary/identity predicates strict for merges. If you relax equality checks that define a boundary (e.g., “which turn does this reasoning belong to?”), you can merge distinct events. If recovery requires tolerance, restrict it to the smallest safe dimension and guard ambiguity (e.g., redacted placeholders). 4) Precedence matters. In pipelines with multiple enrichment/inference paths, run authoritative sources before inference, so guards like “only fill when unset” don’t block correct data. 5) Lock with regression tests around pathological inputs (missing dates, mixed offsets, ambiguous redaction, structured key syntax variants).

Example pattern (semantic sort with deterministic fallback):

let mut items: Vec<(String, String)> = arr
  .iter()
  .filter_map(|m| {
    let id = m.get("id")?.as_str()?.to_string();
    let created_at = m.get("created_at")
      .and_then(|v| v.as_str())
      .unwrap_or("")
      .to_string();
    Some((id, created_at))
  })
  .collect();

// Prefer sorting by parsed instant; fall back deterministically.
items.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| a.0.cmp(&b.0)));

Checklist for PRs in this area:


Graceful Error Recovery

When handling failures in async, remote, or multi-step flows, make the system degrade safely and keep UI/state consistent with what the server actually persisted.

Apply these rules:

1) Bound remote calls; fall back on hang

2) Keep optimistic updates reversible and server-aligned

3) Guard destructive operations with preconditions

4) Retry best-effort operations with bounded backoff and clear completion semantics

Example pattern (timeout + fallback + consistent state + bounded retry):

async function withTimeout<T>(p: Promise<T>, ms: number): Promise<T> {
  return await Promise.race([
    p,
    new Promise<T>((_, reject) => setTimeout(() => reject(new Error('timeout')), ms)),
  ]);
}

async function listModelsWithFallback(providerId: string): Promise<string[]> {
  try {
    const live = await withTimeout(
      fetchLiveModels(providerId), // remote call
      4000
    );
    return live;
  } catch {
    return await fetchCachedInventoryModels(providerId); // safe degraded path
  }
}

async function retryEachUri(uris: string[], fn: (uri: string) => Promise<void>) {
  const maxAttempts = 3;
  for (const uri of uris) {
    let attempt = 0;
    while (attempt < maxAttempts) {
      try {
        await fn(uri);
        break; // success for this item
      } catch {
        attempt++;
        if (attempt >= maxAttempts) throw new Error(`exhausted: ${uri}`);
        const backoffMs = Math.min(200 * 2 ** (attempt - 1), 2000);
        await new Promise((r) => setTimeout(r, backoffMs));
      }
    }
  }
}

If you follow these principles together, your error handling will be both user-friendly (no hangs), correct (no state divergence), and resilient (retries are bounded and semantics are explicit).


Semantic merges and sorts

When implementing algorithms that merge incremental updates and compute ordering (grouping/sorting), ensure the algorithm matches the producer semantics and uses semantically correct keys—don’t rely on heuristic fixes.

Apply these rules: 1) Incremental merge semantics: if the upstream emits append-only deltas, merge with append (e.g., +=). If chunks are cumulative, only then use overwrites or dedup logic. 2) Sorting/grouping keys: sort by the timestamp that represents the meaningful event (e.g., “last message activity”), not by generic updatedAt that may change for renames/metadata-only updates. 3) Live/remote dependencies: if the input set is built via remote discovery, bound per-provider latency and fall back to a stable cache to prevent the whole computation from stalling.

Example patterns (adapted):

// 1) Append-only delta merge (don’t use dedup/overlap heuristics)
function mergeTextDelta(existing: string, incomingChunk: string) {
  return existing + incomingChunk;
}

// 2) Semantically correct sort key
const tA = new Date(a.lastMessageAt ?? a.updatedAt).getTime();
const tB = new Date(b.lastMessageAt ?? b.updatedAt).getTime();
projectSessions.sort((a, b) => tB - tA);

// 3) Bounded live discovery with fallback
async function withTimeout<T>(p: Promise<T>, ms: number): Promise<T> {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => reject(new Error(`timed out after ${ms}ms`)), ms);
    p.then(v => { clearTimeout(timer); resolve(v); }, e => { clearTimeout(timer); reject(e); });
  });
}

async function getModelsWithFallback(live: () => Promise<string[]>, cache: string[], ms = 4000) {
  try {
    return await withTimeout(live(), ms);
  } catch {
    return cache;
  }
}

This prevents subtle UI/state bugs caused by incorrect merge assumptions, wrong sort keys, and unbounded remote computation.


Bounded, Consistent Extras

Whenever you change feature extras or dependency constraints in config (e.g., pyproject.toml), apply the same compatible version range everywhere that dependency is installed or resolved, and follow the dependency policy: bounded ranges only (no bare lower bounds; no conflicting exact pins). Regenerate the lockfile after the update.

Checklist

Example (pattern)

# pyproject.toml
[project.optional-dependencies]
voice = [
  "numpy<2",
]

tenki = [
  "tenki>=0.5.1,<0.7",
]

native-fetch = [
  "readability-lxml>=0.8,<0.9",
  "html2text>=2024.0,<2025.0",
]

Then update any other install mechanism that still references the old pins/ranges, and run uv lock (or the repo’s standard lock regeneration step) so uv.lock reflects the same bounds.


Safe Configuration Handling

When configuration affects scripts (env vars, dotenv files, compatibility gates), treat it as serialized input/output and enforce correctness at three points: (1) safe encoding, (2) correct source scoping, and (3) declared bounds.

Apply this standard: 1) Escape/quote values you write into dotenv/shell syntax.

2) Scope config-file reads to the explicit boundary variable.

3) Enforce compatibility ranges exactly as declared.

Net effect: generated config remains parseable, scripts read the intended configuration source, and installations/feature gates behave consistently with the project’s declared support.


Harden auth and output

Security-sensitive data and sinks must be hardened before use. Concretely:

1) Auth/token validity guarantees

2) Sanitize strings embedded into terminal escape sequences

3) Use secure, permissioned temp locations

Example (sanitizing OSC 8 link URLs):

function stripControlChars(s: string): string {
  return s.replace(/[\x00-\x1f\x7f]/g, "");
}

const href = stripControlChars(token.href ?? "");
const osc8Open = `\x1b]8;;${href}\x07`;
const osc8Close = `\x1b]8;;\x07`;

Normalize selection keys

When selecting a “preferred” item (via find, filter, pagination anchors, etc.) or deciding based on a computed threshold, ensure two things: 1) Compare like with like: normalize/parse inputs so the keys you compare are in the same canonical form. 2) Use explicit priority + fallback: run a primary search first; only if it yields nothing should you consult a fallback source. Avoid making fallback evidence primary.

Practical checklist:

Code pattern (key normalization + prioritized fallback):

// 1) Normalize first (so comparisons match)
const normalized = isCompactionMode
  ? resolveModelId(settings?.merged?.compactionModel?.trim() ?? '')
  : undefined;

// 2) Primary then fallback
const preferred = (() => {
  // primary: use the most reliable/expected source(s)
  const primary = normalized
    ? availableModelEntries.find(({ authType, model }) =>
        authType &&
        authType === normalized.authType &&
        model.id === normalized.modelId
      )
    : undefined;

  if (primary) return primary;

  // fallback: weaker/secondary match only if primary failed
  return availableModelEntries.find(({ model }) => model.id === normalized?.modelId);
})();

Apply this same approach to anchor selection and transcript pagination: prefer session_update-derived ids first; only if absent should you use the history_truncated marker id.


Bound parallel async lifecycle

For any async workflow that fans out (e.g., Promise.all over providers) or mutates shared session state, apply two rules: 1) Bound/cancel all external async work (timeouts must abort the underlying operation, not only the awaiting caller). 2) Centralize lifecycle transitions for shared mutable state (prefer a state enum + transition helper over ad-hoc “reset fields in parallel”).

How to apply

Example (client-side timeout with defense-in-depth)

const LIVE_MODELS_TIMEOUT_MS = 4000;

function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T> {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
    promise.then(
      (value) => { clearTimeout(timer); resolve(value); },
      (err) => { clearTimeout(timer); reject(err); }
    );
  });
}

// In fan-out code, ensure each task is bounded so Promise.all can complete.
const liveIds = await withTimeout(
  acpListProviderSupportedModels(providerId),
  LIVE_MODELS_TIMEOUT_MS,
  `live model discovery for ${providerId}`
);

Example (lifecycle state centralized)

enum PromptLifecycle { Idle, AwaitingRun, Running, Succeeded, Failed }

function transitionEntry(entry: Entry, next: PromptLifecycle) {
  // Reset/updates happen in one place to keep concurrent transitions consistent.
  switch (next) {
    case PromptLifecycle.Idle:
      entry.activePromptAttemptId = null;
      entry.activeRunId = null;
      return;
    // other states...
  }
}

This prevents: (a) UI workflows stalling indefinitely due to a single slow dependency, (b) leaked in-flight work when only the client await is timed out, and (c) inconsistent session state caused by partial or parallel field resets.


Evidence-grade Testing

When adding or updating test/verification logic, treat the harness setup as part of the test and ensure the evidence is causally attributable and non-vacuous.

Standard

  1. Isolate the control variable (no hidden confounds): If your A/B or control relies on shared artifacts like node_modules, document and enforce when that’s a clean control. If dependency inputs change (e.g., package.json/lockfiles), either run a dependency-aware control or explicitly record the confound.
  2. Prove the wiring really points to the intended code: In monorepos, internal workspace dependencies may symlink into the wrong (e.g., PR/head) tree. Add a check that resolves the actual runtime targets (e.g., realpath of resolved modules) and gate pass/fail of the verification on that.
  3. Require non-vacuity for “prove the test matters” runs: If you validate a new/changed test by reverting/mutating inputs, the run must (a) reach the setup, and (b) fail the intended assertion with an expected-versus-actual mismatch message. If the revert breaks import/compile/setup before the assertion, record it as inconclusive, not proof.
  4. Regression-test the harness invariants (the harness is production code): Add unit tests that pin subtle logic in your automation (e.g., stage-marker matching uses startswith, and you filter by bot author). Also ensure ids are re-resolved at patch time when threads/comments may have mixed order.

Example pattern (monorepo control isolation)

# Run from the base worktree.
# 1) Resolve what the code under test actually loads.
REALPATH=$(node -p "require('fs').realpathSync(require.resolve('@qwen-code/qwen-code-core'))")

# 2) Assert it points into the base tree (pseudo-check).
case "$REALPATH" in
  *tmp/base-tree/*) echo "OK wiring: $REALPATH" ;;
  *) echo "FAIL: base control resolved to non-base code: $REALPATH" ; exit 1 ;;
esac

Example pattern (non-vacuity rule)

Example pattern (harness regression tests)


Concurrency synchronization rules

Design GitHub Actions concurrency so overlapping runs can’t corrupt multi-step outcomes.

Rules: 1) Don’t assume concurrency is a durable multi-stage queue. If stage A and stage B must be serialized as one logical transaction, either:

2) Align the concurrency group predicate with the job if gate. GitHub evaluates concurrency before job if, so any kill-switch/feature flag that changes run behavior must be included in the concurrency group condition too.

3) Prevent “request accepted, nothing happens”. When concurrency saturation can drop jobs (only one running + one pending), add an always-hosted acknowledgement path (e.g., in authorize) that posts a visible “queued/dropped” notice based on in-flight counts.

4) Make publication overwrite-safe:

Example patterns:

A) Same-boundary serialization across dependent stages (use when B must not overlap A):

jobs:
  verify:
    concurrency:
      group: ${{ format('{0}-verify-{1}', github.workflow, github.event.issue.number) }}
      cancel-in-progress: false
  publish-verify:
    needs: [verify]
    concurrency:
      group: ${{ format('{0}-verify-{1}', github.workflow, github.event.issue.number) }}
      cancel-in-progress: false

B) Per-run isolation + idempotent publication (use when concurrency can’t be made durable):

jobs:
  verify:
    concurrency:
      group: ${{ format('{0}-verify-run-{1}', github.workflow, github.run_id) }}
      cancel-in-progress: false
  publish-verify:
    needs: [verify]
    concurrency:
      group: ${{ format('{0}-verify-run-{1}', github.workflow, github.run_id) }}
      cancel-in-progress: false

C) Include kill-switch/qualifiers in both if and concurrency.group (conceptually):

If you apply these principles, your concurrency design becomes correct under race conditions, feature toggles, and saturation—without relying on brittle scheduling assumptions.


Fail-Closed Security Hygiene

Security gates and cleanup must be fail-closed and boundary-proven.

Apply these rules when implementing/adjusting secure workflows:

1) Authorization must not degrade

2) Re-sweep after PR-controlled lifecycle scripts

3) Prove the auth boundary with real requests

4) Make security tests hermetic (no global/system config influence)

Example (authorization routing + fail-closed execution):

# In the shell gate script
body_lc="${COMMENT_BODY,,}"
case "$body_lc" in
  *@qwen-code /verify*)
    # FAIL CLOSED: require BOTH principals to have permission
    # (e.g., should_run=false unless author_has_write && commenter_has_write)
    ;;
  *@qwen-code /tmux*)
    # Keep existing narrower gate
    ;;
  *)
    should_run=false
    ;;
esac

Example (post-PR lifecycle hygiene):

# In the agent step, immediately before upload/agent start
rm -rf "$RUNNER_TEMP/verify-results"
mkdir -p "$RUNNER_TEMP/verify-results"
start_openai_proxy

Resilient UI Failure Handling

Make UI behavior robust to failure scenarios by aligning (a) what you validate, (b) what you treat as success, and (c) how state is updated when partial failures happen.

Apply these rules: 1) Don’t treat async work as successful until it resolves. Show success toasts only after awaiting; catch and handle rejections. 2) Avoid brittle callback chains when operations aren’t atomic. Prefer authoritative, event-driven state updates that carry enough context to remain consistent under partial failure. 3) Prevent “hidden required field” failures by gating submit and validating only the inputs that are actually rendered/required.

Example pattern:

// 1) Async success after await
const handleCopyMarkdown = async () => {
  try {
    const markdown = conversationToMarkdown(messages, session?.name);
    await navigator.clipboard.writeText(markdown);
    toast.success(intl.formatMessage(i18n.copiedMarkdown));
  } catch {
    toast.error(intl.formatMessage(i18n.copyFailed));
  }
};

// 2) Gate actions to avoid hidden required-field failures
const requiredNonOAuthKeys = /* compute required keys that are rendered */;
const canSubmit = hasOAuth ? requiredNonOAuthKeys.length > 0 : true;

// render footer only when canSubmit, and validate only those keys
const handleSubmitForm = () => validateAndSubmit(requiredNonOAuthKeys);

// 3) For multi-step updates, prefer authoritative event/state updates
// rather than relying on an 'onComplete' callback that may not fire
// when step N succeeds and step N+1 fails.
// e.g., update header from a full 'config_option_update' payload.

Versioned cache coherence

When a cache is invalidated asynchronously, ensure coherence between (a) the invalidation/version signal and (b) the cached payload/derived artifacts.

Standard

  1. Bundle version with payload: design cache reads to return the version alongside the data they correspond to (e.g., (version, tools)). Never let callers read the version from one moment and the payload from another.
  2. Atomic invalidation under one lock: when invalidating, update both the payload state and the version while holding the same synchronization/lock, so any observer of the new version cannot concurrently see stale payload.
  3. Refresh derived state immediately: if your loop depends on cached data (e.g., tool lists used to build prompts), detect version changes and rebuild derived state using the newly returned (version, payload)—preferably in the same logical iteration/turn, not “some time later”.

Illustrative pattern (Rust-like)

// Cache stores version + payload together.
struct Cache<T> {
    inner: Option<(u64, T)>,
}

impl<T> Cache<T> {
    async fn get(&mut self, version: &AtomicU64, fetch: impl FnOnce() -> T) -> (u64, T) {
        if let Some((v, data)) = self.inner.as_ref().cloned() {
            return (v, data);
        }
        let v = version.load(Ordering::SeqCst);
        let data = fetch();
        self.inner = Some((v, data.clone()));
        (v, data)
    }

    async fn invalidate_and_bump(&mut self, version: &AtomicU64) {
        // Hold the lock for both operations.
        self.inner = None;
        version.fetch_add(1, Ordering::SeqCst);
    }
}

// Reply loop: baseline comes from the payload it used.
let (baseline_version, tools) = tools_cache.get(...).await;
// ... build prompts using `tools` ...
if extension_manager.tools_cache_version() != baseline_version {
    let (new_version, new_tools) = tools_cache.get(...).await;
    // Rebuild prompts derived from `new_tools`.
}

Why

Adopting this standard prevents whole classes of intermittent “cache changed mid-use” bugs and makes refresh behavior deterministic under concurrency.


Use width-safe strings

When implementing string operations that depend on the environment (terminal/UI rendering or filesystem paths), avoid naive .length/single-separator logic. Use algorithms that are correct for Unicode/code points and for the actual width/splitting rules of the runtime.

Apply:

Example patterns:

// Width-safe truncation (prefer established libs)
import stringWidth from 'string-width';
import cliTruncate from 'cli-truncate';

function truncateForTerminal(label: string, maxCells: number) {
  // Truncates by terminal cells; avoids naive .length truncation.
  // (Use/align with the same render-side truncation approach.)
  return cliTruncate(label, maxCells, { ellipsis: '' });
}

// Cross-platform path splitting
function splitDirPath(dir: string): { name: string; parent: string } {
  const trimmed = dir.replace(/[\\/]+$/, '');
  const parts = trimmed.split(/[\\/]/);
  const name = parts.pop() ?? '';
  const parent = parts.join('/');
  return { name, parent };
}

Checklist:


Normalize Missing Values

When handling optional/missing inputs, normalize and guard early so “missing” can’t accidentally become a real value or clobber existing state.

Rules:

  1. Normalize sentinels to None immediately (e.g., treat Some(0)/""/placeholder numbers as “unset”), before applying fallback chains or “is set?” logic.
  2. Gate behavior on prerequisites: if a required resource/path value is missing, return a structured error or defer activation—do not proceed with a potentially wrong default.
  3. Preserve on partial updates/imports: only overwrite fields that were actually provided; never default missing fields to empty values.
  4. Choose semantics for “missing vs explicit off”: omission vs sending an explicit value should be deliberate and tested against downstream behavior.

Example (Rust):

fn apply_update(existing: &mut Config, input: &Input) -> anyhow::Result<()> {
    // 1) Normalize “not configured” sentinel -> None
    let new_limit: Option<usize> = match input.context_limit {
        Some(0) | None => None,
        Some(v) => Some(v),
    };

    // 2) Preserve unspecified fields (partial update)
    if let Some(limit) = new_limit {
        existing.context_limit = Some(limit);
    }

    if let Some(new_provider) = input.provider.as_deref() {
        if !new_provider.is_empty() {
            existing.provider = new_provider.to_string();
        }
    }

    // 3) Guard on prerequisites (defer/return)
    if existing.working_dir_missing() {
        anyhow::bail!("working_dir_missing");
    }

    Ok(())
}

Use this pattern consistently across null/optional fields, sentinels, and partial request bodies to avoid meaning drift and state poisoning.


Null-safe early Guards

Always handle nullable/optional state explicitly before executing logic that can mutate state, clear user input, or drop data. Use early returns or dedicated “disabled” props driven by well-defined nullable/flag conditions, and preserve intentional empty values instead of treating all falsy/empty inputs as “missing.”

How to apply:

Example pattern:

function onUpdate({ currentSnapshot, updateMessage }: any) {
  // Explicit null/flag guard
  if (!currentSnapshot?.session || currentSnapshot.session.working_dir_missing === true) {
    return; // block side effects when required data is missing
  }

  updateMessage();
}

function stripEmptySlots(params: Record<string, any>) {
  for (const [key, value] of Object.entries(params)) {
    const isEmptyObject =
      value && typeof value === 'object' && !Array.isArray(value) && Object.keys(value).length === 0;
    if (isEmptyObject) delete params[key];
    // Note: empty arrays are preserved
  }
}

Canonicalize and Disambiguate Identifiers

Ensure every place that stores, looks up, validates, or returns provider/model/function identifiers uses a clear internal naming contract:

Example (disambiguated picker label pattern):

// Build rows that always map back uniquely.
let mut entries: Vec<(String, String, String)> = vec![]; // (label, provider_name, model_id)
for (meta, _ptype) in &all {
    for m in models_for_meta {
        let mut label = format!("{}  ▸  {}", meta.display_name, m);
        // Ensure uniqueness even if display_name + model collide across providers.
        if collides_somehow { 
            label.push_str(&format!("  (provider:{})", meta.name));
        }
        entries.push((label, meta.name.clone(), m));
    }
}

Apply these rules anywhere you normalize model/provider identifiers or convert between internal ids and user-facing names, so naming stays consistent, lookups remain correct, and selections can’t mis-route.


Enforce Policy Parity

When changing CI routing/guardrails (workflows, CODEOWNERS, rulesets), ensure the policy intent is still enforced in the same way.

Standard 1) Never replace enforced approvals with “request reviewers”: reviewer requests do not block merges. If your repo relies on require_code_owner_review: true, keep CODEOWNERS entries (or explicitly update the ruleset) rather than assuming the workflow will gate merges. 2) Eliminate config drift: any canonical routing list (e.g., maintainer allow/skip lists used by scripts) must not be duplicated across script + workflow YAML without a sync check. 3) Ensure routing logic is tested in CI: if a test file exists but is not included in the workflow’s test selection list, CI coverage is illusory—add it to the workflow selector.

Practical implementation

Example (workflow/YAML config sync test pattern)

import fs from 'node:fs';
import yaml from 'js-yaml';

// Canonical list lives in one place (e.g., imported from the routing script)
const MAINTAINERS = ['wenshao', 'tanzhenxin', 'yiliang114', 'LaZzyMan'];

const workflow = fs.readFileSync('.github/workflows/ci.yml', 'utf8');
const doc = yaml.load(workflow);

// TODO: locate the step/yaml expression that defines the maintainer skip-list
// and extract it into `skipList` deterministically.
const skipList = /* parse from doc */ [];

if (JSON.stringify(skipList.sort()) !== JSON.stringify([...MAINTAINERS].sort())) {
  throw new Error('CI workflow maintainer skip-list is out of sync with canonical MAINTAINERS');
}

Checklist before merging changes to routing/guardrails


Null-safe value handling

Make null/undefined (and “invalid/unknown”) states explicit and prevent them from flowing into non-null/non-optional operations.

Apply these rules: 1) Enforce compiler null safety: enable strictNullChecks so the typechecker blocks x?.foo()/x.foo() on string | null-like values. 2) Guard before method calls: if a value can be null/undefined, check it before calling string/array methods. 3) Align conversion boundaries: parsing/normalization that accepts unknown must either:

Example (null guard + explicit fallback):

function getErrorPrefix(err: string | null | undefined) {
  if (!err) return null; // handles ''/null/undefined per your policy
  return err.startsWith('No API key found') ? err : null;
}

const constrainedStrict = supportsStrictMode
  ? resolveJsonSchemaStrictSampling(tool, true)
  : undefined; // explicit
const strict = constrainedStrict ?? defaultStrict; // only applies when constrainedStrict is undefined

This prevents unsafe member access, accidental propagation of undefined/invalid values across typed boundaries, and confusing fallback behavior.


Test regex alternations

When unit tests depend on filename/path classification via regex (e.g., routing maintainers, detecting test files), add explicit test cases that exercise every alternation token and mapping entry in the regex/table. Uncovered alternations can fail silently if someone introduces a typo or refactors part of the pattern.

Apply this by:

Example (illustrative unit tests):

it('treats .spec. as test-only', () => {
  const result = classify(['packages/core/src/tools/grep.spec.ts'], 'someone');
  assert.equal(result.reviewers.length, 0);
  assert.match(result.reason, /test-only/);
});

it('routes services compaction paths to the right domain expert', () => {
  const result = classify(['packages/core/src/services/compactionService.ts'], 'someone');
  assert.ok(result.reviewers.includes('LaZzyMan'));
});

Explicit Null Semantics

When handling optional/nullable values in TypeScript/React, make “unset/default” distinct from “legitimate empty/zero” and avoid truthiness-based guards.

Apply: 1) Use a dedicated sentinel for “never set”

Example (sentinel + explicit checks):

// Sentinel models “never set” separately from a real 0.
const [navExpandedWidth, setNavExpandedWidth] = useState<number | null>(null);

useEffect(() => {
  window.electron.getSetting('navExpandedWidth').then((stored: number | null) => {
    if (stored === null) {
      // keep component default
      return;
    }

    // stored === 0 is a legitimate explicit value, not “unset”
    setNavExpandedWidth(stored);
  });
}, []);

// Explicit optional check (don’t rely on truthiness)
const initialMessage = editedMessage !== undefined
  ? { msg: editedMessage, images: [] }
  : undefined;

This prevents bugs where guards accidentally skip applying valid persisted values (e.g., 0) or mis-handle empty-but-present content (e.g., '').


Context-aware React State

In React components, make UI state transitions and DOM identity depend on the current rendered context (route/view/filter) and the current component instance. This prevents stale navigation, incorrect optimistic updates, and broken label/control associations.

Apply this as a rule of thumb:

Example patterns:

// 1) Route-aware transition (concept)
function leaveRouteIfCurrent(currentId: string, nextPath = '/') {
  if (getCurrentOpenSessionId() === currentId) navigate(nextPath);
}

// 2) Filter-aware optimistic update
const handleToggleArchive = async (session: SessionListItem) => {
  const isArchived = !!session.archivedAt;
  setSessions(prev => {
    if (activeFilter === 'all') {
      // keep row; it still matches
      return prev.map(s => (s.id === session.id ? { ...s, archivedAt: isArchived ? null : new Date().toISOString() } : s));
    }
    // active/archived views: toggle may move it out of scope
    return prev.filter(s => s.id !== session.id);
  });
};

// 3) Instance-unique label/control pairing
function ParameterInputModal({ parameters }: { parameters: { key: string }[] }) {
  const reactId = React.useId();
  const fieldId = (key: string) => `${reactId}-${key}`;

  return (
    <div>
      {parameters.map((param) => (
        <div key={param.key}>
          <label htmlFor={fieldId(param.key)}>{param.key}</label>
          <input id={fieldId(param.key)} />
        </div>
      ))}
    </div>
  );
}

Use this checklist whenever you change data that affects (1) what’s open on the screen, (2) what’s included in the current list/filter, or (3) how inputs are labeled/identified in the DOM.


Minimize Resource Churn

Prefer designs that avoid unnecessary resource usage—especially filesystem churn and redundant persistence/reload.

Example (OS temp dir for temporary work):

import { mkdtemp, rm } from "node:fs/promises";
import os from "node:os";
import { join } from "node:path";

// Use system temp root to avoid accumulating data under a home directory.
const tempRoot = await mkdtemp(join(os.tmpdir(), "agent-"));
try {
  // ... write/edit temp files ...
} finally {
  // Ensure cleanup even if OS doesn’t immediately collect.
  await rm(tempRoot, { recursive: true, force: true });
}

Example (settings update pattern):


Respect config precedence

When configuration can vary by user/environment, resolve it deterministically (following documented precedence), keep it configurable instead of hardcoded, and apply it dynamically if it may change at runtime.

Practical rules:

Example (dynamic blockImages handling):

// Bad: captures blockImages once at session creation
// const convertToLlmWithBlockImages = blockImages ? filteredConvertToLlm : convertToLlm;

// Good: decide per-use from session manager
function makeConvertToLlm(sessionManager: { getBlockImages(): boolean }) {
  return async function convertToLlm(...args: unknown[]) {
    const shouldBlock = sessionManager.getBlockImages();
    if (shouldBlock) return convertToLlmFilteredImages(...args);
    return convertToLlmUnfilteredImages(...args);
  };
}

Following this standard prevents stale configuration behavior, reduces deployment brittleness, and makes feature flags and user settings reliably predictable.


Spec-Driven Parsing

For any code that parses/normalizes strings or aggregates structured events, require deterministic, complete, and bounded logic:

Example (quote-aware normalization pattern):

export function normalizeNulRedirects(command: string): string {
  if (process.platform !== "win32") return command;

  let out = "";
  let inSingle = false;
  let inDouble = false;

  for (let i = 0; i < command.length; i++) {
    const ch = command[i];

    if (ch === "'" && !inDouble) inSingle = !inSingle;
    else if (ch === '"' && !inSingle) {
      const escaped = (() => {
        let bs = 0;
        for (let k = i - 1; k >= 0 && command[k] === "\\"; k--) bs++;
        return bs % 2 === 1;
      })();
      if (!escaped) inDouble = !inDouble;
    }

    out += ch;

    // Only rewrite redirects when not inside quotes (bounded, deterministic)
    // if (!inSingle && !inDouble && matchesNulRedirectAt(i, command)) { ... }
  }

  return out;
}

Apply the same standard to metrics aggregation: ensure guards don’t accidentally skip new contributors (e.g., treat any entry type with usage as a candidate for token/cost accumulation).


Explicit failure state machine

When code has multi-step lifecycle operations (spawn/register/sync/stop) or user/config-driven behavior, make failures explicit and recoverable: model the lifecycle with a small state machine, track which resources were acquired so teardown can always run safely in reverse, and degrade gracefully with validated fallbacks and user-visible diagnostics. Also keep retry/error event schemas unambiguous so monitoring and recovery logic can reliably interpret what happened.

Apply it like this:

Example (pattern):

type State = 'starting' | 'online' | 'stopping' | 'stopped' | 'error';

class RpcLifecycle {
  private state: State = 'stopped';
  private acquired: {
    rpcProcess?: { stop(): Promise<void> };
    sessionId?: string;
    radiusId?: string;
  } = {};

  async start() {
    this.state = 'starting';
    try {
      // 1) acquire resources step-by-step
      this.acquired.rpcProcess = await this.startRpc();
      this.acquired.sessionId = await this.syncSession();
      this.acquired.radiusId = await this.registerRadius();

      this.state = 'online';
    } catch (e) {
      await this.cleanupBestEffort();
      this.state = 'error';
      throw e;
    }
  }

  private async cleanupBestEffort() {
    // reverse order of acquisition
    if (this.acquired.radiusId) await this.unregisterRadiusBestEffort(this.acquired.radiusId);
    if (this.acquired.sessionId) await this.unsyncSessionBestEffort(this.acquired.sessionId);
    if (this.acquired.rpcProcess) await this.acquired.rpcProcess.stop().catch(() => {});

    this.acquired = {};
  }
}

Collision-Safe Identifier Mapping

Treat every identifier (tool name, command name, provider slug, theme name, thread key) as a runtime contract: you must generate, transform, and resolve it consistently, and preserve an unambiguous mapping between any emitted/sanitized UI value and the backend identity.

Apply these rules: 1) Use a single source-of-truth canonical form for comparisons/dispatch.

Example pattern (opaque UI token → canonical dispatch):

# UI: show truncated label, dispatch uses stable token
items = {token: canonical_name}

# When rendering select options
for token, canonical in list(items.items())[:24]:
    select_option = discord.SelectOption(
        label=canonical[:100],  # display-only truncation
        value=token,            # dispatched identity
    )

# On selection
token = interaction.data["values"][0]
canonical = items[token]
await dispatch(f"/{canonical}")

Follow the same separation for Telegram menus, tool registries, and provider/theme resolution: emitted names/values must be mapped back to the exact canonical identifier used for backend resolution, and collisions must be rejected early rather than “best-effort” resolved later.


Use Null-Safe Config Reads

Treat every potentially-null/nullable config subsection and external payload field as untrusted: normalize it before accessing deeper keys or calling methods.

Rules

Example

def pick_language(stt_config: dict) -> str | None:
    stt_config = stt_config or {}
    groq_cfg = stt_config.get("groq") or {}          # handles groq: null
    local_cfg = stt_config.get("local") or {}
    return groq_cfg.get("language") or local_cfg.get("language")

def handle_matrix_location(payload: dict) -> None:
    geo_uri = payload.get("geo_uri")
    if not isinstance(geo_uri, str):
        return  # or safely log/drop
    if geo_uri.startswith("geo:"):
        ...

This prevents crashes like AttributeError: 'NoneType' object has no attribute 'get' and AttributeError/TypeError from calling string methods on non-strings.


Config contract consistency

Apply a “configuration as a contract” standard: when behavior depends on environment/profile/feature flags (remote vs local, active management profile, accessibility mode, client/server timing), wire that configuration into all relevant code paths and keep its semantics consistent across layers.

Checklist

Example patterns


Wire Contract Enforcement

External API boundaries must enforce the final wire contract: only supported parameters, only provider-accepted content shapes, and only schema-valid payloads.

Apply these rules in API-related code (tool dispatchers, transport builders, and request serializers):

1) Filter/allowlist request parameters at every outbound boundary

2) Validate the serialized “on-the-wire” message shape, not the internal shape

3) Keep JSON schemas consistent with runtime payload contracts

4) Centralize normalization that drives external protocol behavior

Example (parameter/body allowlist + wire-shape sanitation pattern):

# 1) Boundary allowlist for provider JSON body
WIRE_FIELDS = {"model", "input", "response_format", "temperature", "top_p"}

def build_wire_body(api_kwargs: dict) -> dict:
    body = {k: v for k, v in (api_kwargs or {}).items() if k in WIRE_FIELDS}
    # never include SDK-only controls (extra_headers/extra_body/timeout/stream)
    return body

# 2) Final on-the-wire message sanitizer (after all transforms)

def sanitize_wire_messages(messages: list[dict]) -> list[dict]:
    cleaned = []
    for m in messages:
        if m.get("role") == "assistant" and m.get("content") in (None, "", []) and not m.get("tool_calls"):
            # only drop when it is truly empty on the wire
            continue
        cleaned.append(m)
    # TODO: optionally repair role adjacency if you dropped a turn
    return cleaned

Team standard for reviews: if a change touches request building, serialization, tool schemas, or codec/format selection, reviewers should explicitly verify (a) unknown kwargs aren’t forwarded, (b) payloads are schema-valid, and (c) the final serialized wire representation matches what the external service accepts.


Config.yaml First Policy

Behavioral configuration must be owned by config.yaml (and documented), while environment variables must be limited to secrets or internal backward-compatibility bridges. Also ensure any filesystem default paths are profile-safe via get_hermes_home().

Apply this standard: 1) Behavioral knobs → config.yaml

2) **Env vars are allowed only for:

3) Profile-safe defaults

Code sketch (config-first + profile-safe default + env only as compat):

import os
from pathlib import Path
from hermes_constants import get_hermes_home

_TRUEY = {"1","true","on","yes"}

def _truthy(v: str) -> bool:
    return v.strip().lower() in _TRUEY

def enabled() -> bool:
    # Internal compat bridge (optional): env overrides should not be the primary surface.
    env = os.environ.get("HERMES_SOME_FEATURE", "").strip().lower()
    if env:
        return _truthy(env)

    # Primary: config.yaml (load once via existing config helpers)
    from hermes_cli.config import load_config
    cfg = load_config() or {}
    return _truthy(str((cfg.get("agent", {}) or {}).get("some_feature", {}).get("enabled", False)))

def sink_path() -> str:
    # Profile-safe default
    default = get_hermes_home() / "logs" / "feature.log"

    # Optional compat env override for service managers
    override = os.environ.get("HERMES_SOME_FEATURE_FILE", "").strip()
    return str(Path(override).expanduser()) if override else str(default)

If you’re about to introduce a new HERMES_* env var for behavior, stop and ask: “Is this truly a secret or only internal compat?” If it’s user-facing, route it through config.yaml instead.


Generation-guarded async side effects

When async work can overlap (navigation changes, optimistic updates, multiple handler invocations, or speech interruption), treat post-await mutations as conditional on the original intent. Capture (1) the state/identity you’re operating on and (2) a monotonically increasing generation/token before any await or long-running step. Only apply success/failure/rollback when the token still matches the latest value; otherwise discard the completion.

Also, ensure that “normal completion” paths (e.g., a finally that re-arms listening) are skipped when an interrupt/cancel occurred; guard them with the same interruption flag/token.

Practical pattern:

let refreshGen = 0

async function refresh() {
  const gen = ++refreshGen
  const requestedBoard = $kanbanActiveBoard.get() // identity snapshot

  try {
    const next = await getKanbanBoard(requestedBoard)

    // Discard stale response
    if (gen !== refreshGen) return

    $kanbanBoard.set(next)
  } catch (e) {
    if (gen !== refreshGen) return
    $kanbanBoardError.set(String(e))
  }
}

async function moveOptimistic(taskId: string, targetStatus: string) {
  const gen = ++moveGen
  const boardAtStart = $kanbanBoard.get() // snapshot identity

  $kanbanBoard.set(applyMove(boardAtStart, taskId, targetStatus))

  try {
    await updateKanbanTask(taskId, { status: targetStatus }, $kanbanActiveBoard.get())
    if (gen !== moveGen) return
    await refreshFromServer(boardAtStart)
  } catch (e) {
    if (gen !== moveGen) return
    $kanbanBoard.set(boardAtStart) // guarded rollback
    $kanbanBoardError.set(parseError(e))
  }
}

Apply this rule whenever:

Result: late/stale completions stop overwriting newer intent, and both success and error paths become race-safe.


Enforce API Contracts

Client and UI code must explicitly follow the real API/component contract—both for what state transitions are allowed and which side effects/transport paths are actually executed.

Apply this by:

Example pattern for transition gating:

// pseudo: fetch/derive allowed destinations for the client
const allowed = await api.getAllowedKanbanTransitions(taskId)

function onDrop(toStatus: KanbanStatus) {
  if (!allowed.includes(toStatus)) return // backend will reject; avoid optimistic move

  // then call backend and update UI
  await api.updateKanbanTask(taskId, { status: toStatus })
  await refreshBoard()
}

Outcome: fewer “optimistic” failures, fewer integration drift bugs (wrong transport), and predictable behavior when APIs/components have non-cancelable lifecycle hooks.


Integration tests for focus

When behavior depends on library primitives (e.g., Radix) and real browser focus/pointer flows (including document.body portals), unit tests that reimplement internal handlers are not enough. Write tests that render the actual component tree and assert user-observable outcomes.

Apply this standard:

Example pattern (tooltip cancellation):

// Pseudocode: render actual TooltipPrimitive-based component
render(
  <TooltipRoot /* real component */>
    <TooltipTrigger asChild>
      <button>Tip</button>
    </TooltipTrigger>
    <TooltipContent>...</TooltipContent>
  </TooltipRoot>
)

// Mouse/focus path should NOT open
userEvent.click(screen.getByRole('button', { name: /tip/i }))
expect(screen.queryByText('...')).not.toBeInTheDocument()

// Keyboard focus path SHOULD open
screen.getByRole('button', { name: /tip/i }).focus()
expect(screen.getByText('...')).toBeInTheDocument()

This ensures the test verifies the real cancellation mechanism and prevents regressions involving focus and portal DOM behavior.


Secure Rendering And Fetch

All untrusted inputs must be hardened at their security boundaries: (1) for network calls, validate the destination on every redirect hop (and ideally after DNS resolution), and (2) for any rendered or embedded output, sanitize/encode for the exact output context to prevent XSS and script-breaking.

Apply this standard:

Example pattern for safe redirects (sketch):

async function fetchWithValidatedRedirects(initialUrl, validateHop) {
  let url = initialUrl;
  for (let hops = 0; hops < 5; hops++) {
    validateHop(url); // block private/loopback/reserved + enforce allowlist
    const res = await fetch(url, { redirect: 'manual' });
    if (res.status < 300 || res.status >= 400) return res;
    const loc = res.headers.get('location');
    if (!loc) return res;
    url = new URL(loc, url).href;
  }
  throw new Error('Too many redirects');
}

And for JSON-in-script embedding, ensure you escape for script context (e.g., replace </script> with <\/script> before injecting).


Profile-scoped API routing

All profile-scoped routing must use the mechanism your IPC/bridge/router actually consumes (e.g., an outer request field or a ...profileScoped() wrapper). Do not attempt to “scope” routing by placing profile inside nested request bodies that the backend simply binds/forwards, or by passing profile only as a query param unless the bridge explicitly treats it as a routing key.

Apply the rule:

Example pattern:

return window.hermesDesktop.api<Response>({
  ...profileScoped(), // routing key understood by the bridge/router
  path: '/api/audio/speak',
  method: 'POST',
  body: { text }, // backend binding; don’t rely on body nesting for routing
});

Precise Matching Rules

When implementing parsing/classification logic, treat the input grammar as a contract: (1) constrain pattern matches to the intended envelope/boundaries/character sets (avoid prefix/superset regexes and overly broad Unicode ranges), (2) ensure every computed signal/metric is actually used in the final decision, and (3) add targeted regression tests for each boundary/grammar edge.

Apply:

Example (grammar-constrained marker stripping):

import re

def strip_asr_envelope(text: str) -> str:
    # Only remove the Qwen-style start-anchored envelope, not any occurrence.
    m = re.match(r"^language\s+.*?<asr_text>", text, flags=re.IGNORECASE | re.DOTALL)
    if not m:
        return text
    # Remove the first envelope marker then keep the rest.
    return text.replace(m.group(0), "", 1).strip()

Checklist for PRs in this area:


When a security-related skill or script causes any external effect (sending data to third parties, spending funds, changing auth, or modifying security config), the implementation and docs must be explicit about (a) trust boundaries, (b) user-controlled/bounded authorization, and (c) safe, targeted, verifiable changes.

Apply this standard:

Example patterns (illustrative):

1) Don’t overclaim trust boundary

Wrong: “Redacts PII before it reaches your LLM provider.”
Right: “Hosted transformation: the skill sends input text to TrustBoost for processing, then returns sanitized output.”

2) Require bounded user approval before external spend

Before executing a swap: show {wallet, assets, amount, trigger, expiry} and require explicit user confirmation.
Reject or pause if running from a cron/unattended path without an approval token/state.

3) Use directive-scoped config edits

# Instead of rewriting any '* yes' line, edit only the intended directive.
# Then verify with sshd -T or grep before reloading.
sudoedit /etc/ssh/sshd_config
# Verify: sshd -T | grep -E 'passwordauthentication|permitrootlogin'
# Reload only after verification.

4) Firewall enable with lockout-safe rule preservation

Before ufw enable: ensure existing SSH allow rule is present (source/port as configured), then enable.
Never enable default-deny without preserving active SSH management access.

Outcome: fewer security “false assurances,” fewer accidental lockouts, and no silent/unauthorized irreversible actions.


Enforce Security End-to-End

When implementing security controls, treat them as end-to-end requirements across all navigation paths and all auth/transport interfaces. Two common failure modes are (1) hidden/aux renderer windows that still allow unintended credential/WebAuthn UI via a fallback path, and (2) security-sensitive flows that accept security context but some callers pass plain public URLs, causing bypass of the intended secure routing/transport.

Apply this standard:

Example pattern (renderer + typed IPC):

// Renderer hardening: avoid a fallback that can show credential/WebAuthn UI.
try {
  window.webContents.setWindowOpenHandler(() => ({ action: 'deny' }));
  window.webContents.setWebRTCIPHandlingPolicy('disable_non_proxied_udp');

  // Ensure the session/policy for the title/hidden navigation suppresses
  // credential/WebAuthn UI before any navigation occurs.
  // (Apply/remove fallback paths so arbitrary public pages cannot slip in.)
} catch (e) {
  // Fail closed or log and abort navigation.
}
// IPC/auth: always pass the fully expressive payload to prevent bypass.
// Prefer object-based inputs so transport selection can’t be derived from a public URL string.
await ipcRenderer.invoke('probeConnectionConfig', {
  remoteUrl: config.remoteUrl,
  // include the fields needed for effective secure routing
  // (e.g., local_mtls_proxy / loopback transport metadata)
});

Result: security behavior stays consistent even during reauth/boot-failure handling and during unusual navigation/fallback scenarios.


Failure-Safe State Handling

When error handling affects control-flow invariants (dedupe keys, stale-session guards, correctness checks), make failures safe and reversible:

Example pattern (dedupe cleanup):

const dedupeKey = imageBlobDedupeKey(blob, data)
if (rememberRecentImageBlobPaste(refs, dedupeKey)) return
try {
  const ok = await saveImageBuffer(...)
  if (!ok) throw new Error('save failed')
} catch (e) {
  // restore invariant so immediate retry can attach
  forgetRecentImageBlobPaste(refs, dedupeKey)
  throw e
}

Example pattern (guard integrity):

try {
  const remote = await getSessionMessages(guardStoredId /* required routing */)
  // decide based on remote
} catch (e) {
  // safe default: block + refresh rather than submit with stale context
  await refreshSessionContext()
  return
}

Contract-first API design

When designing or consuming client/server APIs, keep the contract explicit and prevent duplicate logic/types from drifting.

Apply this standard:

Example patterns:


Fail Safe Input Handling

When processing security-relevant external inputs (URIs/hosts, file paths/content, auth tokens, and tool-call metadata), validate and constrain early, then ensure failure modes are non-recoverable in ways that could cause retries or duplicate effects.

Apply this pattern: 1) Validate trust boundaries

2) Constrain filesystem operations

3) Make tool execution idempotent and policy-deny non-retryable

4) Use safe auth handling

Example (pattern sketch):

// 1) Constant-time token check
fn tokens_equal_ct(expected: &str, actual: &str) -> bool {
    expected.as_bytes().ct_eq(actual.as_bytes()).into()
}

// 2) Bounded read after regular-file validation
const MAX: u64 = 1024 * 1024;
fn read_bounded(mut f: std::fs::File) -> Result<Vec<u8>, anyhow::Error> {
    let mut buf = Vec::new();
    f.take(MAX + 1).read_to_end(&mut buf)?;
    if (buf.len() as u64) > MAX {
        anyhow::bail!("file exceeds limit");
    }
    Ok(buf)
}

// 3) Policy denial should not invite retries
// Prefer a “final tool outcome” representation over returning an MCP Err
// that could trigger a retry path.
fn deny_tool_call_final(plugin: &str, reason: &str) -> ToolCallResult {
    ToolCallResult { is_error: true, final_message: format!("blocked by {plugin}: {reason}") }
}

Net: validate/normalize untrusted inputs at the boundary, strictly limit side effects (IO size/type, tool execution), use constant-time auth comparisons, and make authorization/policy denials non-retryable to prevent retry storms or duplicate execution.


Assert behavior; inject inputs

When code changes affect what the app sends (RPC/HTTP payloads/options) or what the app decides based on the environment, add targeted tests that (1) assert the exact externally observable behavior and (2) make the inputs deterministic.

Practical rules:

Example (Vitest-style contract assertion):

import { describe, it, expect, vi } from 'vitest'
import { renderHook } from '@testing-library/react'
import { useSessionLifecycle } from './useSessionLifecycle'

vi.mock('../rpc', () => ({
  rpc: vi.fn(),
}))

it('sends launch cwd in session.create payload', async () => {
  process.env.HERMES_CWD = '/expected/launch/dir'

  const { rpc } = await import('../rpc')
  ;(rpc as unknown as ReturnType<typeof vi.fn>).mockResolvedValue({ /* ... */ })

  const { result } = renderHook(() =>
    useSessionLifecycle({ /* required opts */ })
  )

  await result.current.newSession(/* args that lead to startNewSession */)

  expect(rpc).toHaveBeenCalledWith('session.create', expect.objectContaining({
    cwd: '/expected/launch/dir',
  }))
})

Apply the same pattern to wrapper options (assert timeoutMs) and to environment detection (inject sysfs/DMI inputs rather than reading the host).


Collision-Safe Keys

When an algorithm derives a decision key (dedupe) or signal (parsed config) that can suppress/merge data, make that derivation collision- and normalization-safe, and define precedence explicitly.

Dedupe keys (avoid collision-based suppression):

import { createHash } from 'node:crypto'

export function imageDedupeKey(blob: Blob, data: Uint8Array): string {
  // Collision-resistant key: hash actual bytes (optionally include size)
  const digest = createHash('sha256').update(data).digest('hex')
  return `${blob.size}|${digest}`
}

Parsed/merged config (normalize + deterministic precedence):

function hasAnyInheritedProxy(env: Record<string, string>, family: 'http'|'https') {
  const keys = [
    `${family}_proxy`,
    `${family.toUpperCase()}_PROXY`
  ]
  return keys.some(k => (env[k] ?? '').length > 0)
}

Why: these patterns prevent subtle, hard-to-debug behavior like “silent suppression” from hash collisions and inconsistent merging from incomplete normalization/precedence handling.


Preserve signing entitlements

On macOS, treat re-signing (including ad-hoc re-sign after quarantine stripping) as a security-sensitive operation: preserve the app’s entitlements for the main bundle and any helper apps. Otherwise, macOS TCC access (mic/screen audio) may break or continuously prompt because the re-signed artifacts no longer carry the expected entitlements. Also ensure every packaging/update path uses the same entitlement-preserving logic.

Practical rule:

Example (bash pattern):

# Only for macOS ad-hoc path; skip when real signing is configured.
if [ "$OS" = "macos" ] && [ -z "${CSC_LINK:-}" ] && [ -z "${APPLE_SIGNING_IDENTITY:-}" ] && command -v codesign >/dev/null 2>&1; then
  xattr -cr "$app" 2>/dev/null || true

  main_entitlements="$desktop_dir/electron/entitlements.mac.plist"
  helper_entitlements="$desktop_dir/electron/entitlements.mac.inherit.plist"

  if [ -f "$main_entitlements" ] && [ -f "$helper_entitlements" ]; then
    # main bundle
    codesign --force --deep --sign - --entitlements "$main_entitlements" "$app" >/dev/null 2>&1 || true

    # helper apps inside the bundle
    while IFS= read -r -d '' helper_app; do
      codesign --force --deep --sign - --entitlements "$helper_entitlements" "$helper_app" >/dev/null 2>&1 || true
    done < <(find "$app" -type d -name "*.app" -print0)
  fi
fi

Apply this pattern consistently across all build/update routes so security-relevant signing behavior can’t drift.


Robust error paths

When handling errors, ensure you don’t (1) mask the original failure, (2) violate the intended timeout/retry/cleanup boundaries, or (3) make recovery decisions without explicit evidence.

Standards 1) Cleanup must never throw / must not mask the real exception

   class Runner:
       def __init__(self):
           self._tts_playback_thread = None  # initialize for finally safety

       def run(self):
           try:
               ...
           finally:
               t = getattr(self, "_tts_playback_thread", None)
               if t and t.is_alive():
                   t.join(timeout=5)

2) Honor deadlines everywhere (especially after streaming/pipes hit EOF)

3) Cleanup must cover the full resource scope

4) Recovery decisions must be evidence-gated

5) Error ordering: validate ‘not found’ before operations that can raise 400/validation/unknown-task errors

6) Preserve best-effort behavior where it was intentional

Applying this standard will prevent masked exceptions, unblock deterministic cleanup/timeout behavior, and keep recovery logic correct and testable.


Guard Async State Updates

When multiple async operations can be in flight (polling, optimistic mutations, React effects, REST hydration + live WebSocket deltas), older responses may arrive last and overwrite newer state. Standardize a pattern that makes each async result apply only if it is still the current/owned operation.

Apply this rule:

Example pattern (generation-aware commit):

const requestGenRef = useRef(0)

const refresh = useCallback(async () => {
  const gen = ++requestGenRef.current
  try {
    const data = await getKanbanTasks()
    // Only the latest in-flight request may update state
    if (gen !== requestGenRef.current) return
    setTasks(Array.isArray(data.tasks) ? data.tasks : [])
  } catch (e) {
    if (gen !== requestGenRef.current) return
    notifyError(e)
  }
}, [])

Also guard by selection/ownership:

This prevents race-condition clobbering and makes state transitions deterministic under concurrency.


Canonical Identifier Semantics

When code maps or normalizes external identifiers (tool names, locale tags, etc.), it must preserve the identifier’s real semantics and use canonical names.

Standards

Example pattern (display-only normalization)

// Canonical external identifier (real MCP name)
type McpToolName = 'mcp__filesystem__write_file'

function displayTitle(toolName: McpToolName): string {
  // Safe display-only transformation; semantics preserved
  if (toolName === 'mcp__filesystem__write_file') return 'write_file'
  return toolName
}

Example anti-pattern (semantic-unsafe aliasing)

// ❌ Incorrect: Belarusian/Ukrainian/Kazakh tags mapped to Russian UI
const LOCALE_ALIASES: Record<string, 'ru'> = {
  be: 'ru',
  uk: 'ru',
  kk: 'ru'
}
// Fix by removing/correcting those mappings.

Localize configuration UI

In configuration/settings UI (including timezone, system defaults, and messaging), do not introduce or hardcode user-visible text. Always source strings from the appropriate i18n catalog/keys so all locales (e.g., desktop Japanese/Chinese) get consistent wording.

Apply this rule:

Example pattern (web):

// Good: use localized key
const label = t.common.messaging

// Avoid:
const label = 'Messaging' // forces English

Example pattern (component string reuse):

// Good: pull “System default” and related hints from i18n
const systemDefaultText = t.config.systemDefault

Lock and Retry Rules

When coordinating async work with shared resources, (1) tie lock/flag state transitions to the real lifecycle of the work (e.g., confirmed detached handoff or confirmed error) rather than to generic function scope, and (2) treat resource contention as transient by using bounded retry + backoff for cleanup/claims.

Apply this in two parts:

1) Lock lifecycle: clear only when it’s actually safe

Example pattern (JS):

async function applyUpdates(opts = {}) {
  // ... acquire lock: updateInFlight = true
  try {
    const { ok, handedOff, updater } = await applyUpdatesPosixInApp();

    if (handedOff) {
      // Keep lock through quit dwell; do NOT clear via finally.
      return { ok, handedOff: true, updater };
    }

    // Non-handoff normal returns should release the lock.
    updateInFlight = false;
    return { ok, handedOff: false };
  } catch (err) {
    // Only on error: allow a retry by clearing lock.
    updateInFlight = false;
    throw err;
  }
}

2) Transient contention: bounded retry with backoff

Example pattern (PowerShell):

# Attempt in-place delete with retries for transient file locks
Remove-Item -Recurse -Force 'venv' -ErrorAction SilentlyContinue
$retryDelay = 2
for ($retry = 0; $retry -lt 3; $retry++) {
  if (-not (Test-Path 'venv')) { break }
  Write-Info "venv still locked (attempt $($retry + 1)/3); waiting ${retryDelay}s..."
  Start-Sleep -Seconds $retryDelay
  $retryDelay *= 2
}

Net effect: you prevent race windows from premature lock clearing and you make cleanup operations resilient to short-lived contention—both are essential in concurrent and lifecycle-sensitive code.


Stop Infinite Error Polling

In long-running UI workflows that poll (e.g., QR status, task panels, gateway actions), treat failures as transient vs permanent, and ensure your state transitions cannot loop forever.

Apply this standard:

Example pattern:

const [pollingEnabled, setPollingEnabled] = useState(true);
const [phase, setPhase] = useState<'idle'|'waiting'|'applying'>('idle');
const [sessionId, setSessionId] = useState<string|null>(null);

async function fetchStatus() {
  try {
    return await api.getWeixinOnboardingStatus(sessionId!);
  } catch (e: any) {
    // Permanent/unsupported: stop once
    if (e?.status === 404) {
      setPollingEnabled(false);
      setPhase('idle');
      setSessionId(null);
      // show unavailable UI / toast once
      return null;
    }
    throw e; // transient -> let retry logic handle
  }
}

useEffect(() => {
  if (!pollingEnabled || !sessionId || phase !== 'waiting') return;
  let cancelled = false;

  const tick = async () => {
    if (cancelled) return;
    const st = await fetchStatus();
    if (!st) return; // stopped/unavailable
    // ...update UI, schedule next poll...
  };

  const id = setTimeout(() => void tick(), 1500);
  return () => {
    cancelled = true;
    clearTimeout(id);
  };
}, [pollingEnabled, phase, sessionId]);

async function apply() {
  setPhase('applying');
  try {
    await api.applyWeixinOnboarding(sessionId!, {});
    // success path...
  } catch {
    // Critical failure: reset to break retry loop
    setPhase('idle');
    setSessionId(null);
  }
}

This prevents repeated error spam and eliminates auto-retry loops when the backend endpoint is unsupported or when a critical step fails.


Secure boundary enforcement

When code crosses security boundaries (HTTP auth, subprocess execution, or policy-driven external side effects), it must follow the established secure path and validate before acting.

Apply these rules consistently to reduce auth regressions (401/OAuth gating), injection risk, and inadvertent disclosure/side effects from policy mistakes.


Validate model limits

When integrating LLM providers, don’t assume the provider’s model spec equals what the specific API endpoint will actually accept. Enforce two checks in your model configuration: (1) set context_limit to a safe upper bound that matches the endpoint’s effective cap, and (2) restrict model selection to a curated allowlist of chat-capable models instead of auto-loading the full /v1/models catalog (which can include unsupported modalities).

Practical application:

Example (pattern):

{
  "api_key_env": "PROVIDER_API_KEY",
  "base_url": "https://api.provider.com/v1/chat/completions",
  "dynamic_models": false,
  "models": [
    { "name": "Chat-Model-A", "context_limit": 200000 },
    { "name": "Chat-Model-B", "context_limit": 64000 }
  ]
}

Accessible React State Handling

In React components and hooks, changes to focus/interaction state or derived UI state must preserve correct behavior for all users and reflect the actual semantic state transitions.

Apply this standard: 1) Interactive controls: ARIA + roving focus requires keyboard support

Example (tablist pattern):

function onTabKeyDown(e: React.KeyboardEvent, tabs: Tab[], currentId: string) {
  const idx = tabs.findIndex(t => t.id === currentId)
  const move = (nextIdx: number) => {
    const next = tabs[(nextIdx + tabs.length) % tabs.length]
    selectTab(next.id) // set active + update tabIndex
    focusTabButton(next.id) // optional: focus the newly selected tab button
  }

  switch (e.key) {
    case 'ArrowLeft': e.preventDefault(); move(idx - 1); break
    case 'ArrowRight': e.preventDefault(); move(idx + 1); break
    case 'Home': e.preventDefault(); move(0); break
    case 'End': e.preventDefault(); move(tabs.length - 1); break
  }
}

2) Hooks/effects: rerun on the semantic inputs, not just “session changes”

Example (separate locale-independent selection from locale-dependent text):

type PlaceholderSelection = { kind: 'new'|'followUp'; index: number }

function getPlaceholderText(sel: PlaceholderSelection, locale: string) {
  const templates = sel.kind === 'new' ? newTemplatesByLocale[locale] : followUpTemplatesByLocale[locale]
  return templates[sel.index]
}

// Keep sel stable; derive text from locale
const [sel, setSel] = useState<PlaceholderSelection>(() => ({ kind, index }))
const text = getPlaceholderText(sel, locale)

Net effect: keyboard-only users can operate interactive tab UI reliably, and hooks update derived text/state correctly when language or other semantic inputs change—without unintended rerolls or history resets.


Deterministic algorithm workflows

When you describe an algorithm (retrieval pipeline, scoring, ranking, etc.), ensure the implementation includes the complete promised workflow and produces deterministic outputs.

Apply this checklist:

Example pattern (scoring determinism):

from dataclasses import dataclass

@dataclass(frozen=True)
class Checks:
    ssh_root_login: bool
    open_ports: tuple[int, ...]   # ensure stable ordering
    updates_installed: bool

def score(checks: Checks) -> int:
    # Deterministic, explicit per-check points
    points = 0
    points += 25 if not checks.ssh_root_login else 0
    points += 25 if len(checks.open_ports) == 0 else max(0, 25 - 5*len(checks.open_ports))
    points += 20 if checks.updates_installed else 0
    # ... add the remaining dimensions with explicit point math
    return max(0, min(100, points))

def collect_read_only() -> Checks:
    # Only read system state; normalize ordering; no mutations
    open_ports = tuple(sorted(_read_open_ports()))
    return Checks(
        ssh_root_login=_read_ssh_root_login(),
        open_ports=open_ports,
        updates_installed=_read_updates_installed(),
    )

For retrieval workflows, use the same idea: document and implement every required step (index build, pass 1 retrieval, pass 2 expansion/retrieval, result merge, and the call site), or explicitly limit the documentation to the implemented subset.


Separate auth and routing

When using OpenAI-compatible providers/proxies, treat authentication and endpoint routing as separate concerns:

Example (proxy via OpenAI-compatible settings):

# Proxy root only (no trailing path)
export OPENAI_HOST="https://your-proxy.example.com"

# Path the proxy serves (ensure it matches, e.g., v1/chat/completions)
export OPENAI_BASE_PATH="/v1/chat/completions"

# Auth token used by the client
export OPENAI_API_KEY="$YOUR_KEY"

Practical troubleshooting:


Readable Maintainable Code

Write Rust code so its intent is clear at a glance and responsibilities are placed correctly.

Apply this checklist:

Example pattern for readability (intermediate variables + simplified conditions):

let requested_budget = thinking_budget_tokens(model_config);
let max_thinking_budget = max_tokens.saturating_sub(MIN_ANSWER_TOKENS);
let budget_tokens = requested_budget.min(max_thinking_budget);

if budget_tokens >= MIN_THINKING_BUDGET_TOKENS {
    // build the thinking config using budget_tokens
}

Canonical Model Capabilities

When integrating LLM providers/models, derive capability flags and limits from canonical model metadata (catalog) and apply deterministic compatibility rules with explicit fallbacks—avoid brittle name-based heuristics and keep user overrides authoritative.

Apply these practices:

Example pattern (resolve limits with canonical fallback while honoring user overrides):

pub fn with_catalog_provider_fallback(mut self, catalog_provider_id: &str) -> Self {
    let canonical = maybe_get_canonical_model(catalog_provider_id, &self.model_name);
    if let Some(c) = canonical {
        // only override when user didn’t set a real limit
        if self.context_limit.is_none() || self.context_limit == Some(0) {
            self.context_limit = Some(c.limit.context);
        }
        // cap to effective context (not the raw catalog context)
        if self.max_tokens.is_none() {
            let effective_ctx = self.context_limit.unwrap_or(c.limit.context);
            self.max_tokens = c.limit.output
                .filter(|&out| out < effective_ctx)
                .map(|out| out as i32);
        }
    }
    self
}

Secure extension install

When publishing extension/server install options (especially deep-links or Install buttons), default to a secure-by-default path: require explicit/manual installation for binary-first or otherwise security-sensitive extensions. Only enable an automated install/deeplink if the target is explicitly allowlisted.

Apply it like this:

Example (pattern):

{
  "id": "nika",
  "name": "Nika",
  "description": "...",
  "command": "nika mcp",
  "show_install_link": false
}

Then document manual install, e.g.:


Enforce auth preconditions

Security-sensitive state (e.g., creating/persisting a profile that assumes a working remote connection) must not be created when required authentication material is missing or invalid. If downstream token-auth/config saving will reject empty/placeholder tokens, block the flow up front or use a staged/OAuth flow so the local profile is only finalized after auth/config persistence succeeds. If you can’t guarantee that, roll back local changes when remote auth/config saving fails.

Example pattern (block or stage before creating):

async function createRemoteProfile(params: {
  backendMode: 'remote' | 'local';
  token?: string;
  /* ... */
}) {
  if (params.backendMode === 'remote') {
    const token = params.token?.trim();
    if (!token) {
      throw new Error('Token required for remote connection');
      // OR initiate OAuth/staged setup here and return.
    }

    // Only after token is present, persist remote config.
    await window.hermesDesktop?.saveConnectionConfig?.({
      mode: 'remote',
      token,
    });
  }

  // Create/finalize local profile only after remote config succeeds.
  await createProfileAndPersist();
}

Harden Packaged Inputs

Apply a production/packaged hardening rule: in release builds, only use trusted origins and trusted code/resources. Treat environment variables, URLs, and “implicit” host paths as untrusted inputs, and explicitly gate/validate them so they cannot redirect critical behavior.

How to apply:

Example pattern (combined):

// 1) Stable, non-file origin for packaged renderer
let packagedProtocolRegistered = false;
function registerPackagedRendererProtocol() {
  if (MAIN_WINDOW_VITE_DEV_SERVER_URL || packagedProtocolRegistered) return;
  session.fromPartition(GOOSE_SESSION_PARTITION).protocol.handle(
    PACKAGED_RENDERER_PROTOCOL,
    async (request) => {
      // Resolve to bundled resources only
      const resolved = resolvePackagedRendererPath(
        request.url,
        getPackagedRendererRoot()
      );
      if (!resolved) return new Response('Not found', { status: 404 });
      const data = await fs.readFile(resolved);
      return new Response(new Uint8Array(data), {
        headers: { 'Content-Type': rendererContentType(resolved) },
      });
    }
  );
  packagedProtocolRegistered = true;
}

function getAppUrl(): URL {
  if (MAIN_WINDOW_VITE_DEV_SERVER_URL) return new URL(MAIN_WINDOW_VITE_DEV_SERVER_URL);
  registerPackagedRendererProtocol();
  return packagedRendererUrl();
}

// 2) Reject env override in packaged builds
export function findGooseBinaryPath({ isPackaged, resourcesPath }: {
  isPackaged?: boolean;
  resourcesPath?: string;
} = {}): string {
  const envPath = process.env.GOOSE_BINARY;
  if (envPath) {
    if (isPackaged) {
      throw new Error('GOOSE_BINARY override is not allowed in packaged builds');
    }
    // dev/test: resolve & validate
    const resolved = path.resolve(envPath);
    if (existingFile(resolved)) return resolved;
    throw new Error('Invalid GOOSE_BINARY path');
  }

  // packaged: only use bundled resources
  const bundled = resourcesPath ? path.join(resourcesPath, 'bin', 'goose') : '';
  if (existingFile(bundled)) return bundled;
  throw new Error('Bundled goose binary not found');
}

Outcome: release behavior becomes deterministic and resistant to attacker-controlled origin or configuration inputs, reducing security risk while keeping dev/test ergonomics.


Unified configuration semantics

Coding standard: Centralize configuration/credential semantics and never “re-derive” them in multiple places. Read from the real sources (env/config and provider-specific runtime credential caches), preserve provider identity during legacy interop, and let canonical normalizers own final resolution.

Apply this as follows:

Example pattern (shared usable gate):

// Single source of truth used by both server + CLI
pub fn provider_is_usable(meta: &ProviderMetadata, provider_type: ProviderType) -> bool {
    // handle local override
    if meta.name == "local" { return true; }

    // OAuth/token-cache-backed providers must consult inventory/configured signals
    // (not just meta.config_keys)
    if meta.config_keys.iter().any(|k| k.oauth_flow) {
        return provider_inventory_configured(meta.name.as_str());
    }

    // For non-OAuth providers: require explicit config/secret presence (not only defaults)
    required_keys_all_present_and_secrets_real(meta)
}

Enforce Security Boundaries Early

Apply security controls at the controlling layer and before triggering any side effects.

Example pattern:

// (1) Correct effective sandbox policy at the controlling layer
iframe.setAttribute(
  'sandbox',
  sandbox.permissions || 'allow-scripts allow-same-origin allow-forms'
);

// (2) Early allowlist enforcement before backend side effects
const uri = new URL(link).searchParams.get('uri');
if (!uri) throw new Error('mcp deep link is missing the uri parameter');

// allowlist check MUST happen BEFORE discoverExtension
if (!isAllowedMcpUri(uri)) {
  throw new Error('Blocked MCP URI by allowlist');
}

const { data, error } = await discoverExtension({ body: { uri } });
// (defense in depth) optionally re-check resolved endpoint/host here

Use this as a review checklist for any code that: 1) constructs sandboxed browsing contexts, or 2) accepts URIs/deep links and performs discovery/network calls.


Deterministic Docs Pipelines

For CI/CD that builds/publishes documentation (or any release-time artifacts), ensure two things: 1) Correct trigger coverage: docs-only changes must run the docs build via an explicit workflow path (don’t assume upstream jobs will run). If you use paths-ignore to skip heavy pipelines on doc changes, add a separate workflow (or separate trigger) that fires on documentation/** so docs always get published. 2) Reproducible source fetching: when the workflow or docs install script clones external repos, pin to an immutable commit SHA (not a moving tag) so outputs can’t change unexpectedly.

Example (workflow trigger separation):

# docs-bundle.yml
on:
  workflow_call:
    inputs:
      force_build: { type: boolean }
  push:
    branches: [main, "release/*"]
    paths:
      - "documentation/**"
  workflow_dispatch:

Example (immutable pin in an installer script):

HERDR_SETUP=$(mktemp -d) && \
git clone https://github.com/modib/agent-toolkit.git "$HERDR_SETUP" && \
cd "$HERDR_SETUP" && \
git checkout bfe921c7608861c58ea37aac981b32eb3032915e

Idempotent Async Initialization

When async flows drive UI state (events, config reads, resume/load), never assume timing/order will be favorable. Make initialization idempotent and conditionally applied so missed/early events or late async completions can’t leave the UI stuck or clobber user intent.

Apply these rules: 1) Provide a “catch-up” path for state that may already be loaded.

2) Guard against out-of-order async updates.

Example pattern (session event + immediate catch-up):

const loadForSession = (id: string) => {
  // load extensions for id (idempotent)
};

const onLoaded = (event: Event) => {
  const targetSessionId = (event as CustomEvent<{ sessionId?: string }>).detail?.sessionId;
  if (targetSessionId !== sessionId) return;
  loadForSession(targetSessionId!);
};

window.addEventListener(AppEvents.SESSION_EXTENSIONS_LOADED, onLoaded);
// catch-up: don’t rely solely on whether the event already fired
loadForSession(sessionId);

Example pattern (async config read without clobbering user choice):

let userTouched = false;

// set userTouched = true in your dropdown onChange

const effortFromConfig = await readConfig('SOME_EFFORT_KEY');
if (effortFromConfig && !userTouched) {
  setEffort(effortFromConfig);
}

Keep “ordering hazards” (e.g., user actions during resume vs backend load) scoped or explicitly disabled unless you can key off a reliable in-progress signal; otherwise treat them as separate follow-ups to avoid mixing multiple concurrency risks in one change.


Intentful Comments And Limits

Add comments that explain why the code behaves as it does—especially for platform-specific/terminal/UI quirks—and explicitly document any partial implementation.

Apply this standard:

Example pattern:

// On Windows Terminal (including WSL), Ctrl+V is intercepted by the terminal.
const pasteKey = process.platform === "win32" ? "alt+v" : "ctrl+v";

// Wrap link text in OSC 8 hyperlink sequences for terminal click support.
const osc8Open = `\x1b]8;;${url}\x07`;
const osc8Close = `\x1b]8;;\x07`;
result += osc8Open + linkText + osc8Close;

// Limitation: only SGR is tracked for styling state.
// OSC 8 state isn’t tracked yet, so only the first segment is clickable.
// Follow-up: extend the ANSI/terminal wrapping logic to include OSC 8 boundaries.

Immutable Setup Pinning

When your tooling downloads/execut es external installers or scripts, treat both the source and the workspace as security-sensitive:

Example (bash):

set -euo pipefail

# 1) Immutable source pin
REPO_URL="https://github.com/modib/agent-toolkit.git"
PIN="v1.0.0"  # or better: a commit SHA

# 2) Unique workspace
WORKDIR="$(mktemp -d)"
trap 'rm -rf "$WORKDIR"' EXIT

git clone "$REPO_URL" "$WORKDIR/herdr-setup"
cd "$WORKDIR/herdr-setup"
git checkout "$PIN"

# Execute installer from the pinned content
bash "goose/plugins/herdr/install.sh"

Apply this standard to any build/install/automation steps that clone repos, download scripts, or run them from a working directory.


Explicit, Extensible APIs

When designing/adjusting API surfaces, ensure (1) consumers can clearly understand what they’re setting and what defaults apply, (2) implementation-only details don’t leak into public types, and (3) variant-specific behavior is routed through dedicated abstractions/resolvers rather than embedded special-cases.

Guidelines:

Example (options + explicit defaults + no internal leakage):

export interface AgentSessionOptions {
  source?: "interactive" | "rpc" | "extension"; // public, documented
}

export function createAgentSession(opts: AgentSessionOptions = {}) {
  const source = opts.source ?? "interactive";
  // ...
}

// Avoid embedding provider-specific branching in unrelated call paths:
function resolveBaseUrl(model: { provider: string; baseUrl: string }) {
  if (model.provider === "cloudflare") return resolveCloudflareBaseUrl(model);
  return model.baseUrl;
}

Apply this checklist whenever you modify exported types, request/response shapes, client interfaces, or any public function signatures that other teams/code depends on.


Reliable integration tests

Integration/E2E tests should be structured and isolated: use consistent fixture setup/teardown to avoid flakiness and leftover files, and organize higher-level tests using reusable helpers and known-good inputs/models.

Apply this standard:

Example (fixture + cleanup):

import { afterEach, describe, it, expect } from "vitest";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";

describe("some integration", () => {
  let tempDir: string;

  beforeEach(() => {
    tempDir = mkdtempSync(join(tmpdir(), "pi-test-"));
  });

  afterEach(() => {
    rmSync(tempDir, { recursive: true, force: true });
  });

  it("does the thing", () => {
    // use tempDir safely
    expect(tempDir).toBeTruthy();
  });
});

Example (provider-organized E2E/unit structure sketch):

describe("openrouter provider", () => {
  const knownGoodModel = "<provider-specific model>";

  // shared helper used by multiple subtests
  const runProviderTest = (input: unknown) => {/* call provider with knownGoodModel */};

  it("does X", async () => {
    const result = await runProviderTest({/* ... */});
    // assert
  });
});

Prefer cohesive modules

Keep the repository’s module structure and implementations cohesive and non-redundant.

Apply these rules:

Example (dedupe loaders by parameterizing the difference):

function loadSkillsFromDir(dir: string, source: SkillSource): Skill[] {
  // shared parsing + file scanning logic here
}

// instead of two nearly identical functions
const piSkills = loadSkillsFromDir(piDir, "pi");
const claudeSkills = loadSkillsFromDir(claudeDir, "claude");

Migration consistency rules

When changing config schemas, treat migrations as part of the API contract: migrations must be safe under partial/legacy states and must not cause read/write skew that overwrites migrated data.

Practical standard: 1) Backfill before cleanup: if legacy keys are being removed while the new structured block exists, first reconstruct any missing new keys needed to preserve user intent (e.g., active_provider), then delete legacy keys. 2) Prevent clobbering across read vs write: ensure the code path that reads values used to construct a write payload sees the same logical (post-migration) state, or explicitly preserve fields that the migration may have created. 3) Use runtime guards for legacy placeholders: if old entries used sentinel values, detect them during lookup/migration and correct behavior without requiring disk rewrites. 4) Split migrations by side effects, but keep behavior consistent: if load() intentionally does not persist provider migrations, then any logic that constructs persisted updates must account for that (e.g., preserve active provider fields after migration).

Example pattern for (2): preserve the migrated model only when updating the active provider; otherwise write a new empty/default model.

let model = if goose::config::get_active_provider(config)
    .as_deref()
    == Some(provider_name.as_str())
{
    config.get_goose_model().unwrap_or_default() // preserved for active provider
} else {
    String::new() // new provider
};

goose::config::set_provider_entry(
    config,
    &provider_name,
    &goose::config::ProviderEntry {
        enabled: true,
        model,
        configured: true,
    },
)?;

Apply this style whenever a migration changes where authoritative fields live (flat keys → structured blocks, sentinel fixes, etc.).


Harden Untrusted Inputs

When code uses externally influenced data (URLs, hostnames, user-provided strings, identifiers) across trust boundaries, treat it as hostile and apply layered defenses:

Example (network cap + safe client pattern):

import httpx

timeout = 5.0
max_size = 50 * 1024 * 1024  # 50MB

response = _get_ssrf_safe_client().get(image_source, timeout=timeout)
response.raise_for_status()

content_length = response.headers.get("content-length")
if content_length and int(content_length) > max_size:
    return None

buf = bytearray()
for chunk in response.iter_bytes():
    buf.extend(chunk)
    if len(buf) > max_size:
        return None

If you apply this standard consistently, you reduce SSRF and resource-exhaustion risk while also preventing unsafe rendering/templating behavior and avoiding “security bypass by suppression.”


Normalize security inputs

For any security-sensitive policy/matching logic (authZ/exec policies, allow/deny rules, pattern matching), always canonicalize the relevant inputs before matching, and ensure edge cases like absolute-path .. are handled safely to prevent bypass.

Apply:

Example pattern (self-contained):

fn normalize_path(value: &str) -> String {
    let raw = value.trim().replace('\\', "/");
    let absolute = raw.starts_with('/');

    let mut segs: Vec<&str> = Vec::new();
    for s in raw.split('/') {
        match s {
            "" | "." => {}
            ".." => {
                if !absolute {
                    // For relative paths, preserve leading ..
                    if segs.is_empty() || *segs.last().unwrap() == ".." {
                        segs.push(s);
                    } else {
                        segs.pop();
                    }
                } else {
                    // For absolute paths, clamp: `/../foo` -> `/foo`
                    if !segs.is_empty() && *segs.last().unwrap() != ".." {
                        segs.pop();
                    }
                }
            }
            _ => segs.push(s),
        }
    }

    let mut out = String::new();
    if absolute { out.push('/'); }
    out.push_str(&segs.join("/"));
    out
}

// Security regression test idea:
// assert!(!matches_policy("/src/**", normalize_path("/src/../secret.txt")));

This prevents attackers from exploiting normalization gaps to make /src/../secret.txt incorrectly match a /src/**-style rule.


Endpoint Auth Validation

For security-sensitive flows (WS/API, authenticated cloning, token/API-key auth), don’t rely on generic or heuristic validation.

Apply these rules: 1) Validate with explicit allow/deny semantics

2) Decide authorization/authZ at the destination handler

3) Add regression tests for both positive and negative cases

Minimal pattern to follow:

Example (illustrative):

@socketio_server.event
async def connect(sid, environ, _auth):
    with webapp.request_context(environ):
        origin_ok, reason = validate_ws_origin(environ)
        if not origin_ok:
            return False
        return True  # authorization/CSRF requirements enforced by the target handler
@pytest.mark.parametrize(
    "url,should_accept",
    [
        ("https://host/org/repo.git", True),
        ("git@host:org/repo.git", True),
        ("ssh://alice@host/org/repo.git", True),
        ("ssh://host/org/repo.git", False),
        ("javascript://host/org/repo.git", False),
    ],
)
def test_url_validation(url, should_accept):
    assert is_valid_clone_url(url) is should_accept

Null and Empty Handling

Apply a consistent null/empty handling pattern for configuration and user-provided values:

Example pattern:

import os

# 1) Empty env values should not silently fall back
base_url = os.environ.get("OLLAMA_BASE_URL", "http://localhost:11434/v1")
# If base_url is "", downstream will raise a clear configuration error.

# 2) Guard nullable/custom inputs
value = prompt_fn()  # may return None or ""
if value is None:
    # graceful exit / clear error
    raise ValueError("Missing model name")
model = value.strip()
if not model:
    raise ValueError("Please enter a model name.")

# 3) In tests, assert error behavior for None/empty cases

This prevents “quiet localhost” (or other misleading defaults) and ensures null/empty misconfigurations are visible, handled safely, and protected by test coverage.


Explicitly Initialize Inputs

Ensure every required value is explicitly initialized/propagated across both configuration variants and process boundaries. Do not rely on “it will be set implicitly” behavior—new fields or external inputs can end up effectively undefined/empty.

Example (theme variants):

pub struct UiTheme {
    pub header_bg: Color,
    pub footer_bg: Color,
    // ...
}

impl UiTheme {
    pub fn dark() -> Self {
        Self {
            header_bg: Color::from_rgb(0,0,0),
            footer_bg: Color::from_rgb(20,20,20), // set everywhere
        }
    }

    pub fn light() -> Self {
        Self {
            header_bg: Color::from_rgb(255,255,255),
            footer_bg: Color::from_rgb(235,235,235), // set everywhere
        }
    }
}

Example (external input):

// Prefer passing the value in the exact parameter/variable form the command expects,
// rather than assuming redirected stdin will populate it.
let mut child = Command::new("powershell.exe")
    .args(["-NoProfile", "-Command", "Set-Clipboard -Value $input"]);
// ...then wire up $input per the intended mechanism and check the exit status.

Explicit Vercel Configuration

Treat Vercel deployment as a configuration contract: declare dependency/version/runtime settings explicitly and align your code layout with Vercel’s discovery (or override it explicitly).

Apply this standard:

1) Pick the correct dependency manifest/lock strategy

2) Declare supported Python versions

3) Ensure entrypoint discovery always works

4) Match framework “shape” to dependencies

5) Don’t make discovery depend on missing local env/config

Example pyproject.toml wiring:

[project]
requires-python = ">=3.12,<3.15"

[tool.vercel]
entrypoint = "api/main.py"

If Vercel reports entrypoint/callable not found, fix it by updating (a) the entrypoint path override, (b) conventional filename/path placement, and (c) top-level callable exports—then ensure any required env/settings are configured in Vercel.


Standardize Typed Errors

Use consistent, typed exceptions at the point of failure, with structured context, and never rely on unchecked/bypassed paths that convert errors into later crashes.

Apply:

Example (parsing boundary):

try:
    model_parse_json(MyModel, content)  # or TypeAdapter(...).validate_json
except (pydantic.ValidationError, json.JSONDecodeError) as exc:
    raise ContentFormatError(raw_content=content, error=exc) from exc

Example (polling boundary):

start = time.time()
while not until(response):
    if time.time() - start > TIMEOUT_SECS:
        raise OpenAIError("Polling timed out")
    response = self.request(...)[0]

This reduces mystery failures (like KeyError) and makes errors actionable for users and tests.


Secure Auth and Logging

Security-sensitive code must ensure (1) the correct auth path is used without accidental overrides, (2) sensitive auth material is never leaked in logs, and (3) auth-mode “sentinels” and provider handles can’t be accidentally triggered or misused.

Apply these rules:

Example (redact sensitive headers):

SENSITIVE_HEADERS = {"api-key", "authorization"}

def redact_sensitive_headers(headers: dict[str, str]) -> dict[str, str]:
    return {k: ("<redacted>" if k.lower() in SENSITIVE_HEADERS else v) for k, v in headers.items()}

Example (auth provider discipline):


Behavior-First Pytest Testing

Write tests that are pytest-native, high-signal, and behavior-focused.

Apply these rules:

Example (high-signal header behavior):

def test_auth_headers_set_before_request() -> None:
    client = OpenAI(base_url=base_url, api_key=lambda: "test_bearer_token")
    # Access/trigger the behavior you actually rely on at request time
    client.auth_headers  # should force/ensure correct Authorization value
    assert client.auth_headers["Authorization"] == "Bearer test_bearer_token"

Example (parametrize endpoints):

@pytest.mark.parametrize("path", ["/images/generations", "/chat/completions"])
def test_model_stripped_from_body(client: Client, path: str) -> None:
    req = client._build_request(
        FinalRequestOptions.construct(method="post", url=path, json_data={"model": "gpt-image-1-5", "prompt": "sunset"})
    )
    assert "model" not in req.json

Example (inline snapshot idea):

def test_schema_snapshot() -> None:
    schema = to_strict_json_schema(MyModel)
    assert schema == {"type": "object", "additionalProperties": False, "properties": {...}, "required": [...]}
    # or use an inline snapshot if your codebase supports it

Example (lazy import regression assertion):

import importlib
import openai
m1 = openai.types
m2 = importlib.reload(openai.types)
assert m1 is m2

Actionable Troubleshooting Docs

Technical documentation—especially troubleshooting guides—must let contributors go from symptom to reproducible diagnosis with minimal guesswork.

Apply these rules:

  1. Be precise about requirements vs local setup: state the minimum supported versions/constraints separately from “works locally” details.
  2. Anchor steps to the actual workflow/tools: link directly to the CLI action that saves the evidence (e.g., “Save report?”) and document the default location/structure where outputs are written (e.g., reports/<ticker>_<timestamp>/).
  3. Make the workflow traceable: when you claim a step, explicitly connect it to a failure pattern (“what to inspect first”), so readers can find the earliest wrong stage quickly.

Example structure to follow:

Result: docs become operational (tool/paths-driven), deterministic (pattern → first inspection), and clear about constraints (compatibility vs local environment).


Configuration Source of Truth

Maintain configuration in a single, consistent way across the codebase:

Example pattern (provider-specific defaults + None fallback):

def get_global_news(curr_date, look_back_days: int | None = 7, limit: int | None = 50) -> dict:
    # Resolve None via provider-specific config keys
    if look_back_days is None:
        look_back_days = DEFAULT_CONFIG.get("global_news_look_back_days", 7)
    if limit is None:
        # Keep Alpha Vantage historical default separate from other providers
        limit = DEFAULT_CONFIG.get("av_global_news_limit", 50)
    ...

Follow-up actions when issues are found:


Regression Tests With Parametrization

When changing business logic that affects output shape/order or resolution rules, add regression tests that assert observable outcomes for edge cases, and keep the suite maintainable by parameterizing repeated mock/assert patterns.

Apply it like this:

Example pattern (parameterized warning tests):

import warnings
import unittest
from unittest.mock import patch

class UnknownModelWarningTests(unittest.TestCase):
    def assert_one_user_warning(self, warning_records, provider, model):
        self.assertEqual(len(warning_records), 1)
        self.assertIs(warning_records[0].category, UserWarning)
        self.assertIn(f"Unknown {provider} model '{model}'.", str(warning_records[0].message))

    def test_unknown_model_warns(self):
        cases = [
            ("OpenAI",  "tradingagents.llm_clients.openai_client.UnifiedChatOpenAI",  "fake-openai-model"),
            ("Anthropic","tradingagents.llm_clients.anthropic_client.ChatAnthropic","fake-claude-model"),
            ("Google",  "tradingagents.llm_clients.google_client.NormalizedChatGoogleGenerativeAI", "fake-gemini-model"),
        ]

        for provider, patch_path, model in cases:
            with self.subTest(provider=provider, model=model):
                with patch(patch_path, side_effect=lambda **kwargs: kwargs):
                    with warnings.catch_warnings(record=True) as warnings_list:
                        warnings.simplefilter("always")
                        # call the provider client get_llm() here
                        llm = ...
                self.assertEqual(llm["model"], model)
                self.assert_one_user_warning(warnings_list, provider, model)

Also, for limit/order-sensitive behavior, ensure your test locks in the final observable output (e.g., count of headers) after all transformations, not just intermediate steps.


Cache deterministic results

When an operation is deterministic and expensive (often due to external IO like yfinance), avoid doing the same work twice. Use bounded memoization for repeated lookups and explicitly short-circuit cases where two inputs resolve to the same underlying entity. Also ensure caches don’t leak between tests.

Practical rules:

Example pattern:

from functools import lru_cache
import yfinance as yf

@lru_cache(maxsize=128)
def company_name(ticker: str) -> str:
    return yf.Ticker(ticker).info.get("longName") or ""

def fetch_returns(ticker: str, benchmark: str, trade_date, end_str):
    stock = yf.Ticker(ticker).history(start=trade_date, end=end_str)

    # Avoid redundant external call when both refer to the same entity
    if benchmark == ticker:
        bench = stock
    else:
        bench = yf.Ticker(benchmark).history(start=trade_date, end=end_str)

    # ...compute metrics using stock and bench...
    return stock, bench

Graceful, Specific Error Handling

When handling failures, prefer predictable, safe behavior over broad or crash-prone exception handling—especially around filesystem, JSON parsing, network calls, and user/CLI boundaries.

Practical rules: 1) Handle “expected missing” safely (filesystem)

2) Degrade gracefully on corrupted/unreadable data (JSON/parse)

3) Narrow exception types for network/API

4) Use consistent, cross-platform encodings for text I/O

Example pattern:

from pathlib import Path
import json
import requests

def clear_checkpoint_files(data_dir: Path) -> int:
    cp_dir = data_dir / "checkpoints"
    for db in cp_dir.glob("*.db"):
        for p in (db, db.with_name(f"{db.name}-wal"), db.with_name(f"{db.name}-shm")):
            if p.exists():
                p.unlink()
    return 0

def load_persisted(path: Path) -> dict:
    try:
        if not path.exists():
            return {"situations": [], "recommendations": []}
        return json.loads(path.read_text(encoding="utf-8"))
    except (json.JSONDecodeError, OSError):
        # Corrupt/unreadable → safe default
        return {"situations": [], "recommendations": []}

def save_persisted(path: Path, payload: dict) -> None:
    tmp = path.with_suffix(".tmp")
    tmp.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
    tmp.replace(path)

def fetch_with_best_effort(url: str) -> dict | None:
    try:
        resp = requests.get(url, timeout=30)
        resp.raise_for_status()
        return resp.json()
    except requests.exceptions.RequestException:
        return None

# Cross-platform log write
# with open(log_file, "a", encoding="utf-8") as f:
#     f.write(...)

Result: the app won’t crash on common real-world failure scenarios, errors are easier to reason about (because exceptions are specific), and behavior remains consistent across platforms and environments.


Align Mount Paths

When configuring Docker bind mounts (or any persistence paths), set the container mount target to exactly where the application writes at runtime—especially when code uses relative paths like Path.cwd() / "...". Don’t pick mount targets by convention; derive them from the actual path resolution logic.

How to apply:

Example:

# writes to a path relative to the container working directory
out_path = Path.cwd() / "reports"
out_path.mkdir(parents=True, exist_ok=True)
# bind the host reports dir to the container cwd-resolved reports dir
services:
  app:
    working_dir: /home/appuser/app
    volumes:
      - ./reports:/home/appuser/app/reports

This ensures user-facing generated artifacts persist to the intended host location, rather than accidentally redirecting only unrelated logs or internal files.


Boundary API Format Enforcement

When building provider requests or consuming provider responses, enforce that all intermediate representations match the provider’s expected wire format at the boundary—including IDs, message/content blocks, and versioned behavior.

Practical rules: 1) Translate/standardize provider-specific formats at payload-construction time (don’t assume downstream components share the same schema).

Example (pattern):

def _get_request_payload(messages, *, stream: bool, output_version: str | None, tools=None):
    # 1) validate/translate to wire format
    messages = normalize_messages_for_provider(messages)  # standard blocks/ids
    if tools is not None:
        ensure_tool_schemas_present(tools)  # avoid provider/token-counter failures

    # 2) explicit flags: avoid leakage into branching logic
    kwargs = {"stream": bool(stream)}

    # 3) explicit versioning: don’t rely on defaults
    if output_version is not None:
        kwargs["_output_version"] = output_version

    payload = build_provider_payload(messages, **kwargs)

    # 4) strip internal-only keys so they never reach the provider
    payload.pop("_output_version", None)
    return payload

This standard reduces brittle compatibility bugs where the same higher-level object behaves differently depending on hidden flags, streaming vs non-streaming paths, or provider-specific schema requirements.


Semantic naming for schemas

Use names that communicate intent and framework semantics—especially for (a) schemas and (b) callback parameters whose names are used for injection/dispatch.

Standards:

Example (callback arg naming + unused naming):

from typing import Any
from langgraph.types import interrupt

def before_agent(state: Any, runtime: Any) -> dict[str, Any]:
    # framework-injected names: keep as-is
    return {"ok": True, "state": state, "runtime": runtime}

def before_agent_unused(runtime: Any, state: Any) -> dict[str, Any]:
    # if intentionally unused, use underscore prefix
    _ = state
    return {"ok": True}

async def headless_coroutine(_config: Any, **kwargs: Any) -> Any:
    # intentionally unused config -> underscore
    return interrupt({"args": kwargs})

Applying this will reduce confusion in schema-driven tooling, prevent subtle runtime bugs caused by incorrect parameter names, and make behavior easier to understand during review.


Error precedence and degradation

When implementing error handling, ensure (1) failures are validated early or handled explicitly, (2) optional steps degrade gracefully, (3) cancellation/abort prevents unnecessary work, and (4) cleanup never masks the true result.

Practical rules: 1) Fail fast on invalid configuration

2) Use safe fallbacks when detection/lookup can be uncertain

3) Treat optional capabilities as non-fatal

4) Respect abort/cancellation as an explicit control flow

5) Preserve error precedence during cleanup

6) Don’t emit misleading secondary errors/warnings

Example (pattern):

async function runWithPreflightAndCleanup(opts: {
  abortSignal?: AbortSignal;
  envOverrides?: Record<string, string>;
}) {
  if (opts.abortSignal?.aborted) {
    throw Object.assign(new Error('Aborted'), { name: 'AbortError' });
  }

  const prev = new Map<string, string | undefined>();
  let primaryError: unknown;

  try {
    // Preflight validation (fail fast)
    const binary = opts.envOverrides?.COPILOT_BIN_PATH;
    if (binary !== undefined && binary.trim() === '') {
      throw new Error('COPILOT_BIN_PATH is set but blank');
    }

    // Optional step (non-fatal)
    try {
      await maybeOptionalStep();
    } catch (err) {
      logger.warn({ err }, 'optional_step_failed');
    }

    // Primary work
    return await doPrimaryWork();
  } catch (err) {
    primaryError = err;
    throw err;
  } finally {
    // Cleanup must not mask primary outcome
    try {
      if (opts.envOverrides) {
        for (const [k, v] of Object.entries(opts.envOverrides)) {
          if (prev.has(k)) {
            const old = prev.get(k);
            if (old === undefined) Reflect.deleteProperty(process.env, k);
            else process.env[k] = old;
          }
        }
      }
    } catch (cleanupErr) {
      logger.warn({ cleanupErr }, 'cleanup_failed');
      // never replace/override primaryError
    }
  }
}

Safe caching practices

Apply caching only when it is safe, bounded, and correct:

1) Avoid unbounded method memoization

2) Invalidate caches on mutation

3) Don’t memoize trivial derivations

4) Ensure cache-related transformations preserve structure

5) Document cached-metric semantics

Example: invalidate cached schema on mutation

# Pseudocode illustrating the pattern
class Tool:
    _SCHEMA_INVALIDATING_FIELDS = {"name", "description"}

    def __init__(self):
        self.__dict__["tool_schema"] = None
        self.__dict__["_inferred_input_schema"] = None

    def __setattr__(self, name, value):
        if name in self._SCHEMA_INVALIDATING_FIELDS:
            # Clear only the caches that depend on these fields
            self.__dict__.pop("tool_schema", None)
            self.__dict__.pop("_inferred_input_schema", None)
        super().__setattr__(name, value)

Example: avoid unbounded method lru_cache

# Prefer bounded caching or per-instance cached_property when lifecycle is bounded.
# Avoid: @lru_cache on methods where keys can grow without bound.

from functools import cached_property

class Parser:
    @cached_property
    def _compiled_pattern(self):
        import re
        return re.compile(r"\d+\.\s([^\n]+)")

Avoid event-loop blocking

Do not perform blocking I/O or other long-running synchronous work on asyncio’s event loop (especially in async client construction). Offload to worker threads (e.g., asyncio.to_thread) and prefer lazy credential/platform resolution protected by an async lock.

Also, when canceling/ending streamed responses, ensure you deterministically close the local stream before issuing any remote cancel call, and structure async generator cleanup so sessions/resources are released even if iteration terminates early.

Example pattern (lazy thread offload + guarded resolution):

import asyncio

class AsyncClient:
    def __init__(self, *, use_sigv4: bool):
        self._use_sigv4 = use_sigv4
        self._botocore_credentials = None
        self._creds_lock = asyncio.Lock()

    async def _get_credentials(self):
        if not self._use_sigv4:
            return None
        if self._botocore_credentials is None:
            async with self._creds_lock:
                if self._botocore_credentials is None:
                    # Offload blocking credential lookup/refresh work.
                    self._botocore_credentials = await asyncio.to_thread(_get_default_credentials)
        return self._botocore_credentials

    async def _prepare_request(self, request):
        creds = await self._get_credentials()
        _sign_httpx_request(request, creds, region="us-east-1")

Example pattern (stream cancel ordering):

def cancel_stream(stream, cancel_api):
    stream.close()              # close local stream first
    return cancel_api(stream.response_id)

Practical checklist:


Guard Optional Values

Treat any value that may be undefined/null (environment globals, optional stream handles, user config fields, optional IDs) as untrusted at the boundary. Use explicit checks/type guards instead of non-null assertions, and either omit invalid fields or return a deterministic safe failure—never let missing data crash module load or runtime.

Apply these patterns:

Example (safe guards):

function getOrigin(): string {
  return typeof window !== 'undefined' ? window.location.origin : 'http://localhost:3737';
}

function safePipeToQueue(stream: NodeJS.ReadableStream | null | undefined) {
  if (!stream) {
    // deterministic safe failure path
    return { ok: false as const, reason: 'missing_stream' };
  }
  // safe to attach listeners
  return { ok: true as const };
}

function parseConfig(raw: Record<string, unknown>) {
  const out: { model?: string } = {};
  if (typeof raw.model === 'string') out.model = raw.model;
  // drop invalid/unknown fields silently
  return out;
}

This prevents null-reference crashes (SSR/tests), avoids fragile ! usage, and keeps the system robust against malformed inputs.


Safe spawn and permission validation

Enforce security for any code that turns user/config inputs into subprocess execution or permission settings.

Apply these rules: 1) Spawn safely

2) Validate inputs that affect execution

3) Make permission precedence unambiguous

4) Don’t rely on pre-parsing

Example (deny-wins + safe argv building):

function buildArgs({ prompt, config, nodeConfig, extraArgs }: any): string[] {
  const args: string[] = ['-p', prompt];

  const allow = new Set([...(config.allowTools ?? []), ...(nodeConfig?.allowed_tools ?? [])]);
  const deny = new Set([...(config.denyTools ?? []), ...(nodeConfig?.denied_tools ?? [])]);
  for (const t of deny) allow.delete(t); // deny wins

  for (const t of allow) args.push(`--allow-tool=${t}`);
  for (const t of deny) args.push(`--deny-tool=${t}`);

  // extraArgs appended only after all security decisions are derived from final argv
  args.push(...(extraArgs ?? []));
  return args;
}

// Later: scan final argv for broad flags and warn; then spawn(binary, args, ...).

This reduces risks of command injection, path traversal/file misuse, and silent permission escalation.


Defensive config handling

Configuration should be treated as untrusted input: validate and normalize it, ignore unknown/invalid fields, and ensure user misconfiguration can’t crash initialization or produce misleading warnings. Also gate checks by what’s actually configured and implement a clear precedence order (env → explicit config → user paths → canonical defaults → PATH lookup) with platform-correct behavior.

Apply it like this:

Example pattern (parser + guard):

export function parseTimeouts(raw: Record<string, unknown>) {
  const out: { firstEventTimeoutMs?: number; processTimeoutMs?: number } = {};

  const toFinitePositiveMs = (v: unknown) =>
    typeof v === 'number' && Number.isFinite(v) && v > 0 ? Math.trunc(v) : undefined;

  const first = toFinitePositiveMs(raw.firstEventTimeoutMs);
  if (first !== undefined) out.firstEventTimeoutMs = first;

  const proc = toFinitePositiveMs(raw.processTimeoutMs);
  if (proc !== undefined) out.processTimeoutMs = proc;

  return out;
}

function shouldCheckGhAuth() {
  const hasGhToken = !!(process.env.GH_TOKEN || process.env.GITHUB_TOKEN);
  const hasOtherForge = !!(process.env.GITEA_URL || process.env.GITLAB_URL);
  return hasGhToken || !hasOtherForge; // skip GH warning for non-GH-only setups
}

Subprocess stream lifecycle

When you stream a subprocess’s stdout/stderr into an async generator, treat process exit, stream end/close, abort, and timeout escalation as concurrent events that can race.

Coding standard

  1. Finalize on stream close/flush, not only on exit. The “last output” might still be buffered when exit fires. Listen for stream close/end (or the streams’ close) and only then yield the final result/exit chunk.
  2. Coordinate producers/consumer with a single queue. Use a shared async event queue so stdout/stderr/exit/abort events are serialized for the generator.
  3. Make timeouts and escalation timers deterministic. Store timer IDs, clear them before rescheduling and in a cleanup path, and unref() escalation timers so they don’t keep the worker alive.
  4. Regression-test the race. Add a test where exit happens before stdout/stderr stream end to ensure the final chunk is yielded only after buffers are flushed.

Example pattern (simplified)

// shared queue
const { push, next } = makeEventQueue();
let processExited = false;
let stdoutClosed = false;
let stderrClosed = false;

const killProcess = (reason: string) => {
  if (processExited) return;
  child.kill('SIGTERM');

  // escalation timer: track + clear + unref
  if (sigkillTimer) clearTimeout(sigkillTimer);
  sigkillTimer = setTimeout(() => {
    if (!processExited) child.kill('SIGKILL');
  }, 2000);
  sigkillTimer.unref();
};

pipeLinesToQueue(child.stdout!, 'stdout', push);
pipeLinesToQueue(child.stderr!, 'stderr', push);

child.once('exit', (code, signal) => {
  processExited = true;
  push({ kind: 'exit', code, signal });
});

// Finalize only when streams are closed/flushed
child.stdout?.once('close', () => { stdoutClosed = true; push({ kind: 'stdout_close' } as any); });
child.stderr?.once('close', () => { stderrClosed = true; push({ kind: 'stderr_close' } as any); });

// consumer: drain events, then yield result when both close + exit known
// (implementation depends on your result-yield strategy)

Applying this prevents lost tail output, double-yields, and subtle leaks/hangs caused by concurrent lifecycle events and uncleared timers.


Token Precedence Safety

When multiple authentication tokens are supported (e.g., generic GitHub tokens vs Copilot-specific tokens), enforce a deterministic, documented precedence and require explicit opt-in for fallback behavior.

Apply this to CI/workflows and any code that selects credentials:

Example (workflow logic pattern):

# Pseudocode: enforce precedence
env:
  COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
  GH_TOKEN: ${{ secrets.GH_TOKEN }}

# Selection rule (conceptual):
# if COPILOT_GITHUB_TOKEN set -> use it
# else if GH_TOKEN/GITHUB_TOKEN set -> require explicit useLoggedInUser:false
# else -> fail

This prevents accidental use of the wrong credentials, reduces risk of unexpected permissions, and makes security-sensitive behavior consistent across environments.


Config resolution consistency

When adding or extending client/provider integrations, enforce a single, predictable configuration-resolution contract:

Example patterns:

# 1) Env fallback + clear error
resolved_api_version = api_version or os.environ.get("OPENAI_API_VERSION")
if not resolved_api_version:
    raise ValueError("Must provide api_version or set OPENAI_API_VERSION")

# 2) copy(): keep dependent config consistent
new_region = region or self._region
# ensure base_url is recalculated when region changes
_forward_base_url = {} if region else {"base_url": self.base_url}

# 3) copy(): normalize mutually-exclusive auth fields
# if switching to api_key, drop credential provider
forwarded_credential_provider = None if "api_key" in kwargs else (credential_provider or self._credential_provider)

Add unit tests that cover:


Cache validity and bounds

When adding caching, ensure (1) correctness via validity/refresh and (2) safety via bounds/staleness resistance.

1) Align cache lifetime with real validity

def token_provider(*, token_duration: int = 3600):
    _cached = [None]
    _refresh_at = [0.0]

    def generate() -> str:
        # local signing; no network
        return "bedrock-api-key-..."

    def get() -> str:
        import time
        now = time.monotonic()
        if _cached[0] is None or now >= _refresh_at[0]:
            _cached[0] = generate()
            _refresh_at[0] = now + max(token_duration - 60, token_duration * 0.9)
        return _cached[0]

    return get

2) Prevent unbounded memory growth

from functools import lru_cache

@lru_cache(maxsize=128)
def get_type_adapter(type_):
    # expensive instantiation avoided
    return make_adapter(type_)

3) Don’t cache derived auth/state that can go stale

Checklist


Single Source Error Logic

When handling failures or optional data, make the decision exactly once and reuse the result everywhere.

Apply two concrete rules: 1) Normalize once, then use the normalized values for both validation and execution. Don’t validate one set of fields and execute using separately-fallbacked canonical fields. 2) Centralize optional-feature degradation. Don’t repeat broad try/except import patterns across many call sites—move them into a shared helper that returns either the real implementation or a safe no-op.

Example (canonicalize before validate/execute):

def normalize_tool_request(payload: dict) -> tuple[str, dict] | None:
    # pick a single canonical source-of-truth (fallbacking happens only here)
    tool_name = payload.get("tool_name") or payload.get("tool")
    tool_args = payload.get("tool_args") or payload.get("args")
    if not tool_name or tool_args is None:
        return None
    return tool_name, tool_args

async def process_tools(self, msg: str):
    tool_request = extract_tool_request(msg)  # returns dict or None
    if tool_request is None:
        return

    normalized = normalize_tool_request(tool_request)
    if normalized is None:
        return  # structural/misformat handled once

    tool_name, tool_args = normalized
    await self.validate_tool_request({"tool_name": tool_name, "tool_args": tool_args})
    # execution uses tool_name/tool_args derived from the same normalized result
    await self.execute_tool(tool_name, tool_args)

Example (centralize optional integration):

# python/helpers/state_monitor.py
def get_state_monitor():
    try:
        from python.helpers.state_monitor_impl import StateMonitor
        return StateMonitor()
    except ImportError:
        return None  # safe degraded mode

# call site
monitor = get_state_monitor()
if monitor is not None:
    monitor.state_push(...)

This prevents inconsistent “validation passes but execution breaks” flows and reduces duplicated, inconsistent error-handling paths for optional integrations.


Deterministic Algorithm Correctness

When implementing non-trivial algorithms (graph ordering, batching under constraints, multi-pass transformations), apply four requirements:

1) Guarantee termination with explicit guards/invariants

2) Respect real constraints with dynamic computation

3) Keep behavior deterministic across passes

4) Separate algorithm concerns into a dedicated, testable unit

Example (token-aware batching with progress and guaranteed exit):

# Precondition: token_counts and tokens are aligned
batched = []
i = 0
while i < len(tokens):
    batch_end = i + 1  # progress guarantee
    batch_token_count = token_counts[i]
    for j in range(i + 1, min(i + _chunk_size, len(tokens))):
        if batch_token_count + token_counts[j] > MAX_TOKENS_PER_REQUEST:
            break
        batch_token_count += token_counts[j]
        batch_end = j + 1

    # API call uses tokens[i:batch_end]
    response = client.create(input=tokens[i:batch_end], **client_kwargs)
    batched.append(response)
    i = batch_end

Example (deterministic Mermaid node label encoding):

def to_safe_ascii_id(label: str) -> str:
    out = []
    for ch in label:
        if ch.isascii() and (ch.isalnum()):
            out.append(ch.lower())
        else:
            out.append('n' + format(ord(ch), 'x'))
    slug = ''.join(out)
    return slug if slug[0].isalpha() else 'n' + slug

Adopting these rules reduces correctness regressions (limits/termination), avoids subtle identity mismatches in graph-like structures, and makes algorithmic code easier to reason about and test.


Isolate process-global mocks

When a test uses process-global/irreversible module mocking, prevent cross-test contamination by isolating the affected test files into separate bun test runs (batch isolation). Keep mocks narrowly scoped so tests don’t need to mock large dependency graphs, and avoid importing “config/provider” chains in units where tests shouldn’t require them.

Practical checklist:

Example (pattern):

// conversations.test.ts
mock.module('../config/config-loader', () => ({
  loadConfig: mock(async () => ({ assistant: 'claude' })),
}));

Then run it as an isolated invocation:

cd packages/core && bun test packages/core/src/db/conversations.test.ts

This ensures your tests remain deterministic and don’t break due to local .archon/config.yaml contents or prior mocked state from other test files.


Preserve AI Structure Invariants

When working with LLM/chat “auxiliary” content (reasoning, tool calls/results, structured content blocks, and usage/metadata), enforce structural invariants so provider/streaming/truncation logic can’t silently corrupt meaning.

Practical rules:

Example (reasoning normalization + preserving empty semantics):

from typing import Any

def normalize_reasoning(reasoning: Any) -> str | None:
    if reasoning is None:
        return None
    if isinstance(reasoning, str):
        return reasoning  # preserve ""
    if isinstance(reasoning, list):
        if not reasoning:  # empty list => None
            return None
        parts: list[str] = []
        for item in reasoning:
            if isinstance(item, dict):
                # support multiple provider shapes
                v = item.get("thinking") if "thinking" in item else item.get("content")
                parts.append("" if v == "" else str(v) if v is not None else str(item))
            else:
                parts.append(str(item))
        return "\n".join(parts)
    return str(reasoning)

Apply the same “invariant-first” mindset to tool-call/tool-result pairing and streaming chunk finalization: write code so the internal model never allows impossible states (or it is corrected immediately), and back it with targeted tests.


Align AI interfaces

When coding against LLM providers, treat model capabilities and prompt/tool formats as spec-driven interfaces: match upstream expectations exactly, and avoid ad-hoc mappings or manual edits that can drift.

Apply this as three concrete rules: 1) Don’t hand-edit generated AI registries

2) Map “thinking/effort” (and similar) levels per model without collapsing semantics

Example pattern:

   function mapThinkingLevelToEffort(modelId: string, level: string) {
     if (level !== "xhigh") return level;

     // Example: Opus 4.7 distinguishes xhigh vs max.
     const isOpus47 = ["opus-4-7", "opus-4.7"].some(s => modelId.includes(s));
     return isOpus47 ? "xhigh" : "max";
   }

3) Match provider prompt/tool syntax exactly (use the same tag structure)

Example pattern:

   function buildSkillsSection(skills: string[]): string {
     if (skills.length === 0) return "";
     const body = skills.join("\n");
     return `<available_skills>\n${body}\n</available_skills>`;
   }

Net effect: fewer “it works for some models” surprises, less drift between code and provider reality, and safer changes when providers add/alter capabilities.


Organize and Clean Imports

Keep codebase structure and import usage aligned with the intended architecture and boundaries.

Example:

// ✅ type-only import to avoid unused/runtime imports
import type React from 'react';

// ✅ do not import values you never use
// import { useToast } from '../contexts/ToastContext'; // remove if unused

Avoid shared mutable state

When working with concurrency (threads/async), ensure code is safe under parallel invocations and does not block or re-enter running event loops.

Rules: 1) Eliminate shared mutable state across requests/threads

2) Be event-loop safe

3) Provide and test async behavior

4) Keep async detection consistent

Example patterns:

# 1) Immutability / no post-init mutation
class ConditionalModelSettingsMiddleware(AgentMiddleware):
    def __init__(self, conditions: list[tuple[Callable, dict[str, Any]]]):
        super().__init__()
        self._conditions = list(conditions)  # don’t mutate after init
# 2) Offload blocking work from async contexts
async def abefore_agent(self, state, runtime):
    return await run_in_executor(None, self.before_agent, state, runtime)
# 3) Don’t use asyncio.run() inside possibly-running event loops
# Prefer: make the validation async, or detect running loop and schedule appropriately.
async def _avalidate(...):
    ...
# then in async contexts: await _avalidate(...)
# 4) Prefer inspect for coroutine-function checks
import inspect
if ignore_condition_name is None or not getattr(handler, ignore_condition_name):
    event = getattr(handler, event_name)
    if inspect.iscoroutinefunction(event):
        ...

Adopting these practices prevents race conditions, avoids event-loop reentrancy problems, and ensures concurrency-heavy logic is correct under real async/parallel workloads.


Keep Helpers Small

Favor readability and maintainability by keeping functions/methods short, extracting complex logic into well-named helpers, and avoiding duplicated or closure-based implementations in constructors.

Apply these rules:

Example (extracting complex logic into helpers):

def _merge_reasoning_details(details: list[dict[str, Any]]) -> list[dict[str, Any]]:
    if len(details) <= 1:
        return details

    merged: list[dict[str, Any]] = []
    i = 0
    while i < len(details):
        entry = details[i]
        if not _is_mergeable_fragment(entry):
            merged.append(entry)
            i += 1
            continue

        entry_type, entry_index, text_key = _fragment_key(entry)
        base = _fragment_base(entry, text_key)
        texts = [_fragment_text(entry, text_key)]

        i += 1
        while i < len(details) and _matches_fragment(details[i], entry_type, entry_index):
            texts.append(details[i].get(text_key, "") or "")
            base = _merge_fragment_metadata(base, details[i], text_key)
            i += 1

        merged.append({**base, text_key: "".join(texts)})

    return merged

API contract regression

When adding or changing API-like functions (parsers, clients, helpers), treat them as having a stable contract: define the accepted inputs and exact output shape, cover tricky edge cases with regression tests, and remove/deprecate superseded code paths so the API surface stays unambiguous.

How to apply:

Example (contract + regression):

// Contract: treat GitHub URLs as { url } and local/UNC paths as { path }
function getCodebaseInput(input: string): { url?: string; path?: string } {
  // ...implementation
  return {};
}

// Regression cases for gaps
test('treats relative paths as paths', () => {
  expect(getCodebaseInput('../repo')).toEqual({ path: '../repo' });
});

test('treats UNC paths as paths', () => {
  expect(getCodebaseInput('\\server\\share\\repo')).toEqual({
    path: '\\server\\share\\repo',
  });
});

Checklist:


Treat Jinja2 as Unsafe

Don’t trust “sandboxed” templating when any part of template text (or dangerous expressions) can be influenced by an untrusted party. For security-sensitive code, assume Jinja2 (and similar template engines) is dangerous with untrusted inputs and enforce strict trust boundaries.

Apply this rule:

Example (safe pattern: allowlisted templates; user data only as inert values):

from jinja2 import Template

ALLOWED_TEMPLATES = {
    "welcome": "Hello {{ name }}!",
}

def render_welcome(template_id: str, user_name: str) -> str:
    # Block attacker-controlled templates
    if template_id not in ALLOWED_TEMPLATES:
        raise ValueError("Unknown template")

    tmpl = Template(ALLOWED_TEMPLATES[template_id])
    # Treat user_name as inert data; ensure it’s escaped for your output context
    return tmpl.render(name=user_name)

If your system needs to accept user-provided templates, require additional hardening and security review rather than assuming Jinja2 sandboxing is sufficient.


SDK-aware API clients

When building or calling API client code, follow the SDK’s actual request/response types and conventions instead of assuming REST/dict semantics.

Apply these rules:

Example (proto field access + SDK-managed endpoint):

from typing import Any

# Assume `request` is a proto/typed object created by the SDK
def inject_fields(request: Any) -> Any:
    # Proto repeated composite field: iterate directly; do not use request.get(...)
    for content in request.contents:
        for part in content.parts:
            # mutate request parts as required by the API
            pass
    return request

# When initializing provider clients, let the SDK handle endpoint construction
base_url = None  # e.g., instead of hardcoding /v1

Preserve API Contracts

When transforming data to/from the API, always implement the backend’s explicit contract: ordering invariants, exact serialization, correct parsing by response format/content-type, endpoint-appropriate headers, and backend-specific URL/auth/version rules.

Apply these checks consistently:

Example (response-format-safe parsing + invariant-preserving payload building):

def get_response_input_items(response):
    # preserve required reasoning->assistant consecutive pairing
    items = []
    for output_item in response.output:
        items.append(output_item.model_dump(exclude_unset=True))
    return items

def parse_response(rbody: str, headers: dict[str,str], response_format):
    if response_format == "json" or headers.get("Content-Type") == "application/json":
        return json.loads(rbody)
    return rbody  # text/srt/vtt

Rule of thumb: if the contract can be stated as “must be ordered X”, “must be JSON vs text Y”, or “must send header key Z / URL path P”, encode it as logic + validation—not as an assumption.


Async Concurrency Practices

When working in async-capable code, ensure correctness and concurrency safety:

1) Keep async code truly async (no accidental sync calls)

2) Make shared caches/thread-safety explicit

3) Prevent event-loop blocking from blocking IO

Example pattern (bounded blocking + caching):

import os
from functools import lru_cache

@lru_cache(maxsize=1)
def _infer_region() -> str:
    aws_region = os.environ.get("AWS_REGION")
    if aws_region:
        return aws_region

    import boto3  # may do blocking config/FS access
    return boto3.Session().region_name

Also ensure parity between sync/async clients: if an async client exposes the same configuration surface as sync, apply the same changes and keep behavior consistent.


Concise, Consistent State

Adopt a style rule that keeps code (1) concise in data derivation, (2) consistent in input normalization, and (3) correct in conditional logic by using the right source of state.

How to apply:

Example pattern:

from typing import Dict, List, Tuple

ModelOption = Tuple[str, str]
ProviderModeOptions = Dict[str, List[ModelOption]]

MODEL_OPTIONS: ProviderModeOptions = {...}

def get_known_models() -> Dict[str, List[str]]:
    # Concise derived-data construction
    return {
        provider: sorted({value for options in mode_options.values() for _, value in options})
        for provider, mode_options in MODEL_OPTIONS.items()
    }

def _ensure_str(v) -> str:
    # Centralized normalization for serialization/write paths
    if v is None:
        return ""
    if isinstance(v, list):
        return "\n".join(map(str, v))
    return str(v)

def write_text(path, content):
    with open(path, "w", encoding="utf-8") as f:
        f.write(_ensure_str(content))

Checklist:


Harden installation security

Any install/setup instructions and scripts must avoid common supply-chain and remote execution risks, and must clearly communicate the security posture.

Apply these rules:

Example (safer install guidance):

# BAD: remote execution default
curl -fsSL https://example.com/install.sh | bash

# BETTER: pinned artifact + explicit execution step
# (Version is pinned; fetching is logged and execution is explicit)
VERSION='1.2.3'
curl -fsSL -o tool.tgz "https://example.com/tool-${VERSION}.tgz"
# verify checksum/signature here, then extract/run explicitly

tar -xzf tool.tgz
./tool --help

Result: fewer opportunities for compromised dependencies or tampered install scripts to affect users, plus clearer expectations for safe setup.


Tool Loop Output Contract

When implementing tool-using LLM agent nodes (e.g., LangGraph/LangChain multi-agent flows), standardize a “tool loop → finalize only when tools are done” contract.

What to do

  1. Build a node that:
    • Creates a tools list.
    • Builds a ChatPromptTemplate with a strong system_message that includes a coordination stop signal (e.g., FINAL PREDICTION: **YES/NO**) and any required output formatting instructions (e.g., “append a Markdown table”).
    • Injects required context with partial(...) (at minimum: tool_names, current_date/trade date, market_id, market_question).
  2. Bind tools and execute:
    • chain = prompt | llm.bind_tools(tools)
    • result = chain.invoke(state["messages"])
  3. Finalize output only on the non-tool invocation:
    • Populate report only when len(result.tool_calls) == 0 (because the graph will re-invoke the node after tools complete).

Example pattern

def agent_node(state, llm):
    current_date = state["trade_date"]
    market_id = state["market_id"]
    market_question = state["market_question"]

    tools = [get_news, search_markets]

    system_message = (
        "You are a <Role> for prediction markets..."
        " If you or any other assistant has the FINAL PREDICTION: **YES/NO**"
        " prefix your response with FINAL PREDICTION: **YES/NO** so the team knows to stop."
        " Make sure to append a Markdown table at the end of the report."
    )

    prompt = ChatPromptTemplate.from_messages([
        ("system", "... {tool_names}...\n{system_message}"
                   " For your reference, the current date is {current_date}."
                   " Market ID: {market_id}. Question: {market_question}"),
        MessagesPlaceholder(variable_name="messages"),
    ])

    prompt = prompt.partial(
        system_message=system_message,
        tool_names=", ".join([t.name for t in tools]),
        current_date=current_date,
        market_id=market_id,
        market_question=market_question,
    )

    chain = prompt | llm.bind_tools(tools)
    result = chain.invoke(state["messages"])

    report = ""
    if len(result.tool_calls) == 0:  # finalize only when tools are complete
        report = result.content

    return report

Secondary process rule: Keep changes focused—don’t remove or refactor upstream/shared code in the same PR as an unrelated feature; move housekeeping to a separate PR.


Actionable normalized errors

When adding error handling for failure scenarios (infinite/looping behavior, retries, or other unbounded processes), ensure two things:

1) Normalize/validate error-relevant inputs before they affect control flow.

2) Make raised exceptions actionable.

Example pattern:

import math
import sys

def retry_loop(max_retries):
    if max_retries is math.inf or max_retries >= sys.maxsize:
        range_limit = sys.maxsize
    else:
        range_limit = int(max_retries) + 1

    for _ in range(range_limit):
        yield


def detect_potentially_infinite_compaction(threshold):
    # ... if two consecutive compactions happen:
    raise RuntimeError(
        "Potentially infinite compaction detected. "
        f"Increase the compaction threshold (current: {threshold}) to avoid two consecutive compaction iterations."
    )

Apply this standard so exceptions don’t just fail— they guide the fix and avoid additional crashes caused by invalid/edge inputs.


Deterministic API Contracts

When designing API client/runner behavior, ensure the contract is explicit, state-driven, and aligned with what the server actually supports.

Apply these rules:

Example (state-driven follow-up request):

# BAD: reusing container id from a previous API response
# container_id = last_api_response.container.id

# GOOD: use container id from the current last assistant message in state
message = self._get_last_message()
if message.container is not None:
    container_id = message.container.id
    # use container_id for the next tool/assistant step

Example (explicit config with env default):

def get_auth_headers(api_key: str | None = None) -> dict[str, str]:
    key = api_key or os.getenv("AWS_BEARER_TOKEN_BEDROCK")
    if not key:
        raise ValueError("Missing api key")
    return {"Authorization": f"Bearer {key}"}

Prefer Robust Testing Assertions

When adding/changing tests, optimize for (1) clear intent, (2) stability against refactors, and (3) determinism.

Practical rules:

Example: readable, stable expectation

result = convert_to_openai_function(MyModel)
assert result == {
    "name": "MyModel",
    "parameters": {"type": "object", "properties": {}, "required": []},
    "strict": True,
}

Example: avoid brittle intermediate-step tests (assert the actual SDK call)

client = MagicMock()
# arrange llm to use mocked client
llm.invoke("hello", prompt_cache_key="k")
called_kwargs = client.create.call_args.kwargs
assert called_kwargs["prompt_cache_key"] == "k"

Example: fix nondeterministic ordering

items = list(set(items))          # flaky
items = sorted(set(items))        # deterministic

Documentation lookup rules

When writing or updating API skill docs, treat documentation as an operational dependency: prefer the most up-to-date source, keep docs self-contained, and make examples unambiguous.

Apply these rules: 1) Prefer live indexed documentation (MCP) when available

Example (self-contained documentation snippet):

# `frame` must be raw bytes for a single image frame, encoded as JPEG/PNG bytes
# (or provide the required mime_type for the SDK wrapper).
# If you pass base64 strings, convert them to bytes (or use the SDK's expected field type).

await session.send_realtime_input(
    video=types.Blob(data=frame_bytes, mime_type="image/jpeg")
)

Use this checklist during review to prevent stale guidance, broken links, and “works in theory” examples that fail at integration time.


Prefer up-to-date docs

When building Gemini/LLM integrations, always use the most current and indexed API documentation/spec first, and avoid inefficient fallback behaviors.

Apply this standard:

Example (MCP-first behavior):

IF tool search_documentation exists:
  docs = search_documentation("How to call Structured Outputs in Gemini")
  // Ensure docs are sufficient
  generate code using docs
  // Do NOT fetch llms.txt as a fallback
ELSE:
  fetch llms.txt index
  fetch only the needed page(s)
  generate code using fetched docs

Prefer Imports, Not Globals

When wiring state/functions, avoid implicit access through window.*/globalThis. Use explicit ES module imports so code is deterministic and loads correctly, and keep code in the module/plugin that owns it.

Apply this standard

Example (store access)

// Prefer this:
import { createStore } from "/js/AlpineStore.js";
import { store as notificationStore } from "/components/notifications/notification-store.js";

// Avoid this pattern:
// const rootStore = window.Alpine?.store ? window.Alpine.store("root") : undefined;
// ...then rely on root/global wiring

Checklist


Preserve Null Semantics

When inputs or response fields are optional/nullable, preserve their semantics explicitly and avoid unsafe coercion or indexing.

Apply these rules: 1) Don’t coerce None with bool(...) when None has distinct meaning. If you mean “unset,” omit the field/parameter rather than converting it. 2) Don’t blindly index into dicts/JSON (obj["key"]) when keys may be missing; use obj.get("key", default) (often {}) to prevent exceptions. 3) When building request artifacts (e.g., headers), only include values when the input is actually present; otherwise, send an empty structure or omit the header.

Example patterns:

# 1) Tri-state optional: None => omit
payload = {}
if by_alias is not None:
    payload["by_alias"] = by_alias  # preserve None-vs-explicit

# 2) Safe dict access
error_data = response.data.get("error", {})
message = error_data.get("message", "Operation failed")

# 3) Conditional auth header
headers = {} if not api_key else {"Authorization": f"Bearer {api_key}"}

Result: fewer runtime KeyErrors/invalid requests, and correct behavior when upstream defaults/configuration rely on “unset” vs “explicit value.”


Docstrings With Intent

Adopt a single documentation standard: every docstring/comment should (1) explain intent and observable behavior, (2) make responsibility/ownership explicit, (3) be traceable when tied to external or non-obvious defaults, (4) be safe when examples could do harm, and (5) follow established docstring conventions without duplicating type annotations.

Practical rules

Example pattern

def _gpt5_defaults_to_no_reasoning(model: str) -> bool:
    """Return True if a gpt-5 variant defaults to reasoning_effort='none'.

    Notes:
        Source: See OpenAI GPT-5.2 Prompting Guide and GPT-5.2 model docs.
        If OpenAI changes these defaults, update this helper and add a regression test.

    Args:
        model: Model identifier (e.g., 'gpt-5.2', 'gpt-5.2-pro').

    Returns:
        True when the model defaults to no reasoning.
    """
    ...

Applying this standard will make docs easier to maintain, reduce user confusion, and prevent unsafe or misleading copy/paste behavior.


Code Style, Typing, DRY

Adopt a “type-safe, clean, DRY” style for readability and maintainability.

Example (import + typed local + helper pattern):

# module scope
import json


def parse_stream_line(line: bytes) -> str:
    if not line or line == b"data: [DONE]":
        return ""
    if hasattr(line, "decode"):
        line = line.decode("utf-8")
    if line.startswith("data: "):
        line = line[len("data: "):]
    return line


def parse_stream(rbody):
    for line in rbody:
        out = parse_stream_line(line)
        if out:
            yield out


def some_function() -> "ResponseFormatParam":
    schema_param: "ResponseFormatParam" = {"type": "text"}
    return schema_param

Applying these consistently will improve clarity (fewer surprises), maintainability (less duplication), and type-checker effectiveness (fewer ignores and safer refactors).


Prefer precise typing

Use precise types instead of Any, and avoid unnecessary typing.cast by relying on type-guard utilities and existing type narrowing. In tests, prefer the concrete pytest types/fixtures (e.g., pytest.MonkeyPatch) over broad Any.

Apply this as a style rule:

Example:

import pytest
import typing as t
from .typing_utils import is_dict, is_list

@pytest.mark.respx()
def test_something(monkeypatch: pytest.MonkeyPatch) -> None:
    ...

def _deep_merge_extra_fields(existing: object, new: object) -> object:
    if is_dict(existing) and is_dict(new):
        # type is narrowed by is_dict
        for k, v in new.items():
            ...
        return existing
    if is_list(existing) and is_list(new):
        # type is narrowed by is_list
        existing.extend(new)
        return existing
    return new

High-signal Testing Practices

Write tests that are (a) high-signal and not fragile, and (b) structured with standard pytest mechanisms.

Apply:

Example (focused assertion + fixture-friendly structure):

import re
import pytest
import respx
import httpx
from unittest.mock import Mock

@pytest.mark.respx()
def test_bearer_token_env_passes_authorization(monkeypatch: pytest.MonkeyPatch, respx_mock):
    respx_mock.post(re.compile(r"https://bedrock-runtime\.us-east-1\.amazonaws\.com/model/.*/invoke")).mock(
        return_value=httpx.Response(200, json={"ok": True})
    )

    monkeypatch.setenv("AWS_BEARER_TOKEN_BEDROCK", "test-bearer-token")

    # exercise code that triggers the request
    # sync_client.messages.create(...)

    calls = list(respx_mock.calls)
    assert len(calls) == 1
    assert calls[0].request.headers.get("Authorization") == "Bearer test-bearer-token"

This approach keeps tests reliable, maintainable, and valuable as the code evolves.


Unified extension API contracts

When building WebUI plugin/extension systems, treat the backend as the source of truth for (1) resolving extension contents and (2) providing a stable context schema to JS extensions.

Apply these rules:

Example (contract-driven usage):

// Client: paste extension HTML resolved by backend
async function applyExtensionPoint(node, id) {
  const htmlParts = await get_webui_extensions(id); // backend contract
  node.innerHTML = htmlParts.join("\n");
}

// JS extension: rely on unified context schema
export default async function injectBranchButtons(context) {
  const msgs = context?.messages;
  if (!Array.isArray(msgs) || msgs.length === 0) return;

  for (const m of msgs) {
    // contract requires log number (no)
    if (typeof m.no !== "number") throw new Error("Missing context.messages[].no");
    // ...use m.no to wire actions
  }
}

Outcome: frontend extension code becomes deterministic (no “sometimes field is present” surprises), and plugin authors can build against a predictable backend-defined contract.


Consistent None Handling

When a value can be missing/null, reflect it in the type system and handle it explicitly at the boundary—never leak None into observable outputs (yields, dict keys, metadata, merged content) and don’t “paper over” missing invariants with synthetic placeholders.

Practical rules: 1) Prefer X | None = None (or Optional[X]) over sentinel-literals like Literal[False] for optional callables. 2) Guard before writing/using: if something derived could be None (e.g., a dict key), check before assignment. 3) Ensure iterators/streaming never yield None as a valid element unless the type says so. 4) Keep semantic distinctions: e.g., treat args=None as “streaming in-progress” and args={} as “completed no-args” to avoid parsing/execution bugs. 5) If an invariant is violated (e.g., “an AIMessage must exist”), either raise a clear error or widen the function signature and make callers handle the missing case—don’t create dummy objects that hide the underlying state bug.

Example patterns:

from typing import Callable

# 1) Optional callable
length_fn: Callable[[list[str]], list[int]] | None = None

# 2) Guard None-derived keys
header_key = splittable_headers.get("#" * depth)
if header_key is not None:
    current_chunk.metadata[header_key] = value

# 3) Avoid yielding None
first_chunk = await first_map_chunk_task
if first_chunk is not None:
    yield first_chunk

# 4) Preserve streaming vs final semantics
# args=None => not ready to execute; args={} => execute with no args
if tool_call_args is None:
    # streaming/in-progress
    pass
else:
    # final state
    run_tool_with(tool_call_args)

# 5) Missing invariant: raise or widen types (don’t fabricate)
if last_ai_message is None:
    raise ValueError("Expected at least one AIMessage in state")

Centralize shared fields

When multiple modules need the same state/config/schema (e.g., context variables like timezone, or prompt search paths), do not replicate those fields or the logic that derives them in several places. Instead, funnel access through a single abstraction and reuse shared utilities.

How to apply:

Example (pattern):

# Instead of each module reading/handling timezone separately,
# make snapshot the source of truth.

# snapshot.py
@dataclass
class SnapshotContext:
    timezone: str
    # ...other shared fields

def build_context_from_snapshot(snapshot: Any) -> SnapshotContext:
    return SnapshotContext(timezone=snapshot.timezone)

# state_sync_handler.py
ctx = build_context_from_snapshot(snapshot)
state_monitor.mark_dirty(sid, reason=reason, timezone=ctx.timezone)

# Or, if StateMonitor only stores projection fields,
# accept an object built from snapshot rather than individual scalars.

This reduces “adjust multiple scripts when fields change” and keeps code organization consistent while improving readability.


Namespace plugin APIs

When exposing data to the client, treat shared/global values and plugin routes as explicit API surface:

1) Don’t publish global client/window state by sprinkling ad-hoc dictionaries into multiple unrelated API handlers. Instead, use one centralized mechanism:

Example (centralized injection):

<script>
  // after globalThis.gitinfo
  globalThis.runtimeInfo = {
    isDevelopment: {{ runtime.is_development() | tojson }}
  };
</script>

2) Plugin endpoints must be mounted under a stable namespace to prevent collisions with core API routes.

Example (route mounting concept):

# core router bootstrap
register_routes(prefix=f"/plugins/{plugin_name}", handlers=plugin_handlers)

Explicit None Checks

When working with nullable/optional values, treat None (absence) differently from other falsy values like "" (empty string) or 0 (zero). Use explicit is not None checks when empty values are valid, and avoid repeating null checks after you’ve already established a non-null invariant via an early return/guard.

Apply it like this:

Example:

import os

bearer = os.getenv("AWS_BEARER_TOKEN_BEDROCK")
# Empty string is a valid value, so check for None (absence), not truthiness.
if bearer is not None:
    headers["Authorization"] = f"Bearer {bearer}"

# Later, avoid redundant None checks after a guard/early return:
if response is None:
    return
if response.get("content"):
    append_messages(message, response)

Keep secrets out

Do not commit secret keys, credentials, or signing material to source code or public repos. Store secrets in environment variables or a managed secret store, load them at runtime, and ensure they are not present in repository history. Design signed tokens so that the server validates them and they are short-lived, and have a plan to rotate/revoke keys if exposure occurs.

Why: a secret embedded in code (e.g., SECRET_KEY used to HMAC-sign tokens) can be extracted and used to forge or replay tokens even if tokens have expirations. Removing secrets from code reduces attack surface and supports secure key management.

How to apply:

OLD: SECRET_KEY = “dfc92bc5e95825103283f01c2aa6ca7fe7f6ffc31778ea82c354785c73b0858c”

NEW: import os SECRET_KEY = os.environ.get(“MERCH_SECRET_KEY”) # set via env or secret manager if not SECRET_KEY: raise RuntimeError(“MERCH_SECRET_KEY not configured”)

Checks/PR guidance:

References: [0]


Domain-aligned Identifier Naming

When introducing identifiers that represent external/domain data (e.g., tool calls, event payloads) and shared utilities, keep naming and placement semantically aligned and avoid redundant typing.

Apply: 1) Use domain-consistent suffixes for schema-derived types

2) Prefer inference over duplicated/hand-written boundary types

3) Put shared utilities in accurately named modules and reuse them

Example (adapted):

const bashSchema = Type.Object({
  command: Type.String(),
  timeout: Type.Optional(Type.Number()),
});

// Domain-aligned: matches event.input
export type BashToolInput = Static<typeof bashSchema>;

// Inference-first: avoid re-specifying the same structure if already inferred
export const createBashTool = () =>
  ({
    execute: async (
      _toolCallId: string,
      { command, timeout }, // type inferred from bashSchema
      signal?: AbortSignal,
    ) => {
      // ...
    },
  });

Rule of thumb: if the identifier communicates “input/payload”, name it accordingly; if the logic is shared, name the module for what it provides and reuse it rather than duplicating/relocating ad-hoc helpers.


Effect cleanup and subscriptions

When using React hooks that interact with external systems (browser events, subscriptions, async requests), write code so it cannot leak resources or update state after the component unmounts.

Standard

  1. In useEffect, always return a cleanup function that removes listeners/subscriptions.
  2. For in-flight async work started in useEffect (fetch, timers, requests), cancel/abort on cleanup (e.g., AbortController) so setState can’t run after unmount.
  3. For event-based external data that multiple renders/components may depend on, prefer useSyncExternalStore over manual event subscription logic.

Example (safe effect + abort)

function Notifications() {
  const [data, setData] = useState<Notification[]>([])

  useEffect(() => {
    const controller = new AbortController()

    const onResize = () => {
      // listener logic
    }
    window.addEventListener('resize', onResize)

    fetch('/api/notifications', { signal: controller.signal })
      .then(r => r.json())
      .then(next => setData(next))
      .catch(() => {
        /* ignore abort */
      })

    return () => {
      window.removeEventListener('resize', onResize)
      controller.abort()
    }
  }, [])

  return <div />
}

Example (subscription preference)


Prefer nonmutating multiset checks

When doing algorithmic equality checks for arrays where order doesn’t matter (multiset equality), avoid (a) mutating the input with .sort() and (b) sort+join/stringify approaches when a linear-time counting strategy is available. Use a non-mutating sort (toSorted) only if sorting is truly the chosen approach; otherwise prefer counting maps (expected O(n) in common JS engines) to avoid O(n log n) sorting.

Example (order-insensitive multiset equality):

function hasChanges(current: string[], original: string[]) {
  if (current.length !== original.length) return true;

  const counts = new Map<string, number>();
  for (const x of current) counts.set(x, (counts.get(x) ?? 0) + 1);
  for (const x of original) {
    const c = counts.get(x) ?? 0;
    if (c === 0) return true;
    if (c === 1) counts.delete(x);
    else counts.set(x, c - 1);
  }
  return counts.size !== 0;
}

If you must use sorting for comparison, use a non-mutating method:

return current.toSorted().join() !== original.toSorted().join();

No Console Logging

Avoid direct console.log/console.warn (and other console.*) in application code—especially in TUI/interactive flows—because it can break rendering and other runtime behavior. Route all log/diagnostic output through the project’s logging/UI abstraction so messages are formatted and displayed consistently.

Apply this rule by:

Example (pattern):

// Bad (don’t do this)
console.warn("[pi-ai] Skipping unsigned thinking block");

// Good
uiContext.notify("Skipping unsigned thinking block", "warn");

If a function currently falls back to console.log when UI isn’t available, refactor it to use an injected logger (or a non-TUI-safe abstraction) instead of writing to the console directly.


Lock Writes, Snapshot Reads

Use the lock to protect shared mutable state during mutations, but avoid holding it for read-side convenience/field-by-field getters.

Rules

  1. Lock only for writes: Acquire the mutex only around code that mutates shared collections/fields (e.g., logs[], updates[], notifications[]).
  2. Minimize critical sections: Do expensive or deterministic work (masking, truncation, formatting) outside the lock; lock only to commit the final updates.
  3. Reads: prefer no lock or atomic snapshots:
    • If your read is “best-effort” and does not require a logically consistent multi-field view, avoid locking.
    • If you need a consistent snapshot across multiple related reads, either:
      • lock the whole read sequence, or
      • copy the needed data under lock, then release and compute/iterate outside.

Example pattern (commit under lock, transform outside)

def update_item(self, *, no: int, heading: str | None, content: str | None):
    # Preprocess outside the lock
    if heading is not None:
        new_heading = _truncate_heading(self._mask_recursive(heading))
    if content is not None:
        item_type = self.logs[no].type  # or pass in required type explicitly
        new_content = _truncate_content(self._mask_recursive(content), item_type)

    with self._lock:
        item = self.logs[no]
        if heading is not None:
            item.heading = new_heading
        if content is not None:
            item.content = new_content
        self.updates.append(item.no)

Applying this standard will reduce lock contention, prevent unnecessary refactors tied to read-side locking, and still keep shared writes thread-safe.


Intentional Cache Design

Cache behavior should be justified by real reuse and measured impact.

Apply this standard: 1) Scope the cache correctly: for per-process/per-session data, prefer in-memory caching and avoid disk persistence unless it measurably reduces recomputation time on restart/resume. 2) Make eviction policy explicit: if you use a bounded Map/Set, document whether eviction is FIFO, LRU, etc., and why that policy fits the observed access pattern. 3) Size caches based on evidence: verify whether the cache is actually populated and whether larger sizes improve hit rate/latency; don’t pick sizes “because it seems fine.” 4) Define acceptable cold-start behavior: if cache misses on resume are minor and the system already recomputes shortly, it’s fine to start empty.

Example pattern (in-memory, bounded, explicit FIFO):

const CACHE_LIMIT = 512;
const cache = new Map<string, number>();

function getOrCompute(key: string, compute: () => number) {
  const v = cache.get(key);
  if (v !== undefined) return v;

  const next = compute();
  if (cache.size >= CACHE_LIMIT) {
    const firstKey = cache.keys().next().value; // FIFO eviction
    if (firstKey !== undefined) cache.delete(firstKey);
  }
  cache.set(key, next);
  return next;
}

If you need different behavior (e.g., true LRU), use an LRU structure or maintain recency explicitly—don’t assume insertion-order eviction matches your intent.


AI Boundary Compatibility

When building AI/LLM-related tooling (tool-calls, background execution, inference/image generation), enforce compatibility at the boundaries:

1) Use team-standard LLM-friendly IDs

2) Make AI hardware initialization conservative + always fall back

Example (ID generation pattern):

# pseudo-example: use the team helper rather than custom UUID strings
from python.helpers.guids import llm_guid  # assumed name from your guids.py

call_id = llm_guid(length=8)  # keep the default length consistent

Checklist to apply during review


Avoid Hidden Performance Traps

Default rule: in performance-sensitive code, prevent hidden blowups and avoid expensive work being executed repeatedly in hot paths or on import.

Apply this checklist: 1) Replace inefficient primitives inside loops

2) Don’t do global scans per iteration in graph/ordering logic

3) Cache expensive introspection/metadata

4) Prefer lazy, memoized loading over eager initialization

5) Choose fast strategies by default (when the API is designed for it)

Example (dependency resolution):

from collections import deque

# Build reverse deps once: dep -> set(dependents)
reverse_deps = {}
for cls, deps in dep_graph.items():
    for dep in deps:
        reverse_deps.setdefault(dep, set()).add(cls)

queue = deque(sorted([c for c in instance_by_class if in_degree[c] == 0], key=lambda x: x.__name__))
while queue:
    current = queue.popleft()
    for dependent in reverse_deps.get(current, ()):  # only affected neighbors
        in_degree[dependent] -= 1
        if in_degree[dependent] == 0:
            queue.append(dependent)

Fail Fast Dependency Errors

When resolving dependencies or other derived configuration, never “log-and-continue” into an inconsistent internal state.

Apply this standard:

  1. Validate at the source (fail fast): validate depends_on (types/contents) in AgentMiddleware.__init__() so errors point to the middleware that provided bad input.
  2. Use narrow exception handling: during auto-instantiation, catch only expected exception types (e.g., TypeError/ValueError from constructor/args). Avoid broad except Exception.
  3. Preserve invariants: if auto-instantiation fails, do not proceed to dereference structures that assume the dependency exists. Either:
    • raise a clear error immediately, or
    • explicitly check presence before access.
  4. Make errors visible: use warning/error (or raise) rather than DEBUG-only logs so failures are actionable in real runs.

Example pattern (inspired by the discussed failure mode):

instance_by_class: dict[type, Middleware] = {}

try:
    instance_by_class[dep_class] = dep_class()  # auto-instantiation
except TypeError as e:  # narrow expected failures
    # Fail fast with context; do not `continue` and later risk KeyError
    raise ValueError(
        f"Failed to auto-instantiate middleware dependency {dep_class.__name__} "
        f"required by {type(instance).__name__}: {e}"
    ) from e

# Safe access: only when guaranteed present
dep_instance = instance_by_class[dep_class]

This prevents delayed, confusing errors (like KeyError) and ensures failures are reported with precise, fixable context.


Maintainable documentation hygiene

Documentation should be kept authoritative and maintainable: use stable links, avoid recommending deprecated APIs, and remove misleading/ineffective documentation details.

Apply it as follows:

Example (tool-only, non-deprecated usage):

from langchain_desearch.tools import DesearchTool

tool = DesearchTool()
result = tool.invoke({"query": "LLM RAG best practices"})
print(result)

Stable Interface Contracts

When designing or extending APIs, treat existing “core” interface contracts as stable and enforce exact compatibility (method signature + parameter semantics + return shapes) across base classes and all implementations. If you need different inputs/behavior for a subset of modules, add an adapter/compatibility layer in the business layer instead of changing the core interface.

Practical rules:

Example: adapter-based compatibility (don’t modify core)

# Core interface (unchanged)
class ChatPromptTemplate:
    def generate_input_values(self, *, question: str, **kwargs):
        ...

# Business-layer adapter
class ChatDashboardPromptTemplate(ChatPromptTemplate):
    def generate_input_values(self, *, input: str, **kwargs):
        # map new variable name to old core contract
        return super().generate_input_values(question=input, **kwargs)

Example: contract-consistent retriever base

from typing import Any, Tuple

class GraphRetrieverBase:
    async def retrieve(self, input: Any) -> Tuple["Graph", Any]:
        raise NotImplementedError

# Implementation conforms to the base signature
class DocumentGraphRetriever(GraphRetrieverBase):
    async def retrieve(self, input):
        # input can be Union[Graph, List[str], List[List[float]]] in practice
        graph = ...
        extra = None
        return graph, extra

This prevents runtime failures like “takes N positional arguments but M were given” and avoids breaking unrelated modules that depend on the core contract.


Config source precedence

When configuration is moved/renamed or when settings are derived from environment variables, ensure (1) the dotenv loader points to the correct file path/name and (2) there is an explicit precedence order for derived settings (env-provided values override generated/default values).

Apply this as two concrete checks:

Example pattern:

import dotenv

def apply_settings(copy: dict) -> None:
    # precedence: env override > generated default
    external_key = dotenv.get_dotenv_value("A0_EXTERNAL_API_KEY")
    if external_key:
        copy["mcp_server_token"] = external_key
    else:
        copy["mcp_server_token"] = create_auth_token()

Use authenticated env tokens

Any service exposed to the network (e.g., via Docker ports) must be protected with authentication, and any secret used for that auth (e.g., Jupyter token/password) must come from environment variables (e.g., .env) rather than being hardcoded in versioned files. If a compose file uses placeholder defaults, treat them as non-production scaffolding and require production overrides.

Example (secure pattern):

services:
  jupyter:
    ports:
      - "8888:8888"
    env_file:
      - .env
    environment:
      # Put the real token in .env (do not commit it)
      - JUPYTER_TOKEN
    command: >-
      jupyter lab --ip=0.0.0.0 --port=8888 --no-browser --allow-root
      --ServerApp.token='${JUPYTER_TOKEN}'

Checklist:


explicit null checks

Use explicit existence checks rather than value-based null checks, and be intentional about failing fast versus providing defaults for missing data.

When checking for optional data, prefer checking for key/attribute existence rather than checking if values are truthy or greater than zero. This prevents subtle bugs where legitimate zero values or empty strings are treated as missing data.

For missing required data, prefer explicit KeyError/AttributeError over None-based error handling to provide clearer error messages and fail fast.

Prefer explicit existence checks:

# Good - check if key exists
if "cacheReadInputTokens" in usage:
    attributes["cache_read_tokens"] = usage["cacheReadInputTokens"]

# Avoid - value-based check that excludes valid zero values  
if usage.get("cacheReadInputTokens", 0) > 0:
    attributes["cache_read_tokens"] = usage["cacheReadInputTokens"]

Fail fast for required data:

# Good - explicit KeyError for missing required field
status=Status(data["status"])

# Avoid - None handling that masks the real issue
status=Status(data.get("status"))  # Will fail with confusing None error

Be intentional about defaults:

# Good - explicit defaults for optional fields with clear intent
usage = Usage(**{"inputTokens": 0, "outputTokens": 0, "totalTokens": 0, **event.get("usage", {})})

# Consider defensive checks only when inheritance/overrides make them necessary
if not hasattr(self, "session_type"):
    self.session_type = SessionType.AGENT

Use descriptive names

Choose names that clearly convey purpose and intent rather than generic or ambiguous terms. Names should be specific enough to understand functionality without requiring additional context.

Avoid generic names:

Use semantically meaningful names:

Choose appropriate specificity:

Example:

# Avoid generic names
class Executor:  # Too generic
    pass

# Use descriptive names  
class ConcurrentToolExecutor:  # Clear purpose and scope
    def serialize_state(self) -> dict:  # Clear action
        pass
    
    def get_next_nodes(self) -> list[str]:  # Clear return type
        pass

This approach improves code readability and reduces the need for additional documentation to understand component purposes.


Complete docstring documentation

Ensure all classes, methods, and properties have comprehensive docstrings that clearly explain their purpose, behavior, and usage. Docstrings should be preferred over inline comments for method descriptions and should include:

  1. Clear purpose explanation - What the code does and why it exists
  2. Behavior clarification - Explain differences in behavior, especially for similar methods
  3. Attribute documentation - Document all class attributes in the docstring
  4. Examples and expected shapes - Include usage examples and expected data structures
  5. Parameter and return documentation - Use proper Args/Returns sections

Example of comprehensive docstring:

class MultiAgentBase(ABC):
    """Base class for multi-agent helpers.

    This class integrates with existing Strands Agent instances and provides
    multi-agent orchestration capabilities.

    Attributes:
        id: Unique identifier for the multi-agent instance
    """

    @property
    def system_prompt(self) -> str | None:
        """Get the system prompt as a string.
        
        Returns the system prompt content converted to string format,
        while system_prompt_content accepts various content types.
        
        Returns:
            String representation of system prompt, or None if not set
        """

def __init__(self, config_source: str | dict[str, any]):
    """Initialize AgentConfig from file path or dictionary.
    
    Args:
        config_source: Either a file path (with 'file://' prefix) or 
                      a dictionary containing agent configuration.
                      Expected shape: {
                          "name": "agent_name",
                          "model": "model_name", 
                          "tools": ["tool1", "tool2"],
                          "system_prompt": "prompt text"
                      }
    """

This approach improves code maintainability and helps future contributors understand the codebase without needing to read implementation details or PR discussions.


Ensure deterministic resume behavior

When implementing persistence and resume functionality in durable execution systems, ensure that state is persisted at consistent event boundaries and that resume logic handles all execution states explicitly to maintain deterministic behavior.

Key principles:

  1. Choose appropriate persistence timing: Persist state at events that provide clear recovery semantics. For example, persisting on BeforeNodeCallEvent ensures that if execution crashes during a node, resume will restart from that node rather than an earlier point.

  2. Handle terminal states explicitly: When resuming from terminal states (COMPLETED, FAILED), determine whether to restart execution or return previous results based on clear business logic.

  3. Avoid state corruption during resume: Don’t automatically clear failed nodes or modify execution state during resume unless there’s explicit justification, as this can alter the original execution path.

Example of proper state handling:

def deserialize_state(self, payload: dict) -> None:
    # Handle terminal states explicitly
    if payload.get("status") in (Status.COMPLETED.value, Status.FAILED.value):
        if not payload.get("next_nodes_to_execute"):
            # Execution ended - reset for new run
            self._reset_state()
            return
    
    # Resume from persisted state without modifying execution path
    self._restore_state(payload)
    # Don't clear failed_nodes - preserve original execution semantics

This ensures that durable execution systems behave predictably across interruptions and restarts, maintaining the integrity of the workflow orchestration.


Choose appropriate synchronization

Select the correct synchronization mechanism based on your execution context and avoid unnecessary synchronization overhead. In async contexts with coroutines, locks are often unnecessary since coroutines run cooperatively in a single thread. Use asyncio.Lock() for async contexts and threading.Lock() for multi-threaded scenarios. When bridging sync and async code with threads, ensure proper context variable propagation and use daemon threads for background tasks.

Key guidelines:

Example of proper lock selection:

# Async context - lock usually unnecessary
async def process_nodes_async(self, nodes):
    # Coroutines run cooperatively, no race conditions
    for node in nodes:
        self.state.completed_nodes.add(node)

# Mixed async/thread context - use asyncio.Lock
class GraphExecutor:
    def __init__(self):
        self._lock = asyncio.Lock()  # For async task coordination
    
    async def execute_parallel(self, nodes):
        async with self._lock:  # Only if truly needed
            # Critical section
            pass

# Thread context - use threading.Lock  
class FileManager:
    def __init__(self):
        self._lock = threading.RLock()  # For thread coordination
    
    def write_file(self, data):
        with self._lock:
            # Thread-safe file operations
            pass

Before adding synchronization, verify you actually have a race condition. Many async operations don’t require explicit locking due to the cooperative nature of coroutines.


Config-Accurate Dependency Management

When updating project configuration (e.g., pyproject.toml), ensure dependency declarations match how packages are actually used: align requires-python with dependency-supported Python versions, keep dev-only tooling in dev-dependencies, and use extras for optional features instead of adding new required runtime deps. Also, set minimum versions based on the concrete APIs/helpers you rely on.

Apply this checklist:

Example (optional CLI dependency):

# pyproject.toml
[project.optional-dependencies]
cli = ["argcomplete>=1.12.0"]
# _cli.py
try:
    import argcomplete  # type: ignore
except ImportError:
    argcomplete = None

if argcomplete is not None:
    # use argcomplete
    ...
else:
    # either disable CLI niceties or show a message
    ...

Configuration default handling

Use clean, simple patterns when accessing configuration values with defaults. Avoid redundant fallback operations and overly complex boolean conversions that reduce code readability.

Prefer simple .get() with defaults:

# Good: Clean and readable
"stream": self.config.get("streaming", True)

# Good: Method already returns appropriate default
all_tools_config = self.tool_registry.get_all_tools_config()

# Good: Simple default parameter
session_type: SessionType = SessionType.AGENT

Avoid redundant fallbacks:

# Avoid: Unnecessary `or {}` when method returns dict
all_tools_config = self.tool_registry.get_all_tools_config() or {}

# Avoid: Overly complex boolean conversion
"stream": bool(self.get_config().get("streaming", True))

This pattern improves code maintainability by reducing complexity and making default behavior explicit. When methods already guarantee return types (like returning empty dict), additional fallbacks create confusion about the actual contract. Keep configuration access patterns simple and trust documented method behaviors.


comprehensive test assertions

Write robust test assertions that verify complete objects and behaviors rather than individual properties. Use pytest’s built-in features for exception testing and mock verification to make tests more reliable and maintainable.

Key practices:

Example of improved assertions:

# Instead of manual exception handling:
try:
    some_function()
    raise AssertionError("Expected an exception")
except ValueError as e:
    assert "expected message" in str(e)

# Use pytest.raises with match:
with pytest.raises(ValueError, match="expected message"):
    some_function()

# Instead of checking individual properties:
assert agent.messages[1]["role"] == "user"
assert "toolResult" in agent.messages[1]["content"][0]
assert agent.messages[1]["content"][0]["toolResult"]["toolUseId"] == "orphaned-123"

# Assert the complete structure:
expected_message = {
    "role": "user", 
    "content": [{"toolResult": {"toolUseId": "orphaned-123", ...}}]
}
assert agent.messages[1] == expected_message

# Instead of manual kwargs capturing:
def capture_kwargs(*args, **kwargs):
    capture_kwargs.captured_kwargs = kwargs

# Use mock verification:
assert mock_function.call_args == call(expected_args, **expected_kwargs)

This approach makes tests more readable, catches more potential issues, and reduces the likelihood of false positives in test results.


maintain backwards compatibility

When modifying public APIs, always preserve backwards compatibility to avoid breaking existing consumers. Public methods, even if rarely used directly, must maintain their existing signatures and behavior.

Use these patterns to evolve APIs safely:

Add new methods instead of modifying existing ones:

# Instead of changing invoke_callbacks() to async
def invoke_callbacks(self, event: TInvokeEvent) -> tuple[TInvokeEvent, list[Interrupt]]:
    # Keep existing sync method
    
async def invoke_callbacks_async(self, event: TInvokeEvent) -> tuple[TInvokeEvent, list[Interrupt]]:
    # Add new async method, deprecate old one

Use parameter separators for new optional parameters:

# Backwards compatible - new params after *
def __call__(
    self, prompt: AgentInput = None, *, 
    structured_output_type: Type[BaseModel] | None = None, 
    **kwargs: Any
) -> AgentResult:

Avoid @abstractmethod for new interface methods:

# Breaking - forces all implementers to update immediately
@abstractmethod
def new_method(self): pass

# Non-breaking - allows gradual adoption
def new_method(self):
    raise NotImplementedError("Subclasses should implement this method")

Preserve import paths when reorganizing:

# In __init__.py - maintain old import while moving implementation
from .new_location import convert_pydantic_to_tool_spec

Consider the impact on all consumers, including those calling public methods directly, extending abstract classes, or using specific import paths. When in doubt, add new APIs alongside existing ones rather than modifying them.


Centralized Config Standards

When implementing new behavior behind feature flags or configuration (paths, env vars, index dimensions, toggles like text2gql), use centralized, documented config instead of hardcoded values or scattered env access.

Apply these rules: 1) No absolute paths/constants in code: resolve paths from config/env (with sensible defaults). 2) Use feature flags from config and keep them consistent across code/docs/.env.template. 3) Avoid “parameter explosion”: encapsulate related settings into a dedicated *Config object and pass that object (or access via get_config()) instead of threading many constructor args. 4) Don’t read os.getenv in feature logic; normalize env->config during config building. 5) Don’t hardcode tunables (e.g., embedding/index dimension); pull them from config. 6) Keep layer boundaries: app-layer settings (e.g., CFG/proxy/app-specific knobs) should be passed down as explicit parameters/config, not embedded in lower modules.

Example (replace absolute paths with config):

from pathlib import Path
from dataclasses import dataclass

@dataclass
class DataManusConfig:
    db_path: str
    excel_path: str

def load_config() -> DataManusConfig:
    # normalize env in one place (not throughout business logic)
    import os
    return DataManusConfig(
        db_path=os.getenv("DATA_MANUS_DB_PATH", "./examples/test_files/datamanus_test.db"),
        excel_path=os.getenv("DATA_MANUS_EXCEL_PATH", "./examples/test_files/employer_info.xlsx"),
    )

def build_connector(cfg: DataManusConfig):
    db_file = Path(cfg.db_path).expanduser().resolve()
    return SQLiteConnector.from_file_path(str(db_file))

Checklist for each PR:


configurable security controls

Design security mechanisms with configurable behavior to handle different threat scenarios and use cases. Avoid rigid, one-size-fits-all security implementations that may not suit all deployment contexts.

Security controls should provide configuration options that allow teams to adjust behavior based on their specific threat model. For example, a content filtering system might need different redaction strategies - sometimes redacting only the violating content, other times redacting both input and output to prevent cascading security issues.

# Good: Configurable security behavior
def _has_blocked_guardrail(self, guardrail_data: dict[str, Any]) -> tuple[bool, bool]:
    blocked_input = any(self._find_detected_and_blocked_policy(assessment) 
                       for assessment in input_assessment.values())
    blocked_output = any(self._find_detected_and_blocked_policy(assessment) 
                        for assessment in output_assessments.values())
    
    return blocked_input, blocked_output

# Configuration allows different redaction strategies:
# - guardrail_redact_input: redact only input violations
# - guardrail_redact_output: redact only output violations  
# - Both: redact both when either triggers (prevents cascading issues)

This approach enables security controls to adapt to different scenarios, such as preventing assistants from echoing trigger words that could create security loops, while still allowing targeted redaction when appropriate.


CI blocking with overrides

When implementing CI checks that can block pull request merges, always provide clear override mechanisms for exceptional cases. Hard-failing CI checks should be strong signals to developers, but teams need escape hatches when legitimate exceptions arise.

Design your CI workflows to fail meaningfully while maintaining flexibility:

# Example: PR size check with override capability
- name: Check PR size
  run: |
    if [ $TOTAL_CHANGES -gt 1000 ]; then
      echo "PR is too large ($TOTAL_CHANGES lines). Please split into smaller PRs."
      echo "To override, add 'override-size-check' label and provide justification."
      exit 1
    fi

Key considerations:

This approach provides strong developer guidance while acknowledging that exceptional cases requiring large PRs will occasionally arise and need a path forward.


eliminate code duplication

Identify and consolidate duplicate code patterns by extracting common logic into reusable functions and unifying similar code blocks. This improves maintainability, reduces bugs, and enhances readability.

Key strategies:

Example from the codebase:

# Before: Duplicate code paths
if self.node_timeout is not None:
    events = self._stream_with_timeout(...)
else:
    events = self.stream_async(...)

# After: Unified approach
events = self._stream_with_timeout(...) if self.node_timeout else self.stream_async(...)

Another example:

# Before: Complex inline construction
after_event = agent.hooks.invoke_callbacks(
    AfterToolCallEvent(
        agent=agent,
        tool_use=tool_use,
        result={
            "toolUseId": tool_use["toolUseId"],
            "status": "cancelled",
            "content": [{"text": "Tool execution was cancelled"}]
        }
    )
)

# After: Extract result construction
cancelled_result = self._create_cancelled_tool_result(tool_use)
after_event = agent.hooks.invoke_callbacks(
    AfterToolCallEvent(agent=agent, tool_use=tool_use, result=cancelled_result)
)

Always look for opportunities to consolidate when you notice similar patterns, repeated logic, or multiple code paths that achieve the same outcome.


Fail fast explicitly

Always throw exceptions for error conditions rather than silently failing, logging warnings, or attempting fallback behavior that masks underlying problems. When encountering unexpected states, missing required data, or configuration errors, raise descriptive exceptions immediately rather than continuing execution with degraded functionality.

This principle prevents bugs from being masked and ensures developers receive clear feedback about problems in their code. Silent failures make debugging difficult and can lead to unexpected behavior in production.

Examples of what to avoid:

# Bad: Silent failure with warning
try:
    saved = self.session_manager.read_multi_agent_json()
except Exception as e:
    logger.warning("Skipping resume; failed to load state: %s", e)
    return  # Silently continue without state

# Bad: Fallback that masks the real problem  
def serialize_node_result(self, raw):
    if hasattr(raw, "to_dict"):
        return raw.to_dict()
    # Fallback for strings and other types
    return {"agent_outputs": [str(raw)]}  # Masks unknown types

Preferred approach:

# Good: Explicit failure with clear message
try:
    saved = self.session_manager.read_multi_agent_json()
except Exception as e:
    raise RuntimeError(f"Failed to load session state: {e}") from e

# Good: Fail fast on unknown types
def serialize_node_result(self, raw):
    if hasattr(raw, "to_dict"):
        return raw.to_dict()
    if isinstance(raw, dict):
        return raw
    raise TypeError(f"Cannot serialize node result of type {type(raw)}")

The goal is to make problems visible immediately so they can be addressed rather than allowing them to propagate silently through the system.


Simplify and organize code

Keep code simple, direct, and well-organized by avoiding unnecessary complexity and properly structuring components. Remove redundant implementations when existing mechanisms already handle the functionality. Avoid indirect approaches when more straightforward solutions exist. Extract large components into separate files when they become unwieldy.

Examples of improvements:

This approach improves code readability, reduces maintenance burden, and makes the codebase more intuitive for other developers to understand and modify.


Use proper logging practices

Always use logging instead of print statements, and choose appropriate log levels to avoid log spam. Print statements can contaminate the stdio buffer and break system functionality, especially in server environments.

Use logging with appropriate levels:

Example of proper logging practices:

# Bad - using print statements
print("DEBUG: Starting terraform version detection...")
print(f"Elixir test repository already compiled in {repo_path}")

# Good - using appropriate logging levels
logger.debug("Starting terraform version detection...")
logger.info(f"Elixir test repository already compiled in {repo_path}")

# Good - warning for fallback scenarios
logger.warning(f"Could not decode {file_path} with encoding='{encoding}'; using best match '{match.encoding}' instead")

# Good - debug level for potentially verbose information
logger.debug(f"Skipping {path}: does not match include pattern {paths_include_glob}")

This prevents stdio buffer contamination and ensures logs are properly categorized and filterable.


Use semantically meaningful names

Choose names that clearly convey purpose and intent rather than generic or ambiguous terms. Prefer specific, descriptive terminology that makes code self-documenting and reduces cognitive load for readers.

Key principles:

Example improvements:

# Less clear
from charset_normalizer import from_path
def get_extracts(content_reader: Callable[[str], str]):
    severity: int = 1

# More semantically meaningful  
import charset_normalizer
def find_code_snippets(file_reader: Callable[[str], str]):
    severity: DiagnosticSeverity = DiagnosticSeverity.ERROR
    result = charset_normalizer.from_path(path)

This approach makes code more maintainable by reducing ambiguity and making the developer’s intent explicit through careful name selection.


validate AI model configurations

When adding or modifying AI model configurations, ensure proper validation through both pattern-based matching and functional testing. Avoid hardcoding specific model IDs when existing patterns can handle multiple models generically. Always test model functionality before adding to production configurations.

For region-specific model handling, prefer pattern-based approaches:

// Instead of hardcoding each model:
if (isAustraliaRegion && 
  (modelID.startsWith("anthropic.claude-sonnet-4-5") || modelID.startsWith("anthropic.claude-haiku-4-5"))) {
  modelID = `au.${modelID}`
}

// Use existing patterns:
const modelRequiresPrefix = ["claude", "nova-lite", "nova-micro", "nova-pro"].some((m) => 
  modelID.includes(m))

For model priority lists, verify functionality before deployment:

// Test each model before adding to priority list
const priority = ["llama3", "gemini-2.5-pro-preview", "codex-mini", "claude-sonnet-4"]
// Ensure models work beyond just the first request

This approach reduces maintenance overhead and prevents production issues with untested AI model configurations.


Manage network resources

When working with streaming or TCP options, be explicit and defensive:

1) Closing streams: If you terminate a stream early (e.g., you don’t fully consume an HTTP/SSE iterator), ensure you close the underlying network resource—not just a wrapper/decoder that may not implement close().

2) Socket options: Set keepalive (and similar socket options) only when the platform exposes the needed constants, and use mutually exclusive conditionals to avoid configuring conflicting options.

Example pattern:

# 1) Stream termination: close the underlying response/connection
try:
    # consume partially or stop early
    ...
finally:
    # Prefer the actual HTTP response/connection close
    if hasattr(response, "close"):
        response.close()
    elif hasattr(decoder, "close"):
        decoder.close()

# 2) TCP keepalive: conditional and non-conflicting configuration
socket_options = [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True)]
TCP_KEEPINTVL = getattr(socket, "TCP_KEEPINTVL", None)

if TCP_KEEPINTVL is not None:
    socket_options.append((socket.IPPROTO_TCP, TCP_KEEPINTVL, 60))
elif sys.platform == "darwin":
    TCP_KEEPALIVE = getattr(socket, "TCP_KEEPALIVE", None)
    if TCP_KEEPALIVE is not None:
        socket_options.append((socket.IPPROTO_TCP, TCP_KEEPALIVE, 60))

Apply this standard to prevent leaked connections, hanging sockets, and platform-specific networking bugs.


maintain JSON response consistency

When designing API responses that need to handle different data types or display states, maintain consistent JSON structure and use established encoding standards to preserve backward compatibility. Avoid changing response schemas that would break existing client integrations.

For binary data in JSON responses, use base64 encoding as the standard approach:

if (isBinary) {
  const buffer = await bunFile.arrayBuffer().catch(() => new ArrayBuffer(0))
  const content = Buffer.from(buffer).toString("base64")
  return { type: "binary", content, mimeType: getMimeType(full) }
}

For displaying modified or discounted values, use additional fields or metadata rather than changing the core data structure. This allows clients to handle the information appropriately while maintaining the expected response format. The principle follows established practices like AWS S3’s JSON APIs, which use base64 encoding for binary content to ensure text-safe transmission within JSON payloads.


Simple explicit interfaces

Design API interfaces to be simple and explicit rather than hiding complexity behind elaborate fallbacks or conditional logic. When core functionality is unavailable, fail explicitly with clear error messages instead of implementing complex workarounds. Push complexity and decision-making to the caller rather than embedding it within the API implementation.

Key principles:

Example of preferred approach:

# Good: Simple interface, explicit failure
def rename_symbol(self, file_path: str, line: int, column: int, new_name: str) -> WorkspaceEdit | None:
    if not self.server.supports_rename():
        raise UnsupportedOperationError("Language server does not support rename operations")
    return self.server.send.rename(params)

# Good: Explicit assertions instead of conditionals
allow_symbol = next((s for s in symbol_list if s.get("name") == "allow"), None)
assert allow_symbol is not None, "allow symbol should always be found"

# Good: Simple interface pushes list creation to caller
def _run_command(command: list[str], logger: LanguageServerLogger, cwd: str) -> None:
    # Caller is responsible for creating the command list

This approach makes APIs more predictable, easier to test, and clearer about their expectations and limitations.


Contextualize documentation decisions

Documentation should provide contextual guidance about when and why to use features, not just how to configure them. Additionally, strategically link to external documentation rather than duplicating content to reduce maintenance overhead.

When documenting configuration options or features:

  1. Explain the use cases that require each option
  2. Provide context about when users would need specific settings
  3. Link to authoritative external sources instead of duplicating their content

Example of good contextual documentation:

## Azure URL Configuration

Different Azure deployments require different URL formats. Configure these options based on your deployment type:

| Deployment Type | useDeploymentBasedUrls | useCompletionUrls | Use Case |
|-----------------|------------------------|-------------------|----------|
| Standard API    | false                  | false             | Basic Azure OpenAI service |
| Custom Deployment | true                 | true              | When using named model deployments |

For detailed Azure setup instructions, see the [official Azure OpenAI documentation](https://docs.microsoft.com/azure/cognitive-services/openai/).

This approach helps users understand not just what to configure, but when they need each configuration, while avoiding the maintenance burden of duplicating external documentation.


AI provider normalization

When integrating multiple AI model providers, implement proper abstraction layers to normalize differences in APIs, data formats, and behaviors. Different providers often have inconsistent interfaces that require careful handling to maintain application consistency.

Key practices:

Example from LiteLLM provider handling:

def _format_request_message_contents(self, role: str, content: ContentBlock) -> list[dict[str, Any]]:
    """Format LiteLLM compatible message contents.
    
    LiteLLM expects content to be a string for simple text messages, not a list of content blocks.
    This method flattens the content structure to be compatible with LiteLLM providers like Cerebras and Groq.
    """
    # Provider-specific format conversion logic here

# Handle provider-specific error messages
LITELLM_CONTEXT_WINDOW_OVERFLOW_MESSAGES = [
    "Context Window Error",
    "Context Window Exceeded", 
    "Input is too long",
    # Common error substrings from different providers
]

This approach prevents provider inconsistencies from breaking application logic and ensures consistent behavior across different AI model backends.


Maintain naming consistency

Ensure naming follows consistent patterns within the codebase and adheres to official framework conventions. When creating related types or functions, use matching naming schemes to maintain clarity and prevent synchronization issues. Prefer established conventions over custom variations unless there’s a compelling reason to deviate.

For example, if you have CloneRepoParams, create a corresponding CloneRepoReturnType rather than using a generic return type. Similarly, when working with frameworks like Supabase, stick to their official function-name/index.ts convention rather than implementing broader custom patterns.

// Good: Consistent naming pattern
interface CloneRepoParams { ... }
interface CloneRepoReturnType { ... }

// Good: Following official convention
// supabase/functions/my-function/index.ts

// Avoid: Inconsistent or custom naming
interface CloneRepoParams { ... }
interface GenericResponse { ... } // Should be CloneRepoReturnType

This approach reduces cognitive load, prevents naming conflicts, and ensures the codebase remains maintainable as it scales.


exact assertion testing

Tests should verify exact expected results rather than generic existence checks. Avoid assertions like isinstance(), len() > 0, is not None, or any() that only confirm something exists without validating correctness. Instead, assert for specific expected values, names, and properties.

Generic assertions are too weak and don’t catch real functionality issues:

# Weak - only checks existence
assert len(references) > 0
assert isinstance(symbols, list)
assert symbol is not None

# Strong - checks exact expected results  
assert "greet" in symbol_names
assert references[0]["uri"].endswith("Main.scala")
assert symbol["name"] == "add"
assert symbol["kind"] == 12  # Function kind

This approach catches actual bugs in symbol detection, cross-file references, and language server functionality that generic checks miss. Focus on testing the specific symbols, files, and properties your code is supposed to find or produce. When testing language server functionality, verify that expected function names, type names, and file paths are present in results rather than just confirming non-empty responses.


Ensure complete documentation quality

Documentation should be comprehensive, clear, and provide all necessary context for understanding and using the code effectively. This includes several key aspects:

  1. Explain complex implementations: When code uses non-standard approaches, tricks, or unexpected patterns, the docstring must explain what these are and why they’re necessary. For example, if implementing custom handlers, loops, or configuration file writing, document the reasoning behind these choices.

  2. Use proper grammar and tone: Documentation should use correct English grammar and maintain a professional, accurate tone. Avoid subjective or potentially misleading language like “quick and dirty” when describing legitimate implementation approaches.

  3. Include essential details: Provide complete parameter information including units, types, and constraints. For example, specify whether a timeout parameter is in seconds, milliseconds, etc.

  4. Maintain consistency: Follow established documentation standards and formats that support examples and are compatible with documentation tools.

Example of good documentation:

def request_workspace_symbol(self, query: str, timeout: int = 30) -> Union[List[UnifiedSymbolInformation], None]:
    """
    Request symbols across the workspace using the Language Server Protocol.
    
    This method uses a custom retry mechanism with exponential backoff due to 
    server instability issues commonly seen with workspace symbol requests.
    
    :param query: The search string to filter symbols by
    :param timeout: Maximum wait time in seconds (default: 30)
    :return: List of matching symbols, or None if request fails
    """

This approach ensures that future developers can understand both what the code does and why it was implemented in a particular way.


Exception chaining practices

Always use exception chaining with raise ... from e when re-raising or wrapping exceptions to preserve the original error context and stack trace. This maintains debugging information and follows Python best practices for error propagation.

When catching and re-raising exceptions, avoid losing the original exception context. Exception chaining helps developers trace the root cause of errors through the entire call stack.

Example of proper exception chaining:

try:
    project_config = ProjectConfig.from_yml(Path(project_file_path))
except Exception as e:
    raise ValueError(f"Error loading project configuration from {project_file_path}: {e}") from e

Additionally, catch specific exception types rather than broad parent classes to avoid unintended behavior. For instance, catch PermissionError specifically rather than its parent OSError when you only want to handle permission issues.

Avoid over-decorating exceptions with unnecessary context when the original exception already contains sufficient information for debugging.


prefer marketplace actions

Before implementing custom tool installation steps in GitHub Actions workflows, check if there’s an existing setup action available on the GitHub Actions marketplace. Marketplace actions are typically more reliable, better maintained, and reduce workflow complexity compared to custom installation scripts.

When adding tool installation to your workflow, first search the marketplace for actions like setup-<tool> (e.g., setup-node, setup-python, setup-go). Only implement custom installation logic when no suitable marketplace action exists or when the existing action doesn’t meet your specific requirements.

Example of preferred approach:

# Preferred: Use marketplace action
- uses: actions/setup-node@v3
  with:
    node-version: '18'

# Avoid when marketplace alternative exists:
- name: Install Node.js manually
  run: |
    curl -fsSL https://nodejs.org/dist/v18.17.0/node-v18.17.0-linux-x64.tar.xz
    # ... custom installation steps

This approach reduces maintenance burden, improves reliability, and leverages community-tested solutions.


Balance configuration practicality

When making configuration changes, balance technical best practices with developer workflow requirements and real-world usage scenarios. Configuration decisions should not only be technically sound but also support practical development needs.

Consider both immediate technical implications and broader workflow impact:

Example from pyproject.toml management:

# Keep dev dependencies for workflow continuity
[project.optional-dependencies]
dev = [
    "pytest>=7.0.0",
    "pytest-asyncio>=1.0.0",
]

# Include dependencies that mirror customer usage patterns
dependencies = [
    "strands-agents-tools>=0.2.0,<1.0.0",  # Kept for realistic testing despite circular deps
]

Before removing or restructuring configuration elements, verify that the change won’t disrupt established developer workflows or compromise the realism of your testing environment.


coordinate concurrent initialization

When implementing expensive initialization operations that may be triggered concurrently, use a shared promise to coordinate multiple requests and prevent duplicate initialization. This pattern is especially important for operations like downloading dependencies, starting external processes, or establishing connections that take significant time to complete.

Store the initialization promise in a module-level variable and reuse it across concurrent calls. This ensures that multiple simultaneous requests will wait for the same initialization to complete rather than starting duplicate operations.

let jdtlsInit: Promise<ChildProcessWithoutNullStreams | undefined>

async spawn(root) {
  // ... validation logic ...
  
  if (jdtlsInit == null) {
    jdtlsInit = initializeJdtls(java, root)
  }
  const jdtlsServer = await jdtlsInit
  
  // ... use initialized resource ...
}

This approach prevents race conditions where “initialization could run twice or more” due to the time-consuming nature of the operation, and allows concurrent requests to “wait for concurrent initialization requests until the first one’s initialization is finished.”


Ensure proper error signaling

Errors must be communicated through appropriate mechanisms for their execution context. In CLI applications, use proper exit codes to indicate error states (non-zero for failures). For shell command execution, implement proper error handling to prevent unexpected crashes and provide graceful failure modes.

For CLI tools, always set appropriate exit codes when errors occur:

if (err) {
  spinner.stop("Upgrade failed", 1) // Exit code 1 for error
  // ... handle error logging
}

For shell commands, use error handling mechanisms like .quiet().nothrow() to prevent crashes:

await $`curl -L -o '${archivePath}' '${releaseURL}'`.quiet().nothrow()
await $`tar -xzf ${archivePath}`.cwd(distPath).quiet().nothrow()

This ensures that errors are properly signaled to the appropriate layer (operating system, calling process, or user interface) and prevents silent failures or unexpected crashes.


API consistency standards

Maintain consistent patterns across all API endpoints, including naming conventions, response structures, HTTP status codes, and interface design. This ensures a predictable and professional API surface that follows established conventions.

Key consistency requirements:

Example of consistent endpoint design:

@router.patch("/{customer_id}", response_model=CustomerDTO)
async def update_customer(params: CustomerUpdateParamsDTO) -> CustomerDTO:
    # Returns 200 OK with updated entity
    
@router.get("/{evaluation_id}")  
async def get_evaluation(evaluation_id: EvaluationId) -> ReadEvaluationResponse:
    # Dedicated response DTO, not direct internal model

This prevents API fragmentation and reduces cognitive load for API consumers by establishing predictable patterns they can rely on across all endpoints.


AI dependency management

When integrating AI libraries and SDKs, carefully manage dependencies by pinning versions with upper bounds to prevent breaking changes and minimize scope by implementing simple types locally when possible.

For version management, always specify upper bounds to avoid automatic consumption of breaking changes:

# Good: Pinned with upper bound
gemini = [
    "google-genai>=1.32.0,<2.0.0"
]

# Avoid: No upper bound
gemini = [
    "google-genai>=0.5.0"
]

For scope management, evaluate whether you truly need the full SDK or can implement simple components locally. Keep essential functionality like clients and error handling from the official SDK, but consider implementing basic types, enums, and configuration classes yourself to reduce dependency surface area. This approach balances functionality with dependency minimization while maintaining proper API communication and error handling.


Use parameter objects

Design API methods to accept parameter objects instead of individual parameters or complex optional fields. This approach makes interfaces more maintainable and flexible when requirements evolve, avoiding breaking changes when adding or removing fields.

Instead of destructuring parameters or using many optional fields:

// Avoid - breaks when parameters change
public async editCustomLanguageModelProvider({
  id,
  name,
  apiKey,
  baseUrl
}: {
  id: string;
  name?: string;
  apiKey?: string;
  baseUrl?: string;
}) {
  return this.invoke("edit-provider", { id, name, apiKey, baseUrl });
}

// Avoid - complex optional schemas
export const ProviderSettingSchema = z.object({
  apiKey: SecretSchema.optional(),
  vertexProjectId: z.string().optional(),
  azureEndpoint: z.string().optional(),
  // ... many optional fields
});

Prefer parameter objects and proper type modeling:

// Better - stable interface that accepts parameter objects
editCustomLanguageModelProvider(params: EditCustomLanguageModelProviderParams) {
  return this.invoke("edit-provider", params);
}

// Better - use unions for distinct parameter sets
export const ProviderSettingSchema = z.union([
  RegularProviderSettingSchema,
  VertexProviderSettingSchema,
  AzureProviderSettingSchema
]);

This pattern keeps method signatures stable while allowing the parameter types to evolve independently.


Scoped configuration defaults

When updating pyproject.toml (lint/type/dependency config), keep changes minimal and future-safe: enable/disable rules deliberately, scope suppressions to the smallest scope, avoid broad “select everything” patterns that can introduce unintended auto-fixes, remove redundant settings, and bound dependency versions.

Guidelines:

Example (lint config):

[tool.ruff.lint]
# Prefer explicit lists or ALL only with careful fix scoping.
select = ["ALL"]
# AND ensure you only fix the rules you explicitly trust:
# fixable = ["F", "E", "W"]  # example: opt-in only

[tool.flake8-builtins]
# Prefer per-line suppression over global ignores:
# "id" should usually be handled with:  some_var = id(...)  # noqa: A002
ignorelist = []

Example (mypy config):

[tool.mypy]
strict = true
# Avoid redundant flags like strict_bytes if strict already implies it.
# strict_bytes = true  # remove

Example (dependency bounds):

dependencies = [
  "langgraph>=0.6.0,<1.0.0",
]

avoid local imports

Place all import statements at the top of the file as global imports rather than importing modules within functions or methods. Local imports reduce code readability, complicate dependency tracking, and can indicate poor code organization.

Why this matters:

How to fix: Move all imports to the top of the file, organized in the standard order: standard library, third-party packages, then local modules.

Example:

# Bad - local imports
def _setup_runtime_dependencies(cls, logger, config, settings):
    import os  # Should be at top
    import platform  # Should be at top
    
    if platform.system() == "Windows":
        # ...

# Good - global imports  
import os
import platform

def _setup_runtime_dependencies(cls, logger, config, settings):
    if platform.system() == "Windows":
        # ...

Exceptions: Local imports are acceptable only in rare cases like:

In such cases, add a comment explaining why the local import is necessary.


separate model-specific configuration

Avoid mixing model-specific features with provider-level configuration or hard-coding model-specific logic in generic handlers. This creates architectural debt and maintenance burden as new AI models are added to the system.

Model-specific features (like thinking modes, specialized parameters, or model-unique behaviors) should be handled through dedicated model configuration layers rather than being embedded in provider settings or generic request handlers.

Example of what to avoid:

// DON'T: Model-specific config in provider schema
export const ProviderSettingSchema = z.object({
  apiKey: SecretSchema.optional(),
  // Model-specific feature mixed with provider config
  enableFlashThinking: z.boolean().optional(),
});

// DON'T: Hard-coded model logic in generic handlers
if (selectedProviderId === "google" && selectedModelName === "flash-2.5") {
  includeGoogleThoughts = settings.enableFlashThinking;
}

Instead, design model configuration to be modular and keep provider settings focused on provider-level concerns like authentication and endpoints. This approach scales better as new models with unique features are integrated.


Model specification accuracy

Ensure AI model configurations accurately reflect official specifications and avoid hardcoded assumptions. Model parameters, token limits, capabilities, and naming should match vendor documentation rather than using generic defaults.

Key practices:

Example of proper model configuration:

{
  description: 'Gemini 2.5 Flash 是 Google 最先进的主力模型',
  displayName: 'Gemini 2.5 Flash', // Clear, consistent naming
  id: 'google/gemini-2.5-flash',
  contextWindowTokens: 1_048_576, // Verified against official docs
  maxOutput: 65_535, // Separate input/output limits
  // No hardcoded parameter defaults
}

This prevents user confusion, billing errors, and ensures reliable model behavior across different AI providers.


Complete parameter documentation

Ensure all public functions and classes have comprehensive docstrings that include parameter descriptions, type hints, return value documentation, and references to related implementations. This significantly improves usability by helping developers understand how to use APIs correctly and find related code.

Key requirements:

Example:

def __init__(
    self,
    signature: Type["Signature"], 
    tools: list[Callable], 
    max_iters: Optional[int] = 5
) -> None:
    """
    Initialize the ReAct module for reasoning and acting with tools.
    
    Args:
        signature: The signature defining input and output fields for the module.
        tools: List of functions, callable classes, or dspy.Tool instances available to the agent.
        max_iters: Maximum number of reasoning iterations to perform. Defaults to 5.
        
    Example:
        ```python
        react = dspy.ReAct(signature="question->answer", tools=[get_weather])
        ```
    """

This approach helps developers understand APIs without needing to read implementation code, reduces support burden, and improves overall developer experience.


Null safety patterns

Implement proper null safety patterns to prevent runtime errors and unexpected behavior. This includes several key practices:

1. Handle Optional types correctly: When working with Union types containing None, extract the non-None type before type checking to avoid issubclass() errors with type annotations.

def _strip_optional(ann):
    """If ann is Union[..., NoneType] return the non‑None part, else ann."""
    if get_origin(ann) is Union and NoneType in get_args(ann):
        return next(a for a in get_args(ann) if a is not NoneType)
    return ann

2. Add dependency assertions for optional parameters: When optional parameters have dependencies on each other, use assertions to validate the relationships.

# Ensure dependent parameters are provided together
assert custom_instruction_proposer is None or reflection_lm is not None
# Or ensure at least one required parameter is provided  
assert custom_proposer is not None or reflection_lm is not None

3. Avoid mutable default arguments: Never use mutable objects as default parameter values, as they create shared state across function calls.

# Wrong - shared mutable state
history: list[Completions] = Field(default=[])

# Correct - each instance gets its own list
history: list[Completions] = Field(default_factory=list)

4. Use idiomatic null coalescing: Prefer concise Python patterns for handling None values.

# Prefer this concise pattern
self.interpreter = interpreter or PythonInterpreter()

# Over verbose None checks
self.interpreter = interpreter if interpreter is not None else PythonInterpreter()

5. Avoid unnecessary Optional annotations: Don’t use Optional for parameters that have default values, as the default already handles the None case.

These patterns prevent common null-related bugs and make code more robust and maintainable.


Optional configuration parameters

Make configuration parameters optional with sensible defaults instead of requiring mandatory values, and only enable optional features when explicitly configured through environment variables or user settings.

Many configuration issues arise from rigid parameter requirements that don’t accommodate different use cases. Parameters should be optional when they’re not always needed, allowing users flexibility while providing sensible defaults for common scenarios.

Key principles:

Example of flexible configuration:

def __init__(
    self,
    model: str,
    temperature: Optional[float] = None,  # Instead of fixed 0.0
    max_tokens: Optional[int] = None,     # Instead of fixed 1000
    reflection_lm: Optional[LM] = None,   # Optional when using custom proposer
):
    # Set defaults based on model capabilities
    if temperature is None:
        self.temperature = 0.0 if not is_reasoning_model(model) else None
    
    # Only use optional features when explicitly configured
    if reflection_lm is not None:
        with dspy.context(lm=reflection_lm):
            # Use reflection LM
    else:
        # Proceed without reflection LM

This approach prevents configuration errors while maintaining backward compatibility and providing users the flexibility they need for different scenarios.


Provider-based interface design

When designing interfaces that handle multiple providers or services, organize the API structure around provider-specific logic rather than mixing different provider handling in generic components. Use provider-based props structures and create dedicated components or methods for each provider type.

For props design, structure them by provider with clear typing:

// Instead of flat props mixing all providers
interface Props {
  posthogHost?: string;
  posthogToken?: string;
  ga4MeasurementId?: string;
}

// Use provider-based structure
interface Props {
  posthog?: { host: string; token: string } | false;
  ga4?: { measurementId: string } | false;
}

For component design, separate provider-specific logic:

// Instead of mixing provider logic in generic component
const GenericChecker = ({ provider, model }) => {
  if (provider === 'ollama') {
    // ollama-specific logic
  } else {
    // generic logic
  }
};

// Create dedicated components or methods
const OllamaChecker = ({ model }) => { /* ollama-specific logic */ };
const GenericChecker = ({ model }) => { /* generic logic */ };

This approach improves maintainability, reduces conflicts between different provider implementations, and makes the interface more predictable for consumers.


Limit postMessage data exposure

When using postMessage for inter-window communication, avoid sending raw event data or generic message types that could expose sensitive information. Instead, use specific, predefined message types and only send the minimum necessary data.

This prevents potential information leakage and reduces the attack surface for malicious code that might intercept or manipulate cross-window messages.

Example:

// Avoid: Sending raw event data
window.parent.postMessage({
  type: "dyad-shortcut-triggered",
  key: e.key.toLowerCase(),
  eventModifiers: {
    ctrl: e.ctrlKey,
    shift: e.shiftKey
  }
});

// Prefer: Specific message type with minimal data
window.parent.postMessage({
  type: "dyad-select-component-shortcut"
});

API documentation completeness

Ensure API documentation provides comprehensive, accurate information including limitations, complete workflow examples, and proper cross-references. API documentation should clearly state what endpoints do, what they don’t support, their constraints, and how they fit into larger workflows.

Key requirements:

Example of complete API workflow documentation:

// Upload file first
POST /api/v1/files
// Then use file_path in flow
{
  "tweaks": {
    "File-qYD5w": {
      "path": ["returned_file_path"]
    }
  }
}

This ensures developers have all necessary information to successfully integrate with the API without encountering unexpected limitations or missing steps in their implementation.


Maintain naming consistency

Ensure field names, method names, and identifiers are consistent across different contexts including cross-language SDKs, API specifications, and data structures. When multiple naming options exist, prioritize alignment with established patterns and accurate representation of the underlying functionality or data.

For cross-platform consistency, align naming conventions between different language implementations:

# Good: Aligns with TypeScript SDK naming
can_use_tool: ToolPermissionCallback | None = None

# Avoid: Inconsistent with other SDK implementations  
tool_permission_callback: ToolPermissionCallback | None = None

For API alignment, ensure field names match the actual data structure or API specification:

# Good: Matches actual API field name
total_cost_usd=data["total_cost_usd"]

# Avoid: Mismatched field name
cost_usd=data["cost_usd"]  # when API actually uses "total_cost_usd"

Proactively identify naming inconsistencies during code reviews and prioritize fixes that improve overall system coherence.


Document meaningful complexity

Documentation should add genuine value by explaining non-obvious behavior, complex approaches, or important context that isn’t immediately clear from the code itself. Remove redundant docstrings and comments that merely restate what the code obviously does, while ensuring that sophisticated algorithms, design decisions, or non-trivial implementations are properly documented.

For example, remove obvious documentation like:

class CortexEstimatingTokenizer(EstimatingTokenizer):
    """Token estimator for Cortex."""  # Redundant - class name is self-explanatory

But add explanatory documentation for complex approaches:

# This approach works by embedding each capability content separately and using 
# vector similarity search, which is more efficient than retrieving ALL documents 
# and sorting manually because it leverages the database's optimized vector operations
async def find_relevant_capabilities(self, query: str, available_capabilities: Sequence[Capability]):

Focus documentation efforts on clarifying the “why” and “how” of complex logic rather than describing the “what” that’s already evident from well-written code.


Implement graceful error handling

Replace assertions, unhandled exceptions, and error-suppression mechanisms with proper error handling that provides clear, actionable feedback to users. Instead of allowing applications to crash or silently hide issues, implement structured error handling that communicates what went wrong and suggests next steps.

For example, replace crash-prone assertions:

# Avoid - can crash ungracefully
assert await params.indexer.index(container)

# Prefer - graceful handling with clear messaging
try:
    success = await params.indexer.index(container)
    if not success:
        raise RuntimeError("Failed to index container. Check your configuration and try again.")
except Exception as e:
    logger.error(f"Indexing failed: {e}")
    raise RuntimeError("Indexing operation failed. Please verify your setup and retry.") from e

Similarly, avoid broad error suppression (like blanket ignore_missing_imports) that can mask real issues. Handle specific error cases individually to maintain visibility into potential problems while still providing a good user experience.


remove unnecessary authentication

Avoid initializing authentication mechanisms, credentials, or identity objects when they are not actually used in the code. This follows the security principle of least privilege and reduces potential attack surface by minimizing credential exposure.

In test files particularly, only set up authentication when the test actually makes API calls or requires authenticated operations. Unnecessary authentication setup can lead to credential leakage and violates security best practices.

Example of what to avoid:

// Bad: Creating identity when no API calls are made
let identity: Identity;
beforeAll(async () => {
  identity = await idmux({
    name: "robots-txt", 
    concurrency: 100,
    credits: 1000000,
  });
});

// Good: Remove unused authentication setup
// (no identity initialization needed if no API calls)

Always review whether authentication setup is actually necessary for the functionality being implemented or tested.


maintain code consistency

Ensure consistent patterns, formatting, and conventions throughout the codebase. Inconsistencies in code style create confusion, reduce readability, and make maintenance more difficult.

Key areas to maintain consistency:

Import Organization: Group imports consistently and separate them with blank lines:

# Standard library imports
import os
from pathlib import Path

# Third-party imports  
from lagom import Container
from pytest import fixture

# Internal imports
from emcie.server.core.common import ItemNotFoundError, JSONSerializable

Parameter Formatting: Use trailing commas consistently for multi-line parameters:

def create_session(
    self,
    end_user_id: EndUserId,
    client_id: str,
) -> Session:  # trailing comma enables easy additions

Naming and Capitalization: Choose one scheme and apply it consistently across similar contexts:

# Consistent predicate capitalization
"The user asks about weather"  # or
"the user asks about weather"  # but not mixed

Code Patterns: When establishing a pattern (like error handling, logging format, or method signatures), apply it uniformly across the codebase. Before introducing variations, consider if the existing pattern should be updated everywhere or if the new context truly requires different handling.

Review your changes to ensure they follow the same conventions used elsewhere in the codebase. When in doubt, search for similar code patterns and match their style.


Extract reusable components

Extract utilities, types, constants, and shared logic into dedicated modules to improve code maintainability and reduce duplication. When you find yourself writing similar code in multiple places, or when you have magic strings/numbers, inline type definitions, or mixed business logic, extract them into appropriate shared locations.

Examples of what to extract:

// Before: Magic string and inline logic
throw new TRPCError({ code: 'BAD_REQUEST', message: 'Origin File Not Found' });

// After: Extract constant
const ERROR_MESSAGES = {
  ORIGIN_FILE_NOT_FOUND: 'Origin File Not Found'
} as const;

throw new TRPCError({ code: 'BAD_REQUEST', message: ERROR_MESSAGES.ORIGIN_FILE_NOT_FOUND });

This practice reduces maintenance burden, prevents inconsistencies, and makes code more testable and reusable.


Optimize database column types

Choose appropriate data types for database columns to improve storage efficiency and performance. Use auto-incrementing identity columns for primary keys when there are no specific semantic requirements, and select column types with proper constraints based on expected data characteristics.

For primary keys without semantic meaning, prefer identity columns over text-based custom IDs:

// Preferred: Auto-incrementing identity
id: integer('id').primaryKey().generatedByDefaultAsIdentity(),

// Avoid: Custom text-based IDs when not semantically required
id: text('id').$defaultFn(() => idGenerator('usageRecords', 16)).primaryKey(),

For string columns, use varchar with appropriate length constraints instead of unbounded text types:

// Preferred: Constrained varchar for better storage
callType: varchar('call_type', { length: 256 }).notNull(),

// Avoid: Text with enum configuration when varchar suffices
callType: text('call_type', { enum: ['chat', 'history_summary'] }).notNull(),

This approach reduces storage overhead, improves query performance, and provides better data validation at the database level.


use robust test selectors

E2E tests should use stable, reliable selectors and waiting strategies to prevent flaky test failures. Prefer test IDs over CSS class names for element selection, as class names may change during refactoring and break tests. Use condition-based waits instead of arbitrary timeouts to ensure tests wait for the actual state changes rather than fixed time periods.

Example of robust selector usage:

// Avoid: brittle CSS class selector
const chatListItems = await po.page.locator(".chat-list-item");

// Prefer: stable test ID selector  
const chatListItems = await po.page.getByTestId("chat-list-item");

// Avoid: arbitrary timeout
await po.page.waitForTimeout(500);

// Prefer: condition-based wait
await po.page.waitForSelector('[data-testid="search-results"]');

This approach makes tests more maintainable and reduces false failures caused by timing issues or UI refactoring.


Verify configuration documentation

Ensure that all configuration documentation accurately reflects the actual implementation, especially for build tools, tech stack, and architectural decisions. When documenting configurations that deviate from standard practices, provide clear rationale for the choices made.

Key areas to verify:

Example from the codebase:

# Incorrect documentation
- **Build Tools**: Turbo, Vite

# Corrected documentation  
- **Build Tools**: Turbo (monorepo), Turbopack (Next.js dev), Webpack (Next.js prod)
- **Testing**: Vitest (uses Vite internally, but Vite not used directly in main build)

For architectural decisions like using multiple stores instead of the recommended single store pattern, document the complexity-based rationale and provide guidance on when each approach should be used. This prevents confusion during development and helps new team members understand the reasoning behind configuration choices.


Keep related documentation content together on a single page rather than fragmenting it across multiple pages. When users need to understand a complete concept or workflow, they should be able to find all relevant information in one location without having to navigate between multiple pages.

Avoid creating separate pages for closely related concepts that are better understood together. Instead of splitting content and creating circular cross-references, consolidate the information and use a single authoritative source.

For example, instead of having component parameters on one page and detailed usage instructions on another page that links back to the first, put both the parameters and usage instructions on the same page. Use clear section headings to organize the content within the page.

When you do need to reference information from another page, ensure there’s genuine value in the separation. Avoid links that simply point back to pages that already link to the current page, creating circular references with no additional context.

If a page becomes too long due to consolidation, consider whether the content represents multiple distinct concepts that genuinely warrant separate pages, or if better organization within a single page (using sections, tabs, or collapsible content) would serve users better.


Prevent code injection vulnerabilities

When evaluating user-provided code or handling dynamic content, implement strict security measures to prevent malicious code execution and unauthorized access. This includes whitelisting allowed modules/imports, validating input integrity, and properly handling sensitive data.

Key practices:

  1. Whitelist imports: Restrict which modules can be imported in user code to prevent access to dangerous functionality
  2. Secure evaluation: Use safe evaluation methods and validate code integrity before execution
  3. Credential scrubbing: Clear sensitive data from memory after use and document security measures clearly
  4. Input validation: Ensure fallback mechanisms don’t create security bypasses

Example of secure code evaluation:

# Whitelist allowed modules before evaluation
ALLOWED_MODULES = {'math', 'datetime', 'json'}

def eval_custom_component_code(code: str):
    # Validate imports against whitelist
    if not validate_imports(code, ALLOWED_MODULES):
        raise SecurityError("Unauthorized module import detected")
    
    # Generate secure hash to prevent spoofing
    code_hash = hashlib.sha256(code.encode("utf-8")).hexdigest()
    
    # Evaluate in restricted environment
    return safe_eval(code, restricted_globals)

# Clear credentials after setup
finally:
    # Scrub credentials from in-memory settings after setup
    # Prevents users from gaining access to admin credentials by accessing environment variables
    settings_service.auth_settings.reset_credentials()

This prevents attackers from injecting malicious code, accessing unauthorized modules, or exploiting credential exposure vulnerabilities.


precise workflow conditions

When implementing conditional logic in CI workflows, ensure boolean expressions are precise and comprehensive to avoid unintended workflow execution or bypassing. Use multiple filter conditions combined with logical operators to create accurate triggers based on file changes.

For example, when creating a docs-only bypass condition, verify that documentation files changed AND no code files changed:

docs-only: ${{ steps.filter.outputs.docs == 'true' && steps.filter.outputs.python != 'true' && steps.filter.outputs.frontend != 'true' }}

Then use this condition in workflow steps:

elif [[ "${{ needs.check-nightly-status.outputs.should-proceed }}" != "true" && "${{ github.event_name }}" != "workflow_dispatch" && "$DOCS_ONLY" != "true" ]]; then

This prevents workflows from running unnecessarily on documentation-only changes while ensuring they still execute for any code modifications. Always test conditional logic thoroughly to ensure workflows behave as expected across different change scenarios.


Language-agnostic configuration design

Design configuration parameters to be language-agnostic when possible, use established configuration objects, and maintain consistency across language server implementations. Avoid language-specific CLI options or constructor parameters when the functionality could apply broadly.

Key principles:

  1. Use enum values instead of class names for language server-specific settings to make them user-friendly
  2. Make CLI options generic - use --ls-max-memory instead of --max-memory for Intelephense-specific features
  3. Leverage existing configuration objects like LanguageServerConfig instead of adding new constructor parameters
  4. Handle configuration evolution properly - force user decisions on new settings rather than assuming defaults, and provide clear error messages for missing required keys

Example of good configuration design:

# Good: Use enum value for LS-specific settings
custom_settings = self._solidlsp_settings.ls_specifics.get("intelephense", {})

# Good: Generic CLI option that could apply to multiple language servers  
@click.option("--ls-max-memory", type=int, help="Maximum memory (MB) for language server")

# Good: Use existing config object
def __init__(self, config: LanguageServerConfig, logger: LanguageServerLogger, ...):
    max_memory = config.max_memory  # Instead of separate parameter

# Good: Force user decision on new config
if "ignore_all_files_in_gitignore" not in config_dict:
    raise ValueError("Missing required config: ignore_all_files_in_gitignore")

This approach ensures configuration remains maintainable, user-friendly, and consistent as the codebase grows across multiple language servers.


AI model chunk sizing

When configuring text processing components that work with AI embedding models, proactively consider tokenization limits and chunk size constraints. Many embedding models have practical token limits that are lower than their theoretical maximums, and text splitting components may not enforce exact chunk sizes.

Always test your chunk size configuration with your specific embedding model to avoid tokenization errors. If you encounter issues, reduce chunk sizes (try 500 tokens or less), adjust overlap settings, or modify separator strategies.

Example configuration considerations:

# Split Text component
chunk_size: 500  # Conservative size for embedding models
chunk_overlap: 50  # Reasonable overlap
separator: "\n\n"  # Common separator for consistent splits

# Test with your embedding model
# Inspect component output to verify actual chunk sizes

Document any model-specific limitations in your component descriptions and provide fallback strategies. This is especially important for NVIDIA embedding models like nvidia/nv-embed-v1 and other specialized AI models that may have stricter practical limits than advertised.


LLM provider abstraction

When integrating with different LLM providers, create proper base class abstractions that filter and validate parameters based on each provider’s capabilities. Follow established architectural patterns rather than creating custom configuration approaches.

Create provider-specific base classes that define supported parameters and filter hints accordingly. This prevents passing unsupported parameters to APIs and maintains consistency across adapters.

Example implementation:

class OpenAIBaseSchematicGenerator(BaseSchematicGenerator[T], ABC):
    supported_arguments = ["temperature", "logit_bias", "max_tokens"]
    
    async def generate(self, prompt: str, hints: Optional[dict[str, Any]] = None):
        filtered_hints = {}
        if hints:
            for k, v in hints.items():
                if k not in self.supported_arguments:
                    self.logger.warning(f"Key '{k}' is not supported. Skipping...")
                    continue
                filtered_hints[k] = v
        
        response = await self._client.chat.completions.create(
            model=self._get_model_name(),
            **filtered_hints
        )

This approach allows code to specify provider requirements (“I want an OpenAI model”) while ensuring only valid parameters are passed to each API. Use existing patterns like CustomSchematicGenerator and FallbackSchematicGenerator rather than implementing custom configuration systems that diverge from established adapter architectures.


Use idempotent migrations

Always use defensive programming patterns in migration scripts to ensure they can be executed multiple times without errors. This prevents failures during re-execution scenarios and makes migrations more robust.

Key patterns to implement:

Example:

-- Good: Idempotent migration
CREATE TABLE IF NOT EXISTS "chat_groups" (
    "id" text PRIMARY KEY NOT NULL,
    "title" text
);

ALTER TABLE "messages" ADD COLUMN IF NOT EXISTS "group_id" text;

-- Bad: Non-idempotent migration
CREATE TABLE "chat_groups" (
    "id" text PRIMARY KEY NOT NULL,
    "title" text
);

ALTER TABLE "messages" ADD COLUMN "group_id" text;

This approach ensures migrations won’t fail with “already exists” errors when run multiple times, which is common during development, testing, and deployment scenarios.


safe environment variable access

Always use os.environ.get() with appropriate defaults instead of direct dictionary access to prevent KeyError exceptions when environment variables are not set. Additionally, extract configuration constants and magic numbers to named module-level variables for better maintainability and consistency.

This pattern prevents runtime crashes when optional environment variables are missing and makes configuration values more discoverable and maintainable.

Problematic pattern:

api_version = os.environ["AZURE_API_VERSION"] or "2024-08-01-preview"  # KeyError if not set
await asyncio.sleep(10)  # Magic number

Preferred pattern:

# Module-level constants
DEFAULT_API_VERSION = "2024-08-01-preview"
EXTENDED_PERIOD_OF_TIME = 10

# Safe environment variable access
api_version = os.environ.get("AZURE_API_VERSION", DEFAULT_API_VERSION)
await asyncio.sleep(EXTENDED_PERIOD_OF_TIME)

This approach ensures graceful handling of missing environment variables while making configuration values explicit and easily adjustable across the codebase.


Simplify error flows

Avoid complex, multi-layered error handling that obscures error origins and makes debugging difficult. Each error should be handled at the most appropriate level without unnecessary re-parsing or nested try-catch blocks.

Problems with complex error flows:

Instead, handle errors close to their source and use clear, single-responsibility error handling:

// ❌ Avoid: Complex nested error handling
async parseFile(fileId: string): Promise<LobeDocument> {
  try {
    const { filePath, file, cleanup } = await this.fileService.downloadFileToLocal(fileId);
    try {
      const fileDocument = await loadFile(filePath);
      // ... processing
    } catch (error) {
      console.error(`File parsing failed:`, error);
      throw error;
    } finally {
      cleanup();
    }
  } catch (error) {
    console.error(`File not found:`, error);
    throw error;
  }
}

// ✅ Better: Single-level error handling with clear responsibility
async parseFile(fileId: string): Promise<LobeDocument> {
  const { filePath, file, cleanup } = await this.fileService.downloadFileToLocal(fileId);
  
  try {
    const fileDocument = await loadFile(filePath);
    // ... processing
    return document;
  } catch (error) {
    console.error(`[${file.name}] File parsing failed:`, error);
    throw error;
  } finally {
    cleanup();
  }
}

Keep error handling flows simple and direct to improve code maintainability and debugging experience.


avoid hardcoded configuration values

Configuration values such as URLs, endpoints, timeouts, and environment-specific settings should never be hardcoded in source code. Instead, they should be read from configuration files, environment variables, or other configurable sources to ensure flexibility across different environments and deployments.

Hardcoded values make applications inflexible and difficult to deploy across different environments. They also make it impossible for users to customize behavior according to their specific needs.

Example of what to avoid:

// Bad: hardcoded URL
const response = await fetch("http://localhost:11434/api/tags")

// Good: configurable URL
const baseUrl = config.ollama?.baseUrl || "http://localhost:11434"
const response = await fetch(`${baseUrl}/api/tags`)

When implementing configuration options, ensure they behave consistently across all applicable contexts. For instance, if a timeout setting is provided, it should apply regardless of the provider type, unless there are specific technical constraints that prevent this.


AI model configuration consistency

Maintain consistent AI model metadata and configuration across all providers to prevent breaking changes and ensure reliable behavior. When adding new models or updating existing ones, always update corresponding token limits, default configurations, and provider mappings simultaneously.

Key practices:

Example from the discussions:

// Good: Centralized model limits
static MODEL_SPECIFIC_LIMITS: Lazy<Vec<(&'static str, usize)>> = Lazy::new(|| {
    vec![
        ("gpt-4o", 128_000),
        ("claude-3-5-sonnet", 200_000),
        ("moonshotai/kimi-k2-instruct", 131_072), // Added with corresponding limit
    ]
});

// Good: Using constants for defaults
const ANTHROPIC_DEFAULT_FAST_MODEL: &str = "claude-3-5-haiku-latest";
model = model.with_fast(ANTHROPIC_DEFAULT_FAST_MODEL);

This prevents user disruption from inconsistent model behavior and ensures that model updates don’t break existing workflows or introduce undefined behavior due to missing configuration.


Environment variable documentation

Ensure comprehensive and accurate documentation of environment variables, including cross-references, auto-detection behavior, and deployment context. When documenting configuration options, always provide links to the environment variables page and specify the exact variable name. Include information about auto-detected variables that Langflow recognizes by default, and provide deployment-specific context such as Docker usage.

For example, when documenting file upload configuration:

Increased the default maximum size for file uploads from 100 MB to 1024 MB.
You can configure this with the [`LANGFLOW_MAX_FILE_SIZE_UPLOAD`](/environment-variables#LANGFLOW_MAX_FILE_SIZE_UPLOAD) environment variable.

When running a Langflow Docker image, the `-e` flag sets system environment variables:
```bash
docker run -e LANGFLOW_MAX_FILE_SIZE_UPLOAD=2048 langflow

Additionally, document the precise behavior and interactions between related environment variables. For complex variables like authentication settings, clearly explain conditional behavior:

If set to `true`, and `LANGFLOW_AUTO_LOGIN` is set to `true`, skips authentication and allows automatic login as the superuser. If `LANGFLOW_AUTO_LOGIN` is `false`, has no effect.

This ensures users understand not just what variables exist, but how to use them effectively across different deployment scenarios and how they interact with other configuration options.


default least permissive

When implementing security controls, always default to the most restrictive option and require explicit opt-in for more permissive behavior. This applies to authentication mechanisms, user permissions, and security scanning workflows.

For authentication, use centralized middleware instead of manual verification in each handler:

// Instead of manual verification in each handler
async fn start_agent(
    State(state): State<Arc<AppState>>,
    headers: HeaderMap,
    Json(payload): Json<StartAgentRequest>,
) -> Result<Json<StartAgentResponse>, (StatusCode, Json<ErrorResponse>)> {
    verify_secret_key(&headers, &state).map_err(|_| {
        // ... error handling
    })?;
    // ... handler logic
}

// Use middleware for consistent auth across all protected routes

For permission systems, implement security checks before user interaction and default to the most restrictive option available. When multiple security mechanisms exist (like permission checking and security scanning), apply the least permissive result from all checks.

This principle ensures that security is the default state, reducing the risk of accidentally exposing functionality or data through overly permissive configurations.


eliminate code duplication

Identify and eliminate duplicated code by extracting shared functionality to appropriate locations. When multiple components or code sections perform identical operations, consolidate the logic into a single, reusable location such as a parent component, utility function, or shared module.

Key strategies:

Example of eliminating platform duplication:

// Before: Duplicated code for different platforms
if (detectedPlatform === "powershell") {
  const authHeader = ` -H "x-api-key: YOUR_API_KEY_HERE"`;
  uploadCommands.push(`curl -X POST "${baseUrl}/api/v1/files/upload/${flowId}"${authHeader} -F "file=@your_image.jpg"`);
} else {
  const authHeader = ` -H "x-api-key: YOUR_API_KEY_HERE"`;
  uploadCommands.push(`curl -X POST "${baseUrl}/api/v1/files/upload/${flowId}"${authHeader} -F "file=@your_image.jpg"`);
}

// After: Extracted shared logic
const authHeader = ` -H "x-api-key: YOUR_API_KEY_HERE"`;
uploadCommands.push(`curl -X POST "${baseUrl}/api/v1/files/upload/${flowId}"${authHeader} -F "file=@your_image.jpg"`);

This approach improves maintainability, reduces the likelihood of inconsistencies, and makes the codebase more readable by eliminating redundant patterns.


Protect sensitive data

Always identify and properly protect sensitive data fields in your code. Sensitive information includes IP addresses, API keys, authentication tokens, personal identification data, and high-privilege credentials.

Key practices:

Example of proper sensitive data handling:

// Bad: Storing IP address unnecessarily
export const usageRecords = pgTable('usage_records', {
  ipAddress: text('ip_address'), // Remove this sensitive field
});

// Good: Encrypt sensitive user data
const encryptedKeyVaults = encrypt(userKeyVaults); // Encrypt API keys before storage

// Good: Be cautious with webhook data containing sensitive fields
const parsed = JSON.parse(payloadString) as CasdoorWebhookPayload;
// Be aware this may contain accessKey, accessSecret, idCard, etc.

Always ask: “Does this field contain sensitive information?” and “How can I minimize exposure while maintaining functionality?”


containerize sensitive workflows

Use containerization to isolate operations that could access sensitive data, modify critical systems, or execute untrusted code. Containers provide a secure boundary that prevents workflows from affecting the host environment or accessing resources beyond their intended scope.

This practice is essential when:

Example implementation:

# GitHub Actions workflow
- name: Scan recipes in isolation
  run: |
    docker run --rm \
      --network none \
      --read-only \
      -v $(pwd)/recipes:/recipes:ro \
      recipe-scanner:latest \
      scan /recipes
# Development workflow
container-use stdio
# Run a container agent to add a feature to save my to-do list data in sqlite, 
# build and run tests, but use a separate Git branch so my main code stays safe.

Always prefer containerized execution over direct host execution when dealing with potentially unsafe operations, ensuring that failures or security issues remain contained within the isolated environment.


Optimize hook dependencies

Understand React’s built-in optimizations and avoid unnecessary dependencies in hook arrays. React guarantees that state setters maintain referential stability across re-renders, so they don’t need to be included in dependency arrays. Similarly, ref objects themselves don’t change - only their .current property does, and changes to .current don’t trigger re-renders, so refs don’t need to be in dependency arrays either.

Use useCallback when functions are passed to dependency arrays of other hooks, but avoid premature optimization. As one developer noted: “We could have gotten away with keeping this a function re-created on every render… but we’d have to suppress some warnings and potentially invite some future bugs. Using hooks for all of them seemed the right way to go.”

Example of proper dependency management:

const performSubmit = useCallback(
  (text?: string) => {
    // Function logic here
  },
  [
    allDroppedFiles,
    displayValue,
    handleSubmit,
    // Don't include: setters, refs, or other stable values
  ]
);

useEffect(() => {
  if (recipeAccepted && initialPrompt && messages.length === 0) {
    setDisplayValue(initialPrompt); // setter doesn't need to be in deps
    hasSetRecipePromptRef.current = true; // ref doesn't need to be in deps
  }
}, [recipeAccepted, initialPrompt, messages.length]); // Only include values that actually change

API header management

Establish consistent patterns for handling headers in API clients to avoid duplication and ensure predictable behavior. When designing API client interfaces, clearly define header precedence rules and avoid setting headers in multiple locations unless absolutely necessary.

Key principles:

  1. Header Precedence: Decide whether persistent headers should override request-specific headers or vice versa. Document this decision clearly. As one developer noted: “if the provider made the effort to set a persistent header, that it shouldn’t be overridden.”

  2. Avoid Duplication: Don’t set the same headers in multiple places unless there’s a technical requirement. If duplication is necessary, document why both locations are needed.

  3. Clean Construction: Use efficient header object construction patterns instead of multiple mutations.

Example of clean header construction:

// Preferred: Clean, efficient construction
const headers = {
  'anthropic-beta': betas.length > 0 ? betas.join(",") : undefined,
  'idempotency-key': taskId && checkpointNumber !== undefined ? this.getIdempotencyKey(taskId, checkpointNumber) : undefined,
}

// Avoid: Multiple object mutations
const headers: Record<string, string> = {}
if (betas.length > 0) {
  headers["anthropic-beta"] = betas.join(",")
}
if (taskId && checkpointNumber !== undefined) {
  headers["idempotency-key"] = this.getIdempotencyKey(taskId, checkpointNumber)
}

This ensures API clients are maintainable, predictable, and efficient in their header management.


Incremental CI development

Develop CI/CD workflows incrementally, starting with simpler versions and adding complexity gradually. This approach makes testing easier and reduces the risk of introducing breaking changes. When adding new steps or jobs, consider their performance impact and dependencies on other workflow components.

Start by implementing basic functionality first, then progressively add advanced features like release automation or complex build matrices. For example, when creating a new build workflow, begin with a single architecture or platform, test thoroughly, then expand to multiple targets.

When adding new CI steps, evaluate whether they should run in parallel jobs or be integrated into existing ones based on dependencies and performance considerations. Monitor build times and be prepared to refactor job organization if performance degrades.

Example approach:

# Phase 1: Basic build only
- name: build
  run: cargo build --release

# Phase 2: Add testing after basic build is stable  
- name: test
  run: cargo test

# Phase 3: Add release automation once build/test is proven
- name: release
  if: github.ref == 'refs/heads/main'
  run: ./scripts/release.sh

This incremental strategy helps identify issues early and makes workflow changes easier to debug and maintain.


Use established logging libraries

Avoid using print statements (println!, eprintln!) or custom logging implementations for application logging. Instead, use established logging libraries like tracing that provide proper log levels, structured output, and configurable destinations.

Print statements bypass logging configuration and cannot be controlled at runtime. Custom logging implementations are error-prone and lack the features of mature libraries. Established logging libraries offer better performance, structured data support, and integration with monitoring systems.

Replace debug prints with appropriate log levels:

// Instead of this:
println!("🔒 SecurityManager::new() called - checking if security should be enabled");

// Use this:
tracing::debug!("SecurityManager::new() called - checking if security should be enabled");

For custom logging needs, extend existing logging infrastructure rather than creating new implementations:

// Instead of rolling your own:
pub fn log_debug_event(event: &str) {
    // custom file writing logic...
}

// Use tracing with appropriate configuration:
tracing::debug!(event = %event, "debug event occurred");

This ensures consistent logging behavior, proper log level control, and integration with the application’s logging configuration.


inline external dependencies

For security-critical applications, prefer inlining external dependencies (JavaScript libraries, CSS frameworks) rather than loading them from CDNs or external sources at runtime. This approach eliminates risks from compromised external sources, network-based attacks, and supply chain vulnerabilities.

Inlining dependencies provides “zero risk” by ensuring complete control over the code being executed and removing external attack vectors. This is especially important for core functionality and recommended features that users rely on.

Example:

<!-- Preferred: Inline the minified library -->
<script>
    {{CHART_MIN}}
    // Minified D3.js or other library code here
</script>

<!-- Avoid: External CDN dependency -->
<script src="https://cdn.example.com/d3.min.js"></script>

Consider external dependencies acceptable for optional third-party extensions where users make explicit choices about trust, but default to inlined dependencies for built-in functionality.


avoid panics and expects

Replace panic-inducing operations like .expect() and .unwrap() with proper error handling that allows graceful recovery or controlled failure. Panics can crash entire applications and provide poor user experience, especially in server environments where “it will kill goosed and it is all over.”

Instead of panicking, use Result types, .ok_or() methods, or provide sensible defaults:

// Instead of panicking:
let stderr = stderr.take().expect("should have a stderr handle");

// Use proper error handling:
let stderr = stderr.take().ok_or_else(|| 
    ExtensionError::ConfigError("Missing stderr handle".to_string()))?;

// Or provide defaults when appropriate:
fn get_current_working_dir() -> PathBuf {
    std::env::current_dir()
        .unwrap_or_else(|_| get_home_dir())
}

When encountering unexpected None values or potential failures, log the issue and either return an appropriate error or continue with a reasonable fallback. This approach makes applications more resilient and provides better debugging information when issues occur.


Avoid hardcoded configuration values

Replace hardcoded configuration values with configurable parameters to improve flexibility and maintainability. Hardcoded timeouts, domain strings, validation constraints, and operational parameters should be exposed as advanced inputs, environment variables, or settings.

Examples of improvements:

# Instead of hardcoded values:
response = client.predictions.wait(response.id, timeout=600)
domain = "audio.transcription"

# Use configurable parameters:
IntInput(
    name="timeout_seconds",
    display_name="Timeout (seconds)",
    value=600,
    advanced=True,
    info="Maximum time to wait for processing completion"
)

DropdownInput(
    name="domain",
    display_name="Processing Domain",
    options=["audio.transcription", "audio.diarization"],
    value="audio.transcription",
    advanced=True
)

This approach enables users to customize behavior for their specific use cases, supports different environments (development vs production), and makes the code more maintainable by centralizing configuration management.


Safe null access patterns

Always use safe access patterns to prevent runtime errors when dealing with potentially null or undefined values. Instead of direct access that can raise KeyError or IndexError, use defensive programming techniques.

For dictionary access, prefer dict.get(key) or check key in dict before accessing:

# Bad - raises KeyError if key missing
if not os.environ["LITELLM_PROVIDER_MODEL_NAME"]:
    
# Good - safe access patterns  
if "LITELLM_PROVIDER_MODEL_NAME" not in os.environ:
# or
if not os.environ.get("LITELLM_PROVIDER_MODEL_NAME"):

For collections, validate bounds before indexing:

# Bad - IndexError if empty
generation = event_generation_result.generations[0]

# Good - check bounds first
if not event_generation_result.generations:
    raise ValueError("No generations available")
generation = event_generation_result.generations[0]

Use null coalescing for function parameters:

# Ensure non-null defaults
arguments = tc.arguments or {}
hints = hints or {}  # instead of Optional[dict] = None

This prevents common runtime exceptions and makes code more robust when handling optional or potentially missing data.


Use definite assignment assertions

When you’re certain a value will be initialized but TypeScript can’t infer this, use the definite assignment assertion operator (!) instead of as any or suppressing type errors. This maintains type safety while avoiding unnecessary null checks throughout your codebase.

Avoid this pattern:

// Creates unnecessary undefined checks everywhere
#agent: Agent<Env, State> | undefined;

// Or suppressing valid type concerns
// @ts-expect-error TODO: fix this type error
await this._drainStream(response.body);

// Or forcing types unsafely  
}) as any

Instead, use definite assignment assertions when you know the value will be there:

// Tells TypeScript "trust us, it'll always be there"
#agent: Agent<Env, State>!;

Or add proper null checks when the value might actually be null:

// When the value could legitimately be null/undefined
if (response.body) {
  const reader = response.body.getReader();
  // ... handle the stream
}

This approach maintains TypeScript’s null safety benefits while eliminating false positives that lead to code pollution or unsafe type assertions.


optimize frequent operations

Identify code paths that execute frequently and ensure they use performant, non-blocking solutions. Frequent operations should avoid expensive database queries, CPU-intensive synchronous processing, or anything that can block the event loop.

For high-frequency database operations, use caching solutions like Redis instead of direct database queries. For CPU-intensive tasks like HTML parsing that run often, consider moving the logic to more performant runtimes or libraries.

Example of what to avoid:

// Bad: DB query on every job insert
const { data: recentNotifications } = await supabase_service
  .from("user_notifications")
  .select("*")
  .eq("team_id", team_id)
  .gte("sent_date", pastDate.toISOString());

Example of better approach:

// Good: Use Redis for frequent lookups
const recentNotifications = await redis.get(`notifications:${team_id}`);

Before implementing any operation that will run frequently, evaluate its performance impact and consider alternatives like caching, background processing, or more efficient libraries/runtimes.


validate IPC inputs

Always validate and sanitize inputs to IPC handlers to prevent unauthorized access to system resources. Implement allowlists or blocklists for file system operations and maintain secure Electron configuration.

IPC handlers that accept file paths, URLs, or other system resources can be exploited if not properly validated. Even with secure Electron configuration (context isolation enabled, node integration disabled), IPC endpoints remain potential attack vectors.

Example of vulnerable code:

ipcMain.handle('open-directory-in-explorer', async (_event, path: string) => {
  // Dangerous: path can be any directory on the machine
  shell.openPath(path);
});

Secure implementation:

const ALLOWED_DIRECTORIES = ['/safe/app/directory', '/user/documents'];

ipcMain.handle('open-directory-in-explorer', async (_event, path: string) => {
  // Validate path is in allowlist
  const normalizedPath = path.normalize(path);
  if (!ALLOWED_DIRECTORIES.some(allowed => normalizedPath.startsWith(allowed))) {
    throw new Error('Directory access not permitted');
  }
  shell.openPath(normalizedPath);
});

Ensure your Electron app maintains secure configuration: context isolation enabled, node integration disabled, web security enabled, and controlled API surface through preload scripts with explicit method exposure.


avoid internal object access

Avoid accessing internal object attributes like __dict__ or using unpacking syntax when cleaner alternatives exist. Instead, prefer stable public methods or direct assignment patterns that don’t couple to object internals.

For object attribute access, use stable methods when available:

# Avoid
"usage": response.usage.__dict__ if hasattr(response, "usage") else None

# Prefer
"usage": response.usage.model_dump() if hasattr(response, "usage") else None
# or explicitly map known fields
"usage": {"tokens": response.usage.tokens, "cost": response.usage.cost} if hasattr(response, "usage") else None

For list/tuple assignments, use direct assignment when possible:

# Avoid
outputs = [*BaseFileComponent._base_outputs]

# Prefer  
outputs = BaseFileComponent._base_outputs

This approach reduces coupling to implementation details, improves maintainability, and makes code more resilient to internal API changes.


Database session lifecycle

Ensure all database operations and access to database objects occur within the appropriate session scope. Database objects become invalid once their session is closed, leading to runtime errors when accessed later.

Always perform database queries and access object attributes within the same session context. If you need to use database object attributes after the session, extract the needed values while the session is still active.

Example of the problem:

async def update_build_config(self, build_config, field_value, field_name=None):
    if field_name == "knowledge_base":
        async with session_scope() as db:
            current_user = await get_user_by_id(db, self.user_id)
        # BAD: Accessing current_user.username after session is closed
        kb_user = current_user.username

Correct approach:

async def update_build_config(self, build_config, field_value, field_name=None):
    if field_name == "knowledge_base":
        async with session_scope() as db:
            current_user = await get_user_by_id(db, self.user_id)
            # GOOD: Access attributes within session scope
            kb_user = current_user.username

Additionally, consider the timing of database availability checks. Operations that verify database state (like table existence) should occur after initialization is complete, not during the initial setup phase.


sanitize trace metadata

Always sanitize trace metadata and attributes before sending to observability platforms to ensure compatibility with OpenTelemetry attribute type restrictions. Complex objects, custom types, and non-primitive values should be converted to supported types (str, int, float, bool, None) or JSON strings to prevent warnings and ensure reliable trace data.

Implement sanitization methods that:

Example implementation:

def sanitize_for_otel(value):
    """Sanitize values for OpenTelemetry attribute compatibility."""
    if value is None or isinstance(value, (str, int, float, bool)):
        return value
    elif isinstance(value, (list, tuple)):
        return [sanitize_for_otel(item) for item in value]
    elif isinstance(value, dict):
        try:
            return json.dumps(value)
        except (TypeError, ValueError):
            return str(value)
    else:
        return str(value)

# Usage in trace metadata
span.set_attributes({
    key: sanitize_for_otel(value) 
    for key, value in metadata.items()
})

This prevents OpenTelemetry warnings like “Invalid type StructuredTool in attribute” and ensures consistent trace data across different observability platforms (Traceloop, Opik, Arize Phoenix).


validate API inputs comprehensively

Ensure thorough validation of API inputs and outputs using robust validation techniques rather than simple string checks or partial validation. Use proper libraries for validation (like urllib.parse for URLs) and validate all required components, not just a subset.

For URL validation, avoid simple string prefix checks:

# Avoid this
if source_name.startswith("http"):
    # process URL

# Use this instead
from urllib.parse import urlparse
parsed = urlparse(source_name)
if parsed.scheme in ['http', 'https', 's3', 'gs']:
    # process URL

For component validation, ensure completeness:

# Avoid partial validation
if "Chat Input" not in display_names:
    raise ValueError("Missing ChatInput component")

# Validate all required components
required_components = ["Chat Input", "Chat Output"]
missing = [comp for comp in required_components if comp not in display_names]
if missing:
    raise ValueError(f"Missing required components: {missing}")

This prevents runtime errors, improves API reliability, and ensures consistent behavior across different input scenarios.


eliminate code duplication

Actively identify and eliminate code duplication by extracting repeated logic into reusable functions, using loops instead of repetitive code blocks, and consolidating similar implementations. When you find yourself copying and pasting code or writing nearly identical logic multiple times, refactor it into a shared function or use iteration patterns.

For example, instead of repeating similar command creation logic:

// Before: Duplicated command creation
let output = if cfg!(target_os = "windows") {
    Command::new("cmd")
        .args(["/C", command])
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .stdin(Stdio::null())
        .kill_on_drop(true)
        .output()
        .await?
} else {
    Command::new("sh")
        .args(["-c", command])
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .stdin(Stdio::null())
        .kill_on_drop(true)
        .output()
        .await?
};

// After: Consolidated approach
let mut command = if cfg!(target_os = "windows") {
    Command::new("cmd").args(["/C", command])
} else {
    Command::new("sh").args(["-c", command])
};
let output = command
    .stdout(Stdio::piped())
    .stderr(Stdio::piped())
    .stdin(Stdio::null())
    .kill_on_drop(true)
    .output()
    .await?;

Similarly, replace repetitive field processing with loops, extract common validation logic into helper functions, and consolidate similar error handling patterns. This improves maintainability, reduces the chance of bugs from inconsistent implementations, and makes the codebase more readable and easier to modify.


consolidate API parameters

Prefer consolidating common configuration and parameters in API constructors or base methods rather than requiring multiple method calls, complex parameter passing, or external configuration loading. This reduces API surface area and makes interfaces easier to use for consumers.

When designing APIs, favor approaches that:

Example of preferred approach:

// Instead of separate methods for each model type
pub async fn complete_with_model(&self, model: Option<String>) -> Result<Message> {
    let model = model.unwrap_or_else(|| self.default_model());
    // implementation
}

// Instead of requiring multiple setup calls
pub fn new(api_key: String) -> Result<Self> {
    let mut client = ApiClient::new(host, auth)?;
    
    // Load common config automatically
    if let Some(tls_config) = TlsConfig::from_config()? {
        client = client.with_tls_config(tls_config)?;
    }
    
    Ok(Self { client })
}

// Instead of string-based parameters, use direct types
pub fn create_tool(schema: serde_json::Value) -> Tool {
    // Use schema directly instead of requiring JSON string
}

This approach reduces the cognitive load on API consumers and prevents the need to understand complex setup sequences or parameter serialization formats.


explicit None handling

When operations cannot complete successfully or return meaningful results, explicitly return None rather than raising exceptions or using placeholder values. Document when None is expected and ensure consistent None handling throughout the codebase.

Prefer explicit None returns when:

Always document when None is possible and what it represents:

def get_relative_path(self) -> str | None:
    """
    Get the relative path of the file containing the symbol.
    
    :return: the relative path, or None if the symbol is defined 
             outside of the project's scope
    """
    return self.symbol.location.relative_path

# Better than using defaults or exceptions
def find_executable() -> str | None:
    """Find the executable path, or None if not found."""
    path = shutil.which("executable")
    return path  # Returns None if not found, caller handles it

# Consistent None handling throughout
if relative_path is None:
    # Handle the None case appropriately
    continue  # or return, or use fallback logic

This approach makes error conditions explicit, prevents silent failures, and allows callers to make informed decisions about how to handle missing or invalid data.


Document API contracts

Ensure all API interfaces have clearly documented contracts specifying expected request/response formats, data encoding standards, and return types. This prevents integration issues and enables reliable external consumption.

When designing callback functions or data exchange formats, explicitly document:

Example from callback responses:

const handleUIAction = useCallback(async (result: UIActionResult) => {
  // Process the action...
  
  // IMPORTANT: Always return documented response format
  const response = {
    type: 'ui-message-response',
    payload: result,
  };
  return response;
}, []);

Consider adding TypeScript interfaces or runtime validation to enforce documented contracts. For data formats like deeplinks, establish official standards (e.g., “use URL_SAFE_NO_PAD base64”) and implement backwards-compatible decoding to handle legacy formats during transitions.


Prevent credential exposure

Ensure that sensitive authentication data such as API keys, tokens, passwords, and other credentials are never exposed in documentation, client-side code, logs, or configuration files. This includes both preventing accidental inclusion in documentation and implementing proper secure handling in application code.

Key practices:

Example from authentication form:

// Good: Using FormPassword for sensitive data
<FormPassword
  autoComplete="new-password"
  placeholder={t('comfyui.apiKey.placeholder')}
/>

// Good: Using FormPassword for passwords
<FormPassword
  autoComplete="new-password"
  placeholder={t('comfyui.password.placeholder')}
/>

This practice prevents credential theft, unauthorized access, and security breaches that can occur when sensitive authentication data is inadvertently exposed through various channels.


intentional error handling

Make deliberate, context-appropriate decisions about error handling strategy rather than applying generic patterns. Consider whether each error scenario should fail fast, provide graceful degradation, or offer recovery options based on the specific business impact and user experience requirements.

Key principles:

Example of intentional error handling:

# Fail fast for critical dependencies
try:
    from required_library import CriticalClass
except ImportError as e:
    msg = "Required library not installed. Install with: pip install required_library"
    raise ImportError(msg) from e

# Graceful degradation for optional features  
try:
    dependency_info = analyze_component_dependencies(code)
    metadata["dependencies"] = dependency_info
except (SyntaxError, TypeError, ValueError) as exc:
    logger.warning(f"Failed to analyze dependencies for {name}: {exc}")
    # Continue without dependency info - this is optional

The choice between failing fast and graceful degradation should be explicit and documented, considering the impact on users and the ability to debug issues effectively.


Environment-aware configuration handling

Use environment variables to control application behavior and ensure configuration changes are properly synchronized between in-memory state and persistent storage. When configuration depends on environment context, check for relevant environment variables first before falling back to defaults.

This prevents inconsistencies where in-memory configuration differs from persisted configuration, and allows for environment-specific behavior without hardcoding values.

Example patterns:

// Check environment variable before generating defaults
const key = process.env.GOOSE_SERVER__SECRET_KEY || 
           (process.env.GOOSE_EXTERNAL_BACKEND ? 'test' : crypto.randomBytes(32).toString('hex'));

// Enable development features via environment
if (process.env.ENABLE_DEV_UPDATES === 'true') {
  autoUpdater.forceDevUpdateConfig = true;
}

When modifying configuration in memory, ensure changes are also reflected in the persistent storage layer to maintain consistency, or clearly document when temporary in-memory modifications are intentional.


Extract duplicate constants

Eliminate code duplication by extracting repeated values and components into well-organized constants. This applies at both the variable level (extracting duplicate literal values) and file level (separating reusable components).

For duplicate values, extract them to named constants:

// Instead of:
const [downloadUrls, setDownloadUrls] = useState({
  deb: "https://github.com/block/goose/releases/latest",
  rpm: "https://github.com/block/goose/releases/latest"
});

// Use:
const LATEST_RELEASE_URL = "https://github.com/block/goose/releases/latest";
const [downloadUrls, setDownloadUrls] = useState({
  deb: LATEST_RELEASE_URL,
  rpm: LATEST_RELEASE_URL
});

For reusable components, consider separating them into individual files rather than grouping them in a single constants file:

// Instead of: src/components/Constants.js (with multiple components)
// Use: src/components/DesktopProviderSetup.js
//      src/components/ModelSelectionTip.js

This improves maintainability, reduces the risk of inconsistencies, and makes the codebase more modular and easier to navigate.


User-focused documentation structure

Documentation should prioritize user needs and problems over technical implementation details. Start with the “why” - what problem does this solve and when would users need it? Provide clear use cases and benefits before diving into technical specifics.

Structure documentation to guide users through their journey:

  1. Problem statement: What user problem does this solve?
  2. Use cases: When would someone use this feature?
  3. Simple examples: Basic usage with expected outcomes
  4. Benefits: What can users accomplish after following the guide?
  5. Platform-specific details: Clearly distinguish between UI and CLI instructions

Move implementation details, technical architecture, and contributing guidelines to separate technical documentation when they don’t directly serve user goals.

Example structure:

# Feature Name

## What problem does this solve?
Help users understand when they need this feature...

## Use cases
- Run this when you want to...
- Use this for...

## Quick start
Simple example with expected output...

## Benefits
What you can accomplish after setup...

Avoid documentation that “reads more like internal technical documentation than a user guide” by consistently asking: “Does this help users accomplish their goals?”


Use descriptive names

Choose clear, descriptive names for variables, methods, types, and parameters that unambiguously convey their purpose and avoid conflicts. Prefer full words over abbreviations and ensure names are specific enough to prevent clashes with inherited or similar functionality.

Examples of improvements:

This practice reduces cognitive load, prevents naming conflicts during inheritance or composition, and makes code more maintainable by clearly expressing intent through naming.


Include API Version

When configuring client access to an external API, store the provider’s base endpoint as a fully-qualified URL that already includes the required API version (and defaults). Avoid splitting “base URL” and “version” in ways that can drift or be forgotten—make the endpoint unambiguous.

Example (.env.example style):

# Provider base endpoint including version path
OPENAI_ENDPOINT=https://api.openai.com/v1

# If using Azure, include the full endpoint and keep the version as part of the endpoint you call
# (or ensure the final request URL includes the version parameter/path consistently)
AZURE_OPENAI_ENDPOINT=https://<resource>.openai.azure.com/
AZURE_API_VERSION=2024-xx-xx

Application guidance:


Ensure comprehensive test coverage

Always add test coverage for new functionality, especially when introducing integrations or services. Use mocks and patches when testing external dependencies. Additionally, configure coverage reporting to exclude irrelevant paths like legacy components, deactivated features, and test files themselves to maintain meaningful coverage metrics.

Example coverage configuration:

# .coveragerc
[run]
source = src/backend/base/langflow
omit =
    # Test files
    */tests/*
    */test_*
    
    # Deactivated Components
    */components/deactivated/*
    
    # Legacy components with legacy = True
    */components/legacy_component.py

When adding tests, use appropriate mocking:

# Example test with mocking
@patch('module.external_service')
def test_tracing_functionality(mock_service):
    mock_service.return_value = expected_result
    # Test implementation
    assert result == expected_result

Ensure naming consistency

Maintain consistent naming for the same entities across different contexts including code, documentation, APIs, and external systems. When names must differ between contexts, implement fallback mechanisms to handle variations gracefully.

Key principles:

Example from codebase:

// Handle repository name variations gracefully
const tries = [
  app.repo, // First try with the original repo name
  app.repo.replace(/\.git$/, ""), // If that fails, try without .git suffix
];

// Use consistent server identifiers that match documentation
const servers: Record<string, LSPServer.Info> = LSPServer.getServerIds(); // Use "typescript", not "Typescript"

This prevents user confusion and reduces integration issues when the same logical entity has different naming requirements across different systems.


Conditional configuration management

Ensure configurations are conditional, context-aware, and resilient. Use feature flags to control functionality availability rather than instructing systems to avoid certain features. Implement proper fallbacks for missing configuration values and support backward compatibility when introducing new config formats.

Key practices:

Example:

// Good: Conditional tool availability based on feature flag
if (experiments?.morphFastApply !== true) {
    tools.delete("edit_file")
}

// Good: Fallback to system language instead of hardcoded default
initializeI18n(context.globalState.get("language") ?? formatLanguage(vscode.env.language))

// Good: Support multiple rule file formats for backward compatibility  
const ruleFiles = [".kilocoderules", ".roorules", ".clinerules"]

// Good: Make hardcoded values configurable
const sizeLimit = config.get("sizeLimitFraction") ?? SIZE_LIMIT_AS_CONTEXT_WINDOW_FRACTION

avoid environment variable proliferation

Prefer the consolidated config system over adding new environment variables. Environment variables should only be used for deployment-specific overrides, not as the primary configuration mechanism.

Guidelines:

Example:

// ❌ Avoid: Adding new environment variables
const GOOSE_RECIPE_RETRY_TIMEOUT_SECONDS: &str = "GOOSE_RECIPE_RETRY_TIMEOUT_SECONDS";

fn get_retry_timeout(retry_config: &RetryConfig) -> Duration {
    let timeout_seconds = env::var(GOOSE_RECIPE_RETRY_TIMEOUT_SECONDS)
        .ok()
        .and_then(|s| s.parse().ok())
        .unwrap_or(DEFAULT_RETRY_TIMEOUT_SECONDS);
    Duration::from_secs(timeout_seconds)
}

// ✅ Prefer: Use config system with parameter passing
fn get_retry_timeout(retry_config: &RetryConfig, config_timeout: Option<u64>) -> Duration {
    let timeout_seconds = retry_config.timeout_seconds
        .or(config_timeout)
        .unwrap_or(DEFAULT_RETRY_TIMEOUT_SECONDS);
    Duration::from_secs(timeout_seconds)
}

// At call site:
let config = Config::global();
let timeout = config.get_param("RETRY_TIMEOUT_SECONDS").unwrap_or(DEFAULT_RETRY_TIMEOUT_SECONDS);
get_retry_timeout(&retry_config, Some(timeout))

This approach reduces environment variable sprawl while maintaining flexibility for deployment-specific configuration through the existing config system.


Use descriptive identifiers

Replace generic, ambiguous, or magic identifiers with descriptive, specific names that clearly communicate intent and avoid confusion.

Key principles:

Examples:

// Bad: Generic time-based ID
let execution_id = format!("exec_{}", SystemTime::now().duration_since(UNIX_EPOCH));

// Good: UUID-based ID  
let execution_id = format!("exec_{}", Uuid::new_v4());

// Bad: Magic number with comment
command.creation_flags(0x08000000); // CREATE_NO_WINDOW flag

// Good: Named constant
const CREATE_NO_WINDOW: u32 = 0x08000000;
command.creation_flags(CREATE_NO_WINDOW);

// Bad: String constants
const EXECUTION_MODE_PARALLEL: &str = "parallel";
const EXECUTION_MODE_SEQUENTIAL: &str = "sequential";

// Good: Enum
enum ExecutionMode {
    Parallel,
    Sequential,
}

This approach improves code maintainability, reduces ambiguity, and makes the codebase more self-documenting.


Use descriptive names

Choose names that clearly communicate purpose, type, and intent rather than generic or ambiguous identifiers. Names should be self-documenting and help other developers understand what the code does without additional context.

Key principles:

Example improvements:

// Instead of generic names:
const cache = new Map<string, Promise<string>>() // unclear what string represents
function KiloBaseUri(options: ApiHandlerOptions) // unclear if this gets, sets, or creates

// Use descriptive names:
const cache = new Map<string, Promise<string>>() // with comment: kilocodeToken -> model promise
function getKiloBaseUri(options: ApiHandlerOptions) // clearly indicates this retrieves a URI

// Parameter clarity:
files?: string[] // ambiguous
filePaths?: string[] // clearly indicates these are file paths

This approach reduces cognitive load, improves code maintainability, and makes the codebase more accessible to new team members.


Handle errors intentionally

Avoid generic catch-all error handling that masks important failures. Instead, be selective about which errors to handle locally versus letting them bubble up to higher-level handlers. When you do handle errors locally, implement safe defaults and use robust parsing methods.

Key principles:

Example of intentional error handling:

// Bad: Generic catch that hides all errors
try {
  const result = await response.json();
  return result;
} catch (error) {
  return { success: false }; // Masks what actually went wrong
}

// Good: Let parsing errors bubble up, handle specific conditions
const result = await safeJsonParse(response);

// Handle specific recoverable errors
if (response.status === 529 || response.status === 503) {
  // Retry logic for service overload
  return retryRequest();
}

// For security scans, default to safe behavior on failure
try {
  const scanResult = await scanRecipe(recipeConfig);
  setHasSecurityWarnings(scanResult.has_security_warnings);
} catch (error) {
  setHasSecurityWarnings(false); // Safe default, show generic warning
}

Test structure and clarity

Organize tests for maximum clarity and maintainability by leveraging pytest features and proper test structure. Split complex tests into focused, single-purpose test cases rather than testing multiple scenarios in one function. Use pytest fixtures for setup and cleanup instead of manual resource management, and prefer parameterization for testing multiple inputs.

Key practices:

Example of good test structure:

@pytest.mark.parametrize("module", [dspy.Predict, dspy.ChainOfThought])
def test_color_classification_using_enum(module):
    # Single focused test case with parameterization
    
def test_file_access_control(tmp_path):
    # Use pytest fixture for automatic cleanup
    testfile_path = tmp_path / "test_file.txt"

This approach makes tests more readable, maintainable, and reliable while following pytest best practices.


Use configuration enums

Replace hardcoded string matching and magic values with proper configuration enums or flags. This improves maintainability, reduces errors, and makes configuration behavior explicit and type-safe.

Instead of checking string content for configuration decisions:

// Avoid: hardcoded string matching
{!prompt?.includes('SECURITY WARNING') && (
  <Button onClick={() => handleButtonClick(ALWAYS_ALLOW)}>
    Always Allow
  </Button>
)}

Use explicit configuration enums or flags:

// Better: explicit configuration enum
enum ConfirmationType {
  STANDARD = 'standard',
  SECURITY_WARNING = 'security_warning',
  CRITICAL = 'critical'
}

{confirmationType !== ConfirmationType.SECURITY_WARNING && (
  <Button onClick={() => handleButtonClick(ALWAYS_ALLOW)}>
    Always Allow
  </Button>
)}

Similarly, for platform-specific configurations, use structured approaches rather than inline conditionals. This pattern prevents bugs from typos in string matching, makes the configuration intent clear to other developers, and enables better tooling support through TypeScript’s type system.


Configuration parameter validation

Always validate configuration parameters for type, range, and reasonable values before use. Provide safe defaults for optional settings and prefer explicit parameter passing over runtime environment variable modification.

Key practices:

Example:

# Good: Validate and use safe defaults
recursion_limit = int(os.getenv("AGENT_RECURSION_LIMIT", "25"))
if recursion_limit <= 0:
    raise ValueError("Recursion limit must be greater than zero")
logger.info(f"Recursion limit is set: {recursion_limit}")

# Good: Pass as parameters instead of environment modification
return AzureChatOpenAI(
    api_version=llm_config.get("api_version"),
    api_key=llm_config.get("api_key"),
    azure_endpoint=llm_config.get("base_url")
)

# Avoid: Runtime environment modification
os.environ.update({"AZURE_OPENAI_API_KEY": api_key})  # Not recommended

Use self-documenting names

Choose variable, function, and constant names that clearly express their purpose and eliminate the need for explanatory comments. Break down complex expressions into well-named intermediate variables rather than relying on comments to explain the logic.

For example, instead of:

// Use explicit hasEnvVars if provided, otherwise fall back to checking step3Content
const hasConfiguration = hasEnvVars !== undefined ? hasEnvVars : step3Content !== null;

Use descriptive intermediate variables:

const hasConfigurationContent = step3Content !== null;
const shouldShowConfigurationSteps = hasEnvVars ?? hasConfigurationContent;

This principle also applies to extracting repeated string literals into named constants. Instead of using ‘New Chat’ multiple times throughout the code, define a constant like DEFAULT_CHAT_TITLE = 'New Chat' to make the intent clear and improve maintainability.


Separate configuration concerns

Keep persistent user configuration separate from transient state, setup flags, and derived values. Persistent configuration should only contain user-defined settings that need to be saved across sessions. Transient state like cached detection results, setup completion flags, or runtime-derived values should be stored separately using dedicated state management or separate files.

For example, instead of adding setup state to the main config:

type Config struct {
    Providers     map[models.ModelProvider]Provider `json:"providers,omitempty"`
    Agents        map[AgentName]Agent               `json:"agents,omitempty"`
    SetupComplete bool                              `json:"setupComplete,omit"` // ❌ Don't mix setup state with config
}

Extract setup functionality into its own module or store in app state:

// ✅ Keep config clean of transient state
type Config struct {
    Providers map[models.ModelProvider]Provider `json:"providers,omitempty"`
    Agents    map[AgentName]Agent               `json:"agents,omitempty"`
}

// ✅ Store transient state separately
type AppState struct {
    detectedTimeFormat *bool // cached detection result
    setupComplete      bool  // setup state
}

This separation improves maintainability, prevents config bloat, and makes it clear which data persists vs which is computed or temporary.


Native fetch over dependencies

Prefer Node.js native fetch API over external HTTP client libraries like node-fetch when the target Node.js version supports stable native functionality. While fetch is available from Node.js 18+, it’s considered stable from version 21 onwards.

Before adding HTTP client dependencies, evaluate:

Example of unnecessary dependency:

// Avoid when targeting Node.js >= 21
"dependencies": {
  "node-fetch": "3.3.2"  // Remove if native fetch suffices
}

This reduces bundle size, eliminates potential security vulnerabilities from external packages, and leverages platform-native optimizations. Only retain HTTP client libraries when they provide essential features not available in the native fetch API or when targeting older Node.js versions where native fetch is unstable.


AI configuration documentation

Ensure AI model configurations and related documentation use precise terminology and provide clear, complete setup instructions without overwhelming users.

When documenting AI models, LLMs, and related infrastructure:

  1. Use precise terminology: Distinguish between “parameters” (learned values) and “hyperparameters” (values that control the learning process). For example, demonstration examples are parameters, while max_labeled_demos and temperature are hyperparameters.

  2. Provide complete configuration examples: Include all required parameters, environment variables, and credentials users need. For instance, when documenting model clients, specify required connection parameters and API keys:

# Good: Complete configuration
lm = dspy.Snowflake(
    model="mixtral-8x7b",
    credentials={
        "account": "your_account",
        "user": "your_username", 
        "password": "your_password",
        "warehouse": "your_warehouse"
    }
)

# Environment variables required:
# OPENAI_API_KEY="your-openai-api-key"
  1. Start simple, then expand: Begin with essential configurations before introducing advanced options. Avoid overwhelming users with complex features upfront - start with basic functionality like llms.txt before introducing llms-full.txt.

  2. Include performance considerations: Document recommended settings for better performance, such as async configurations and optimal hyperparameters:

dspy.settings.configure(lm=lm, async_capacity=16)  # max 16 concurrent DSPy programs
dspy_model = dspy.asyncify(dspy.ChainOfThought("question -> answer"))

This approach ensures developers can successfully configure AI systems while understanding the underlying concepts and performance implications.


Optimize memory and algorithms

Focus on efficient memory usage and algorithm selection while preserving functionality. Apply these optimization techniques:

Memory optimization:

Algorithm efficiency:

Remember that correctness takes priority over performance optimizations. Avoid truncating or modifying data in ways that could break downstream functionality, even if it improves performance metrics.


Explicit CI Environment Config

Make CI and build configuration deterministic by explicitly selecting tool versions and target environments, and by ensuring monorepo config paths match what downstream generators expect.

Apply this by:

Example (targeting the correct venv with uv):

# Prefer deterministic venv selection; keep it explicit to avoid global overlap.
VIRTUAL_ENV=.venv uv pip install dist/*.whl

# If you prefer deriving it, ensure your script finds/creates the same venv
# that the rest of the pipeline uses, then pass VIRTUAL_ENV accordingly.
uv venv
VIRTUAL_ENV=.venv uv pip install dist/*.whl

Example (monorepo package config):

# Ensure `path` reflects the package root the build/docs tooling expects.
- name: toolbox-langchain
  repo: googleapis/mcp-toolbox-sdk-python
  path: .   # (not a nested subdir) when the generator expects package-root contents

Provider-specific AI handling

Implement provider-specific logic when integrating different AI services, as each provider has unique requirements for message formatting, API endpoints, validation rules, and optimization strategies.

Different AI providers require distinct handling approaches:

Message Role Handling: Transform message roles based on provider requirements. For example, Baidu requires system messages to be converted to assistant/user roles and maintains strict alternating patterns, while Google converts system roles to user roles.

// Provider-specific message role transformation
const messages = options.messages.map((v) => ({
  role: v.role === "system" ? "assistant" : v.role, // Baidu-specific
  content: getMessageTextContent(v),
}));

// vs Google-specific transformation
role: v.role.replace("assistant", "model").replace("system", "user"),

API Path Construction: Use provider-specific URL patterns and model handling. Azure requires deployment names in URLs, while Gemini needs dynamic model injection into paths.

// Provider-specific path handling
if (modelConfig.providerName == ServiceProvider.Azure) {
  chatPath = this.path(`/deployments/${deploymentName}/chat/completions`);
} else {
  chatPath = this.path(OpenaiPath.ChatPath);
}

Model-Specific Optimization: Apply provider-specific models for different operations like summarization, using each provider’s most suitable and cost-effective options rather than defaulting to a single model across all providers.

This approach ensures compatibility, optimal performance, and proper functionality across different AI service providers while maintaining clean, maintainable code.


Database migration isolation

When performing database migrations or schema changes, use containerized environments to ensure isolation and comprehensive testing. This approach prevents migration issues from affecting development environments and allows for reliable rollback scenarios.

Containerized database migrations provide several benefits:

Example approach for migrating from file-based storage to SQLite:

# Use container-use to create isolated environment
container-use stdio

# Within the container, perform migration steps:
# 1. Set up SQLite database schema
# 2. Migrate data from file-based storage
# 3. Run comprehensive tests
# 4. Validate data integrity

This practice is especially important when transitioning between storage mechanisms (like moving from file-based to database storage) where data integrity and application functionality must be thoroughly validated before deployment.


Configuration bounds validation

Always validate configuration values against system limits and constraints, implementing automatic adjustment when values exceed acceptable bounds. This prevents runtime errors and ensures configurations remain within operational parameters.

When setting configuration values that have system-imposed limits (like token counts, memory limits, or API constraints), implement validation logic that checks against maximum allowed values and automatically adjusts when necessary. For user-facing configuration displays, ensure accuracy by showing actual values rather than assumptions, and consider platform-specific variations.

Example implementation:

// Validate and auto-adjust configuration values against system limits
useEffect(() => {
    if (isFeatureSupported && systemInfo?.maxLimit && userConfigValue > systemInfo.maxLimit) {
        setConfigurationField("configKey", systemInfo.maxLimit || DEFAULT_FALLBACK_VALUE)
    }
}, [isFeatureSupported, userConfigValue, systemInfo?.maxLimit, setConfigurationField])

// For display, show actual vs default values with platform awareness
const displayValue = userHasCustomized ? `${actualValue} [custom]` : `${defaultValue} [default]`
const platformKey = isMac ? "" : "Ctrl"

This approach prevents configuration-related failures and provides users with accurate information about their current settings.


Verify configuration documentation

Ensure all configuration documentation accurately reflects actual system behavior, available options, and correct command syntax. Configuration errors in documentation lead to broken user setups and erode trust.

Key areas to verify:

Example of problematic documentation:

# Incorrect - this command doesn't exist
ALPHA_FEATURES=true goose session start

# Correct - verified working command  
ALPHA_FEATURES=true goose session

Before publishing configuration documentation, test each command and verify each described behavior actually works as documented. Remove or clearly mark any configuration options that are planned but not yet implemented.


Handle AI provider specifics

Different AI providers and models have unique requirements for input processing, output filtering, and API parameters that must be implemented correctly. When working with AI APIs, research and implement provider-specific handling rather than assuming uniform behavior across all providers.

Key considerations:

Example implementation:

// Provider-specific parameter handling
const requestOptions = {
    model: model.id,
    messages: openAiMessages,
    max_tokens: maxOutputTokens, // Required by Fireworks API
    // ... other provider-specific params
}

// Provider-specific content filtering
const processedContent = isSpecialModel 
    ? filterThinkingTags(block.text)
    : block.text

Before implementing generic solutions, verify whether the target AI provider has documented requirements or behavioral differences that need accommodation.


Conditional telemetry flushing

Avoid fixed delays for telemetry flushing. Instead, make flushing conditional on whether telemetry endpoints are configured and use dynamic timeouts when possible.

Fixed sleep durations for telemetry flushing create unnecessary delays when no telemetry is configured and don’t guarantee actual completion of data export. This is particularly problematic in CLI tools where delays accumulate across multiple runs.

Implementation approach:

  1. Check if telemetry endpoints are configured before adding any delays
  2. Consolidate multiple fixed sleeps into a single, centralized flushing mechanism
  3. Use dynamic checks with maximum timeouts when the SDK supports it

Example:

// Instead of fixed delays everywhere:
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
std::thread::sleep(std::time::Duration::from_millis(500));

// Use conditional flushing:
let should_flush = std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT").is_ok()
    || config.get_param::<String>("otel_exporter_otlp_endpoint").is_ok();

if should_flush {
    shutdown_otlp_with_timeout(Duration::from_secs(2)).await;
}

This approach improves performance for users without telemetry configured while ensuring proper cleanup when telemetry is enabled.


Document non-obvious code

Add clear documentation for code elements that aren’t immediately self-explanatory to improve readability and maintainability. This includes replacing magic numbers with named constants, adding explanatory comments for complex types, and ensuring documentation remains consistent and synchronized across different contexts.

Key practices:

Example for type documentation:

/// A message stream yields partial text content but complete tool calls, 
/// all within the Message object. So a message with text will contain 
/// potentially just a word of a longer response
pub type MessageStream = Pin<...>;

This practice helps new team members understand the codebase faster and reduces the cognitive load when reviewing or modifying code.


dependency version precision

Choose appropriate version constraints in package.json based on stability requirements and risk tolerance. Use tilde (~) for patch-level updates when you want stability but need bug fixes, caret (^) for minor updates when you can tolerate feature additions, or exact versions for maximum control. For critical dependencies requiring precise version control, consider using npm overrides to enforce specific versions across the dependency tree.

Example:

{
  "dependencies": {
    "@mcp-ui/client": "~5.3.1"  // Allow patches only
  },
  "overrides": {
    "@mcp-ui/client": "5.3.1"   // Force exact version if needed
  }
}

The choice between “~5.3.1” (patches allowed) versus “5.3.1” (exact) should reflect your project’s stability needs and tolerance for automatic updates.


avoid expensive operations

Identify and mitigate costly operations that can significantly impact performance. This includes CPU-intensive processing, expensive I/O operations, and repeated function calls that involve file system access or complex computations.

When you encounter performance bottlenecks:

Example of avoiding expensive operations:

// Avoid: Multiple expensive calls
const { mode, apiConfiguration, language } = await this.getState()
const { experiments } = await this.getState() // Expensive I/O operation called twice

// Prefer: Single expensive call with full destructuring
const {
    mode,
    apiConfiguration, 
    language,
    experiments
} = await this.getState()

// Or disable expensive features when cost outweighs benefit:
// context = await this.addAST(context) // Disabled: uses too much CPU for Swift

Always weigh the performance cost against the actual benefit provided, especially for operations involving file I/O, network calls, or intensive computations.


Externalize configuration values

Avoid hard-coding configuration values directly in source files. Instead, externalize them using environment variables, configuration files, or external resources. This improves maintainability, enables environment-specific settings, and reduces bundle sizes.

For runtime configuration, use environment variables:

// Instead of hard-coding:
id: 'ep-20250627155918-4jmhg'

// Use environment variables:
id: process.env.MODEL_ID

For build-time configuration, consider external dependencies:

// Instead of bundling large resources:
const minifiedCSS = cleanCSS.minify(reportCSS).styles;

// Use external CDN resources in modern.config.js:
// https://unpkg.com/@ui-tars/visualizer/dist/report/

This approach enables different configurations per environment, reduces code coupling, and keeps sensitive or environment-specific values out of the codebase.


Ensure proper React keys

Always provide meaningful keys for React components and fragments to ensure proper rendering and re-rendering behavior. Use composite keys when component identity depends on multiple values, and include keys even for Fragment components when rendering lists.

For components that need to re-render based on multiple state changes, create composite keys:

<MarketplaceInstallModal
    key={`install-modal-${item.id}-${installModalVersion}`}
    // other props
/>

For Fragment components in lists, always include a key prop:

{PROVIDERS.map(({ value, label }, i) => (
    <Fragment key={value}>
        <SelectItem value={value}>
            {label}
        </SelectItem>
    </Fragment>
))}

This prevents React from incorrectly reusing components and ensures predictable rendering behavior, especially when component state or props change frequently.


Replace polling with events

Replace busy-wait polling loops with event-driven async patterns using asyncio.Event() or similar synchronization primitives. Polling loops that continuously check state variables waste CPU cycles and block the event loop, while event-driven patterns allow the thread to yield control until the condition is actually met.

Look for patterns like:

# Avoid: Busy-wait polling
while self.state.paused:
    await asyncio.sleep(0.1)  # Still wastes cycles checking every 100ms

Replace with event-driven patterns:

# Prefer: Event-driven waiting
self._pause_event = asyncio.Event()

# In the waiting code:
await self._pause_event.wait()  # Blocks until event is set, no polling

# In the control code:
def pause(self):
    self.state.paused = True
    self._pause_event.clear()

def resume(self):
    self.state.paused = False
    self._pause_event.set()

This approach eliminates CPU spinning, allows proper async task isolation (each task can have its own events), and removes the need for redundant state variables when the event itself serves as the synchronization mechanism. Consider removing duplicate state tracking when the event primitive provides the same information.


Document implementation reasoning

Add comments that explain WHY implementation decisions were made, not just WHAT the code does. This is especially important for backwards compatibility hacks, workarounds, non-obvious logic checks, and temporary solutions.

For backwards compatibility measures, include:

For complex logic checks, explain the underlying business reason or technical constraint that necessitates the check.

Example:

# Backwards compatibility hack introduced in v2.1.0 (Dec 2024)
# Maps old context_id system to new server-based sessions
# TODO: Remove after v3.0.0 when all clients migrate to new API
self._context_to_session: dict[str, tuple[str, str]] = {}

# Check if instance is Component subclass (but not Component itself)
# Required because we manually create Component instances from user dicts
# which need compilation/parsing, unlike pre-built Component classes
if isinstance(instance, type) and issubclass(instance, Component):

This practice helps future maintainers understand the codebase evolution and make informed decisions about refactoring or removing temporary measures.


Document log level options

When documenting logging configuration parameters, always provide the complete list of available log level options and use consistent naming conventions. This ensures developers understand all available choices and prevents confusion from incomplete documentation.

Log levels should be documented in lowercase format consistently across all interfaces (CLI, environment variables, configuration files). When a parameter accepts log level values, explicitly list all valid options rather than showing only the default.

Example:

| `--log-level` | `error` | String | Set the logging level. Possible values: `debug`, `info`, `warning`, `error`, `critical`. |

This practice helps developers make informed decisions about logging configuration and ensures consistency across different parts of the system documentation.


Database configuration clarity

When documenting database configuration or setup procedures, provide specific, actionable instructions with clear verification steps. Always specify which database backend is being used and include concrete examples for verification.

Key practices:

Example of good database verification documentation:

5. To verify the configuration, create any flow using the Langflow UI or API, and then query your database to confirm new tables and activity.
    
    * Query the database container:
    
        ```
        docker exec -it <postgres-container> psql -U langflow -d langflow
        ```
    
    * Use SQL:
    
        ```
        SELECT * FROM pg_stat_activity WHERE datname = 'langflow';
        ```

This approach ensures users can successfully configure and verify their database setup, reducing support issues and improving the development experience.


observability documentation structure

Use proper heading hierarchy instead of bold text formatting when documenting observability features like monitoring, failure points, and telemetry. This improves navigation, readability, and maintains consistent documentation structure across observability-related content.

Instead of using bold text for section organization:

**Database Failure**:
* **Impact**: Disrupts flow retrieval, saving, user authentication...
* **Mitigation**: Use a replicated PostgreSQL setup...

**File System Issues**:
* **Impact**: Concurrency issues in file caching...

Use proper heading hierarchy:

### Database failure

* **Impact**: Disrupts flow retrieval, saving, user authentication...
* **Mitigation**: Use a replicated PostgreSQL setup...

### File system issues

* **Impact**: Concurrency issues in file caching...

This approach makes observability documentation more scannable, enables proper table of contents generation, and follows standard documentation practices. Apply this consistently across monitoring guides, troubleshooting sections, telemetry documentation, and failure analysis content.


Implement concurrent safety patterns

When designing concurrent systems, implement comprehensive safety patterns that handle resource lifecycle management, race conditions, and proper cleanup mechanisms. This includes setting resource limits to prevent exhaustion, implementing timeout-based cleanup for idle resources, and handling database race conditions with proper rollback and retry logic.

Key patterns to implement:

  1. Resource Lifecycle Management: Use structured cleanup with limits and timeouts
    class ResourceManager:
     def __init__(self):
         self.resources_by_key = {}  # Group resources by identity
         self._cleanup_task = asyncio.create_task(self._periodic_cleanup())
        
     async def _periodic_cleanup(self):
         """Periodically clean up idle resources."""
         while True:
             await asyncio.sleep(CLEANUP_INTERVAL)
             await self._cleanup_idle_resources()
        
     async def get_resource(self, key, params):
         # Check limits before creating new resources
         if len(self.resources_by_key.get(key, {})) >= MAX_RESOURCES_PER_KEY:
             # Remove oldest resource
             await self._cleanup_oldest_resource(key)
    
  2. Race Condition Handling: Implement proper exception handling with rollback and retry
    async def create_resource(name, session):
     try:
         # Check if resource exists
         existing = await get_resource_by_name(name, session)
         if existing:
             return existing
            
         # Create new resource
         resource = Resource(name=name)
         session.add(resource)
         await session.commit()
         return resource
     except IntegrityError:
         # Handle race condition - another worker created it
         await session.rollback()
         existing = await get_resource_by_name(name, session)
         if existing:
             return existing
         raise  # Re-raise if no resource found after rollback
    
  3. Test Concurrent Scenarios: Use asyncio.gather() to test real concurrent behavior
    @pytest.mark.asyncio
    async def test_concurrent_resource_creation():
     """Test multiple concurrent calls handle race conditions properly."""
     tasks = [
         create_resource("shared_name", session1),
         create_resource("shared_name", session2)
     ]
     results = await asyncio.gather(*tasks, return_exceptions=True)
     # Verify both succeed or handle conflicts gracefully
    

Always consider the impact of automatic resource cleanup on user experience and provide clear boundaries for resource limits to prevent unexpected behavior disruptions.


avoid concurrency anti-patterns

Avoid common concurrency anti-patterns that lead to race conditions, deadlocks, and unreliable behavior. Use structured approaches instead of ad-hoc solutions.

Key anti-patterns to avoid:

  1. Manual buffer management with select! - Can cause race conditions where data is lost
  2. Sleep-based synchronization - Creates timing dependencies and potential bugs
  3. Wrong synchronization primitives - Using Mutex when RwLock is needed blocks concurrent readers
  4. Improper lock lifetime management - Forgetting to release locks can cause deadlocks

Preferred approaches:

Example:

// Anti-pattern: Manual buffer management with select!
select! {
    n = stdout_reader.read_until(b'\n', &mut stdout_buf) => {
        // Risk of losing last chunk of data
    }
}

// Better: Use streams
let stdout_stream = LinesStream::new(BufReader::new(stdout).lines());
let stderr_stream = LinesStream::new(BufReader::new(stderr).lines());
// Drive streams to completion without manual buffer management

// Anti-pattern: Wrong lock type
pub(super) extension_manager: Mutex<ExtensionManager>, // Blocks concurrent readers

// Better: Allow concurrent reads
pub(super) extension_manager: RwLock<ExtensionManager>, // Multiple readers, single writer

Secure credential management

Ensure sensitive data like API keys, passwords, and encryption keys are stored securely and never exposed in code, configuration files, or documentation. This prevents credential leakage and unauthorized access to external services and systems.

Key practices:

Example secure configuration:

# Good: Reference secrets from secure storage
env:
  - name: OPENAI_API_KEY
    valueFrom:
      secretKeyRef:
        name: api-secrets
        key: openai-key
  - name: LANGFLOW_SECRET_KEY
    valueFrom:
      secretKeyRef:
        name: langflow-secrets
        key: secret-key

Example documentation:

# Good: Truncated example
LANGFLOW_SECRET_KEY=dBuu...2kM2_fb

# Bad: Full credential exposed
LANGFLOW_SECRET_KEY=dBuuuB_FHLvU8T9eUNlxQF9ppqRxwWpXXQ42kM2_fb

This practice is especially critical in production environments where credential exposure can lead to data breaches, unauthorized system access, and compromise of connected services.


Follow consistent semantic naming

Ensure that names accurately reflect their purpose and maintain consistency with established patterns in the codebase. Method names should clearly indicate their behavior - avoid misleading conventions when they don’t match the actual functionality. Similarly, maintain consistent naming patterns across similar contexts.

For example, avoid using “set” prefixes for methods that don’t actually set a value:

// Misleading - implies setting a value
setNotificationDismissed: (notificationId: string) => void

// Clear - accurately describes the action
markNotificationAsDismissed: (notificationId: string) => void

Also ensure consistency in organizational naming patterns:

// Inconsistent
title: "UI/Badge"     // in Badge.stories.tsx
title: "Component/Button"  // in Button.stories.tsx

// Consistent
title: "Component/Badge"   // matches established pattern
title: "Component/Button"

This approach helps maintain code readability and reduces confusion for team members working across different parts of the codebase.


break down large files

Large files with multiple responsibilities should be broken down into focused, single-responsibility modules to improve maintainability and avoid tight coupling. When a file becomes difficult to navigate or contains unrelated functionality, extract logical components into separate files or classes.

Key indicators for refactoring:

Example refactoring approach:

// Instead of a large BrowserSession.ts with everything:
// Break into focused modules:
// - ChromeExecutableManager.ts (for ensureChromiumExists, getDetectedChromePath)
// - BrowserConnectionManager.ts (for connection logic)
// - BrowserSession.ts (core session management only)

// Instead of inheritance when not needed:
export class OcaHandler extends LiteLlmHandler { // Avoid this
}

// Prefer composition:
export class OcaHandler {
  constructor(private authManager: OcaTokenManager) {}
}

When refactoring, make incremental changes - move existing code to new files without changing functionality simultaneously. Separate platform-specific code paths into dedicated modules (like host-providers) rather than mixing them with generic logic.


extract reusable utilities

When you notice repeated logic or functions that could be shared across multiple files, extract them into dedicated utility files. This improves code organization, reduces duplication, and minimizes merge conflicts.

Key principles:

Example:

// Instead of adding to existing file
// src/core/prompts/system.ts
function getMorphInstructions(cwd: string, supportsComputerUse: boolean, settings?: Record<string, any>): string {
  // implementation
}

// Extract to dedicated utility
// src/utils/morph-instructions.ts
export function getMorphInstructions(cwd: string, supportsComputerUse: boolean, settings?: Record<string, any>): string {
  // implementation
}

This approach keeps files focused, reduces the likelihood of merge conflicts, and makes shared functionality more discoverable and maintainable.


reuse common message types

Prefer reusable message types over single-purpose request/response pairs to reduce API bloat and improve maintainability. Avoid creating dedicated “Response” types when the return value can be a plain, reusable struct. Merge identical request types and leverage common message patterns like StringRequest or EmptyRequest where appropriate.

Key principles:

Example:

// Avoid: Single-use response type
rpc getRecordingStatus(GetRecordingStatusRequest) returns (GetRecordingStatusResponse);

// Prefer: Reusable plain type
rpc getRecordingStatus(EmptyRequest) returns (RecordingStatus);

// Avoid: Duplicate request types
message RestartMcpServerRequest {
  Metadata metadata = 1;
  string server_name = 2;
}

// Prefer: Reuse common type
rpc restartMcpServer(StringRequest) returns (Empty);

This approach creates cleaner APIs with fewer message types while maintaining the same functionality.


add tests for changes

Every code change, whether it’s a new feature, bug fix, or refactoring, must include corresponding tests. This ensures code quality, prevents regressions, and maintains system reliability.

When adding new functionality:

// New feature: paste detection logic
it('should process a paste as a single event', () => {
  renderHook(() => useKeypress(onKeypress, { isActive: true }));
  const pasteText = 'hello world';
  act(() => {
    stdin.paste(pasteText);
    if (isLegacy) {
      vi.advanceTimersByTime(35);
    }
  });
  // Test the new behavior
});

When fixing bugs, write tests that would have failed before the fix:

// Test for race condition fix
it('should handle concurrent update checks without race conditions', async () => {
  // This test would have failed before the fix
  updateNotifier.mockReturnValue({
    fetchInfo: vi.fn().mockResolvedValue({ current: '1.1.0', latest: '1.0.0' }),
  });
  // Verify the fix works
});

Tests serve as documentation of expected behavior and catch regressions during future changes. They should cover the main functionality, edge cases, and error conditions of the code being modified.


Maintain consistent naming

Ensure naming consistency across all contexts where an identifier appears - configuration files, code enums, documentation, and user interfaces. Names should be semantically clear and distinguish between related but different entities.

When the same concept appears in multiple places, use identical naming:

Prefer simple, unambiguous names that avoid unnecessary complexity:

// Good: Consistent across config and code
"selectedAuthType": "oauth" // matches AuthType.OAUTH in code

// Bad: Inconsistent naming
"selectedAuthType": "oauth-personal" // while code uses AuthType.LOGIN_WITH_GOOGLE

For related but distinct entities, use clear semantic distinctions:

When naming conflicts arise, implement graceful resolution strategies that preserve the original simple names for the most common cases while providing clear alternatives for conflicts.


Comprehensive coverage collection

Configure Jest to collect coverage data from all source files, not just those with existing tests, while avoiding test failures due to coverage thresholds. Coverage enforcement should be handled by external reporting tools rather than the test runner itself.

Use comprehensive collectCoverageFrom patterns to include all source files while excluding test files, setup files, and type definitions:

module.exports = {
  collectCoverage: true,
  collectCoverageFrom: [
    "src/**/*.{ts,tsx}",
    "!src/**/*.{test,spec}.{ts,tsx}",
    "!src/**/tests/**",
    "!src/**/__tests__/**",
    "!src/setupTests.ts",
    "!src/vite-env.d.ts",
    "!src/**/*.d.ts",
  ],
  // Remove coverageThreshold to avoid test failures
  // Let external tools like codecov handle enforcement
};

This approach provides complete visibility into code coverage across the entire codebase while keeping test execution focused on correctness rather than coverage metrics.


Explicit type checking

Use explicit type checks instead of just undefined checks to prevent null values from being passed to functions or APIs that don’t expect them. Checking only for undefined can still allow null values to pass through, which may cause runtime errors.

When dealing with optional parameters that should only be included when they have valid values, check for the specific expected type rather than just checking if the value is not undefined.

// ❌ Problematic - allows null to pass through
...(params.seed !== undefined ? { seed: params.seed } : {})

// ✅ Better - ensures only valid numbers are passed
...(typeof params.seed === 'number' ? { seed: params.seed } : {})

For truly optional environment variables or configuration values, avoid unnecessary fallbacks that might mask configuration issues:

// ❌ Unnecessary fallback for optional values
OPTIONAL_KEY: process.env.OPTIONAL_KEY || ''

// ✅ Let optional values remain undefined
OPTIONAL_KEY: process.env.OPTIONAL_KEY

Check before property access

Always verify that parent objects and properties exist before accessing nested properties or calling methods on them. Use optional chaining (?.) only when the parent object might genuinely be null or undefined, not as a blanket safety measure for guaranteed values. When values can be undefined, provide meaningful defaults rather than arbitrary fallbacks.

Good examples:

// When parent might be undefined
if (navigator && navigator.userAgent) {
    const isChrome = navigator.userAgent.indexOf("Chrome") >= 0
}

// When property might be undefined  
const cachedTokens = chunk.usage.prompt_tokens_details?.cached_tokens || 0

// When request is guaranteed to exist
if (request.options?.canSelectMany !== undefined) { // not request?.options

Avoid:

// Unnecessary optional chaining on guaranteed values
request?.options?.canSelectMany // when request is never null

// Accessing without null checks
const isChrome = navigator.userAgent.indexOf("Chrome") >= 0 // navigator might be undefined

// Arbitrary defaults that cause calculation errors
let effectiveOutputPrice = modelInfo.outputPrice || 0 // should use meaningful default

This prevents runtime errors from null reference exceptions and ensures more predictable behavior when handling optional data.


Use semantic naming

Choose names that clearly communicate the purpose, behavior, and intent of variables, methods, classes, and interfaces. Avoid ambiguous or misleading names that require additional context to understand.

Names should be self-documenting and accurately reflect what the entity represents or does. Consider the actual behavior and usage patterns when naming, not just the initial implementation.

Examples of improvements:

When naming conflicts arise or behavior changes, prioritize semantic accuracy over maintaining existing names. The name should help future developers understand the code without needing to read the implementation.


Never ignore errors silently

All errors must be explicitly handled through catching, logging, or user feedback. Silent error suppression makes debugging impossible and creates poor user experiences.

Always do one of the following:

Example of proper error handling:

// Bad: Silent failure
checkForUpdates().then((info) => {
  // handle success
});

// Good: Explicit error handling  
checkForUpdates().then((info) => {
  // handle success
}).catch((error) => {
  console.error('Update check failed:', error.message);
});

// Bad: Removing error logs
} catch (error) {
  // Ignore clipboard image errors
}

// Good: Maintain error visibility
} catch (error) {
  console.error('Error handling clipboard image:', error);
}

This ensures errors are visible to developers during debugging and users understand when operations fail, enabling proper troubleshooting and recovery.


AI provider naming clarity

Use specific, unambiguous names for AI providers and models to prevent confusion when working with multiple AI services. Avoid generic names that could be mistaken for other providers or create ambiguity about the underlying service.

When naming AI providers:

Example from discussions:

// Before: Confusing connection between Oracle and LiteLLM
// After: Rename to "oca_" for clarity

// Before: Generic interface name
interface HuaweiCloudMaaSHandlerOptions {
    huaweiCloudMaasApiKey?: string
}

// After: Huawei-specific naming
interface HuaweiCloudMaaSHandlerOptions {
    huaweiCloudMaasApiKey?: string  // Clear this is Huawei-specific
}

// Include explicit provider suffixes for discoverability
"moonshotai/Kimi-K2-Instruct:groq": {
    // model configuration
}

This prevents developer confusion, improves code maintainability, and makes the relationship between code and AI services immediately clear.


Analyze async operation dependencies

Before choosing between sequential awaits and parallel execution (Promise.all), carefully analyze whether operations have dependencies that require specific execution order. Operations that depend on each other’s results or shared state must be executed sequentially to prevent race conditions.

When operations must complete in a specific order (e.g., setting backend context before fetching data), use sequential awaits:

// Sequential - when second operation depends on first
await AccountServiceClient.setUserOrganization({ organizationId })
await fetchCreditBalance() // Needs correct backend context from above

When operations are independent and can run concurrently, use Promise.all for better performance:

// Parallel - when operations are independent
await Promise.all([getUserCredits(), getUserOrganizations()])

The key is understanding the data flow and dependencies between async operations. Don’t optimize for speed at the expense of correctness - a race condition where “the subsequent call might execute with the wrong backend context” can cause subtle bugs that are difficult to debug.


Use null meaningfully

Choose between null and undefined based on semantic intent rather than convenience. Use null when operations can explicitly fail and you want to represent that failure state, allowing consumers to handle it appropriately. Use optional properties (?) when a value may simply not be provided or initialized.

Avoid redundant null safety patterns when operations are guaranteed to succeed, as this can create unnecessary complexity and potential regressions.

Example:

// Good: null represents explicit failure state
interface ExtensionState {
  totalTasksSize: number | null  // null when operation fails
}

// Good: undefined represents uninitialized/optional state  
interface ComponentProps {
  targetSection?: string  // may not be provided
}

// Avoid: redundant fallback when find() will always succeed
const defaultTab = SETTINGS_TABS.find(tab => tab.id === "general")?.id ?? SETTINGS_TABS[0].id

This approach makes the code’s intent clearer and helps consumers understand how to handle different null states appropriately.


organize code by responsibility

Place code at the appropriate abstraction level and extract complex logic to dedicated modules. Large files like App.tsx and gemini.tsx should focus on their core responsibilities, with specific functionality moved to specialized components or utility files.

When to extract:

When to move to lower abstraction:

Example:

// Instead of handling keystrokes directly in App.tsx:
if (key.ctrl && input === 'o') {
  setShowErrorDetails((prev) => !prev);
} else if (key.ctrl && input === 't') {
  // complex logic...
}

// Extract to keystrokeHandler.ts:
const keystrokeHandlers = [
  {
    input: 'o',
    ctrl: true,
    handler: () => setShowErrorDetails((prev) => !prev),
  },
  // ...
];

This approach keeps files focused, improves testability, and makes the codebase more maintainable by ensuring each module has a clear, single responsibility.


Prevent concurrent state races

When multiple operations can execute concurrently (e.g., multiple keystrokes in the same React event loop, simultaneous async calls), ensure they don’t operate on stale state or create race conditions. Use centralized state management patterns like reducers, proper synchronization flags, and avoid direct state manipulation from concurrent contexts.

Key strategies:

Example from vim input handling:

// ❌ Problematic: Direct state reading in concurrent context
const getCurrentOffset = useCallback(() => {
  const lines = buffer.lines; // Could be stale if multiple keystrokes processed
  // ... calculate offset
}, [buffer]);

// ✅ Better: Use reducer for sequential operations
const [state, dispatch] = useReducer(vimReducer, initialState);
// Operations go through reducer ensuring proper sequencing

Example from async flag management:

// ❌ Race condition: Flag set inside async operation
async flushToClearcut() {
  this.flushing = true; // Too late - race window exists
  // ... async work
}

// ✅ Proper: Flag set synchronously after checks
flushIfNeeded() {
  if (this.flushing || /* other conditions */) return;
  this.flushing = true; // Set immediately after checks pass
  this.flushToClearcut().finally(() => this.flushing = false);
}

This prevents bugs where rapid user interactions or concurrent async operations interfere with each other, ensuring predictable behavior even under high-frequency input scenarios.


reduce nesting complexity

Prefer early returns, guard clauses, and helper method extraction to reduce nesting levels and improve code readability. Deep nesting makes code harder to follow and understand.

Apply early returns to eliminate unnecessary nesting:

// Instead of:
if (config) {
  const promptCommands: SlashCommand[] = [];
  // ... more nested logic
}

// Use early return:
if (!config) { 
  return promptCommands; 
}
const promptCommands: SlashCommand[] = [];
// ... logic at top level

Extract complex conditionals into helper methods:

// Instead of nested ternary:
const effectiveAuthType = configuredAuthType || 
  (process.env.GOOGLE_GENAI_USE_GCP === 'true'
    ? AuthType.USE_VERTEX_AI
    : process.env.GEMINI_API_KEY
      ? AuthType.USE_GEMINI
      : undefined);

// Use switch or helper method for clarity

Replace magic numbers with named constants:

// Instead of:
await new Promise((res) => setTimeout(res, 200));

// Use:
const PROCESS_KILL_TIMEOUT_MS = 200;
await new Promise((res) => setTimeout(res, PROCESS_KILL_TIMEOUT_MS));

Extract complex logic into focused helper methods rather than embedding it inline. This keeps the main function readable and allows for better testing and reuse.


API backward compatibility

Maintain backward compatibility when evolving API interfaces by preserving existing method signatures and parameter patterns. When adding new functionality, prefer extending existing interfaces over breaking changes, and use deprecation warnings for obsolete parameters.

Key principles:

  1. Preserve existing signatures: Avoid changing method signatures that users depend on, as noted: “This signature cannot be changed, we do need to handle the case where users directly call get
  2. Use kwargs for flexibility: Support both initialization-time and call-time parameters: “It’s important that users can set kwargs in __init__, which become defaults for __call__. The kwargs passed to __call__ overwrite any defaults from __init__
  3. Deprecate gracefully: Instead of removing parameters immediately, use deprecation warnings and **kwargs to maintain compatibility: “We can introduce the wildcard kwargs and move the deprecated args there, and print a clear warning that it’s deprecated”
  4. Design for evolution: Structure APIs to accept configuration through method parameters rather than constructor-only initialization, enabling reuse across different contexts

Example of backward-compatible parameter evolution:

# Before
def __init__(self, model):
    self.model = model

# After - maintains compatibility while adding type safety
def __init__(self, embedding_model: Union[str, Callable] = 'text-embedding-ada-002', 
             embedding_function: Optional[Callable] = None, **kwargs):
    # Handle both old and new parameter patterns
    self.model = embedding_function or embedding_model
    self.kwargs = kwargs

This approach prevents breaking existing user code while enabling clean API evolution and improved developer experience.


Centralize configuration management

Prefer centralized configuration files (settings.json, settings.ts) over environment variables for application settings, especially when organizational control is needed. Avoid hardcoded assumptions about user environments and ensure configuration is loaded at appropriate initialization points.

Environment variables should be reserved for deployment-specific concerns, while user preferences and feature toggles belong in structured configuration files that support organizational policies and are easier to manage across multiple sources.

Example of preferred approach:

// Instead of:
if (process.env.GEMINI_CLI_DISABLE_AUTOUPDATER === 'true') {
  return;
}

// Prefer:
if (settings.merged.disableAutoUpdater) {
  return;
}

// Load configuration early in initialization:
// Load custom themes from settings
themeManager.loadCustomThemes(settings.merged.customThemes);

This approach enables organizational control through settings.json files, reduces the complexity of merging configuration from multiple sources, and makes configuration more discoverable and maintainable. Additionally, organize reusable configuration interfaces in dedicated files rather than embedding them in component files to support future extensibility and reuse across the application.


minimize merge conflicts

When working with upstream codebases, prioritize coding approaches that minimize merge conflicts while maintaining functionality. Keep dependency arrays in consistent order with upstream code, use CSS classes for conditional styling instead of conditional rendering to create smaller diffs, and isolate custom components in separate directories. For example, instead of wrapping large code blocks in conditionals, use className approaches:

// Prefer this - smaller diff, easier merging
<div className={cn("shrink-0", "w-[70px]", { "hidden": options.length < 2 })}>

// Avoid this - creates large indentation diff
{options.length >= 2 && (
  <div className="shrink-0 w-[70px]">
    // ... large code block
  </div>
)}

This approach reduces the likelihood of merge conflicts and makes code reviews easier to follow when syncing with upstream changes.


Document connection parameters clearly

When documenting network connections (SSH, HTTP, database, etc.), provide clear explanations of all connection parameters, their security implications, and their relationships. Don’t just list placeholders - explain what each parameter represents and why it’s needed.

For connection commands, structure parameter explanations as bulleted lists after the command block. Clarify security-sensitive distinctions (like public vs private keys) and include context about how parameters work together in the network protocol.

Example:

ssh -i PATH_TO_PRIVATE_KEY/PRIVATE_KEY_NAME root@SERVER_IP_ADDRESS

Replace the following:

This approach helps developers understand the security model and connection flow, not just the syntax to copy-paste.


Add unit tests

All new functionality must include corresponding unit tests. This is especially critical for utility functions, core logic modules, stream processing, data transformation methods, and complex business logic. Without unit tests, code becomes difficult to understand and maintain over time.

Key areas that require unit tests:

Example test structure for a utility function:

// For a model parsing utility
describe('detectModelProvider', () => {
  it('should detect anthropic provider for claude models', () => {
    expect(detectModelProvider('claude-3-sonnet')).toBe('anthropic');
  });
  
  it('should default to openai for unknown models', () => {
    expect(detectModelProvider('unknown-model')).toBe('openai');
  });
});

When adding tests, ensure proper mocking of external dependencies and use appropriate test setup (providers, wrappers) to avoid test environment issues. Tests should cover both happy path scenarios and error cases to maintain code reliability.


gRPC interface consistency

Ensure gRPC/RPC interfaces follow consistent patterns for return types, error handling, and method design. Avoid creating duplicate RPC methods when existing ones can be reused, use proper gRPC clients instead of direct imports, and maintain type safety with specific parameter types rather than generic objects.

Key principles:

Example of proper gRPC handler:

// Good - proper return type and error handling
export async function addRemoteMcpServer(
  controller: Controller, 
  request: AddRemoteMcpServerRequest
): Promise<McpServers> {
  if (!request.serverName) {
    throw new Error("Server name is required") // Native gRPC error
  }
  
  const servers = await controller.mcpHub?.addRemoteServer(request.serverName, request.serverUrl)
  return { mcpServers: convertMcpServersToProtoMcpServers(servers) }
}

// Bad - generic response with custom error handling
interface CustomResponse {
  success: boolean
  error?: string
  values?: Record<string, any>
}

This ensures API interfaces are predictable, type-safe, and work consistently across different client implementations.


API consistency patterns

Maintain consistent interface patterns across APIs and avoid loose coupling through magic strings or unstable properties. APIs should follow established conventions and provide stable, well-defined contracts.

Key principles:

  1. Follow established patterns: When designing new APIs, align with existing SDK patterns and conventions. For example, subagent interfaces should “keep this interface consistent with what you see if you are using the SDKs natively” by using standard system prompt strings and chat pairs.

  2. Avoid magic strings and loose metadata: Don’t rely on consumers knowing magic strings or loose information. Instead of metadata objects with string-based properties, use strongly-typed enums or explicit properties that provide compile-time safety.

  3. Use stable properties: Prefer stable, well-defined properties over transient values. For instance, use schema (a stable BaseTool property) rather than parameterSchema (a transient value used to populate the schema field).

  4. Standardize protocols: Extract common protocol patterns into shared libraries rather than having integrators hardcode protocol layers. Methods like ide/diffClosed should be part of a protocol library that IDE integrations can import.

Example of good API consistency:

// Good: Stable, consistent interface
interface ToolInterface {
  name: string;
  schema: SchemaUnion; // Stable property
  execute(params: ToolParams): Promise<ToolResult>;
}

// Avoid: Loose coupling with magic strings
interface ToolInterface {
  metadata: { source: string; behavior: string }; // Magic strings
  parameterSchema: SchemaUnion; // Transient property
}

This approach ensures APIs are predictable, maintainable, and provide clear contracts for consumers.


implement resource constraints

Implement multiple types of resource constraints with appropriate thresholds to prevent performance degradation and resource exhaustion. This includes rate limiting, memory thresholds, execution time limits, and queue size bounds.

Key constraint types to implement:

Rate Limiting: Limit frequency of expensive operations

// Only record when RSS is 5%+ above previous high water mark
if (currentRss > previousHighWaterMark * 1.05) {
  recordMemoryUsage(currentRss);
  previousHighWaterMark = currentRss;
}

Time-based Constraints: Set reasonable timeouts to balance accuracy and user experience

// 50ms timeout for protocol detection to avoid blocking users
setTimeout(() => {
  if (!checkFinished) {
    detectionComplete = true;
    resolve(false);
  }
}, 50);

Execution Limits: Use multiple constraint types for long-running operations

interface RunConfig {
  max_time_minutes: number;
  max_turns: number;        // Stop after N iterations
  max_tokens: number;       // Budget for resource consumption
}

Queue Size Bounds: Prevent unbounded growth with capacity limits

// Use FixedDeque with hard capacity limit
const events = new FixedDeque(1000);
const eventsToRetry = eventsToSend.slice(-this.max_retry_events); // Limit retry count

These constraints should be configurable and set based on the criticality of the operation - more lenient for user-facing features, stricter for background processes. Always consider the trade-off between resource protection and functionality degradation.


Maintain naming consistency

Ensure consistent naming patterns and approaches across similar functionality in the codebase. This includes using named constants instead of magic strings, aligning input handling patterns with existing code, maintaining consistent identifier formats, and following established conventions from libraries or existing implementations.

Key practices:

Example from the discussions:

// Before: Magic string
if (trimmedValue === '__CLEAR_QUEUE__') {
  setQueuedInput(null);
  return;
}

// After: Named constant
import { CLEAR_QUEUE_SIGNAL } from './constants.js';
if (trimmedValue === CLEAR_QUEUE_SIGNAL) {
  setQueuedInput(null);
  return;
}

This approach improves code maintainability, reduces errors from typos in magic strings, and makes the codebase more predictable for developers working across different modules.


Document configuration defaults clearly

When documenting configuration options, always specify exact file paths, explicit default values, and clarify potentially confusing settings to prevent user confusion. This includes documenting where settings are persisted, what happens when optional properties are omitted, and explaining any non-obvious behavior like token budget comparisons.

For example, instead of just mentioning “settings are saved,” specify the exact location:

// Settings are saved to ~/.gemini/settings.json
"vim": true

When documenting optional configuration properties, explicitly state the default behavior:

// authProviderType is optional - omitting it defaults to "dynamic_discovery"
"authProviderType": "dynamic_discovery"  // default

For complex configurations that might cause confusion, add clarifying comments:

// tokenBudget is compared against character length as an approximation
"summarizeToolOutput": {
  "run_shell_command": {
    "tokenBudget": 100  // approximate token count, compared to character length
  }
}

avoid non-null assertions

Avoid using the non-null assertion operator (!) and instead use union types or explicit null checks for better type safety. Non-null assertions bypass TypeScript’s null safety checks and can lead to runtime errors if the assumption is incorrect.

Preferred approach - Use union types:

// Instead of using non-null assertion
return {
  filePath,
  relativePathForDisplay, 
  fileReadResult: fileReadResult!.llmContent  // ❌ Unsafe
};

// Use union types to make success cases explicit
type FileResult = 
  | { success: true; fileReadResult: FileReadResult }
  | { success: false; reason: string };

// TypeScript now properly narrows the type
if (fileResult.success) {
  // fileReadResult is guaranteed to exist here
  return fileResult.fileReadResult.llmContent; // ✅ Safe
}

When explicit checks are safer:

// Instead of non-null assertion
return this.contentGenerator!; // ❌ Bypasses safety

// Use explicit null check with clear error handling
if (!this.contentGenerator) {
  throw new Error('Content generator not initialized');
}
return this.contentGenerator; // ✅ Safe and clear

This approach makes null handling explicit in the type system and prevents runtime errors from incorrect assumptions about null values.


Validate migration conflicts

Before applying database migrations, systematically validate existing data and check for potential conflicts with current schema constraints. This prevents migration failures and ensures backward compatibility.

When modifying database schema or constants that affect database state:

  1. Validate existing data - Check current data integrity and identify potential constraint violations
  2. Check for naming conflicts - Ensure new constraints don’t conflict with existing constraint names
  3. Plan data transformation - Create a step-by-step approach for handling existing data
  4. Create migration scripts - Generate proper migrations for any changes that affect database state

Example approach for constraint modifications:

# 1. Select all, validate all names per user and update db
# 2. Create new table with constraint that does not conflict with existing constraint  
# 3. Insert into it
# 4. Delete old table

This systematic validation prevents issues like foreign key conflicts during table recreation and ensures that changes to constants (like DEFAULT_FOLDER_NAME) don’t break existing database functions that depend on those values.


secure XML parsing

When configuring XML parsing options, carefully evaluate security implications of each setting, especially those that enable potentially risky features like DTD processing. Document the business justification for enabling such features and verify that the chosen library provides adequate protection against common XML-based attacks (XXE, DTD attacks, etc.).

Example of secure XML parsing configuration:

let doc = roxmltree::Document::parse_with_options(
    xml_content,
    roxmltree::ParsingOptions { 
        allow_dtd: true, // Enable only when necessary for business requirements
        ..Default::default() 
    },
)?;

Always include comments explaining why potentially dangerous options are enabled and confirm the library’s security guarantees against relevant attack vectors.


Guard against null

Always use optional chaining (?.) and nullish coalescing (??) operators when accessing potentially undefined or null properties. These patterns prevent TypeErrors when accessing nested properties and provide appropriate defaults only when values are null or undefined.

// Unsafe - may throw TypeError:
const message = runData.data[NodeConnectionTypes.Main][0][0].evaluationData;
const activeModules = [...settings.value.activeModules, 'data-store'];
const isMFAEnforced = settings.value.enterprise.mfaEnforcement;

// Safe - uses proper null handling:
const message = runData?.data?.[NodeConnectionTypes.Main]?.[0]?.[0]?.evaluationData ?? {};
const activeModules = [...(settings.value.activeModules ?? []), 'data-store'];
const isMFAEnforced = settings.value.enterprise?.mfaEnforcement ?? false;

When handling arrays from potentially empty sources, provide empty array defaults and filter out falsy values:

// Handle empty split results with proper filtering
const selectedApps = currentUserCloudInfo.value?.selectedApps?.split(',').filter(Boolean) ?? [];

// Check object existence before property access
if (toolOrToolkit && typeof (toolOrToolkit as Toolkit).getTools === 'function') {
  // Now safe to call the method
}

// Use proper object access patterns to avoid null reference errors
const hasNodeRun = Object.prototype.hasOwnProperty.call(runData ?? {}, node.name);

Always ensure your type definitions accurately represent nullable values. If an API can return null for a field, include it in the type:

// Accurate type for a field that can be null
interface Response {
  stop_reason: string | null;
}

Prevent null reference exceptions

Always use optional chaining and nullish coalescing operators to prevent runtime errors when accessing properties or methods on potentially undefined objects.

Key practices:

  1. Use optional chaining (?.) when accessing properties that may be undefined:
    // UNSAFE: May throw if connectionsByDestinationNode[name] is undefined
    const activeNodeConnections = 
      workflowsStore.connectionsByDestinationNode[activeNode.value.name].main || [];
       
    // SAFE: Uses optional chaining to prevent runtime errors
    const activeNodeConnections = 
      workflowsStore.connectionsByDestinationNode[activeNode.value.name]?.main || [];
    
  2. Apply optional chaining at every level in property chains:
    // UNSAFE: Only checks if node.value exists, but not if type exists
    const packageName = computed(() => node.value?.type.split('.')[0] ?? '');
       
    // SAFE: Checks both node.value and type before calling split
    const packageName = computed(() => node.value?.type?.split('.')[0] ?? '');
    
  3. Choose appropriate default value operators:
    • Use ?? (nullish coalescing) when you only want to provide a default for null or undefined
    • Use || (logical OR) when you want to provide a default for any falsy value (empty string, 0, false) ```typescript // Only use a default when the value is null/undefined return (props.inputDataLength ?? 1) > 1;

    // Use a default for any falsy value, including empty strings :placement=”tooltipPlacement || ‘right’” ```

  4. When dealing with deeply nested properties, ensure all levels are checked:
    // UNSAFE: Will throw if node.value.parameters is undefined
    resource: node.value?.parameters.resource
       
    // SAFE: Checks both node.value and parameters before accessing resource
    resource: node.value?.parameters?.resource
    

This pattern makes your code more resilient by preventing the most common cause of runtime exceptions.


Maintain consistent terminology patterns

Ensure consistent terminology usage across the codebase, especially in localization files and technical documentation. When a term is established (whether in translation or technical context), maintain that same term throughout related files and contexts.

Key guidelines:

  1. Use identical technical terms across related contexts (e.g., if using “API key”, don’t switch to “API token”)
  2. Maintain consistent translations for technical terms across localization files
  3. Preserve capitalization patterns for product/technical names
  4. Use the same term for identical concepts across different languages

Example:

// Incorrect - Inconsistent terminology
{
  "vectorStore": {
    "embeddings": "埋め込み次元",
    "dimensions": "ベクター次元"  // Inconsistent with embeddings
  }
}

// Correct - Consistent terminology
{
  "vectorStore": {
    "embeddings": "ベクター次元",
    "dimensions": "ベクター次元"  // Maintains consistency
  }
}

This practice improves code maintainability, reduces confusion, and ensures a more professional user experience, especially in localized applications.


Ensure comprehensive user documentation

All user-facing features, APIs, and tools must have clear, comprehensive documentation that explains their purpose, limitations, and usage. Documentation should use terminology that users can understand, provide helpful guidance for common scenarios, and include warnings about potential issues.

Key requirements:

Example of good documentation:

/**
 * Processes import statements in GEMINI.md content
 * Supports @path/to/file.md syntax for importing content from other files
 * 
 * Note: Only .md files are supported. Attempting to import other file types
 * will result in a warning and the import will be skipped.
 */
export async function processImports(content: string, basePath: string): Promise<string> {
  // Implementation with clear error messages for unsupported file types
  if (!importPath.endsWith('.md')) {
    console.warn(`[WARN] Only .md files are supported for imports. Skipping: ${importPath}`);
    return content;
  }
}

This ensures users can effectively use features without confusion and reduces support burden by providing clear guidance upfront.


classify errors appropriately

Different types of errors require different handling strategies. Classify errors into categories and apply appropriate response patterns: fail fast for user-actionable problems, retry with backoff for transient issues, and graceful degradation for non-critical failures.

Error Classification Guidelines:

Example Implementation:

const shouldRetry = (err) => {
  // Network errors - retry
  if (!err.statusCode) return true;
  
  // Rate limits and server errors - retry  
  if (err.statusCode === 429 || err.statusCode >= 500) return true;
  
  // Client errors - fail fast
  return false;
};

// For user-facing features - fail fast
if (userWantsTelemetry && !telemetryWorking) {
  throw new Error('Telemetry failed - user should know');
}

// For background operations - graceful degradation
try {
  await backgroundTelemetry();
} catch (error) {
  console.debug('Background telemetry failed:', error);
  // Continue execution
}

This approach prevents infinite retry loops on permanent failures while ensuring transient issues are handled gracefully and users are informed when they need to take action.


Optimize loop operations

Avoid repeated computations and object creation in loops or high-frequency operations. Move invariant calculations outside the loop and reuse objects rather than creating new instances on each iteration. This reduces CPU overhead, memory churn, and improves performance in critical code paths.

Key practices:

  1. Pre-calculate values that don’t change between iterations
  2. Initialize objects before loops when they can be reused
  3. Cache expensive operation results rather than recalculating
  4. Avoid unnecessary object creation with spreads or concatenations

Example - Before:

const searchByName = (query: string, limit: number = 20): NodeSearchResult[] => {
  const normalizedQuery = query.toLowerCase();
  const results: NodeSearchResult[] = [];

  for (const nodeType of this.nodeTypes) {
    // Name is lowercased on every iteration
    if (nodeType.name.toLowerCase().includes(normalizedQuery)) {
      // Score calculation logic...
    }
  }
  // ...
};

After:

// Pre-calculate lowercase names when loading node types
const initNodeTypes = (types) => {
  return types.map(type => ({
    ...type,
    nameLower: type.name.toLowerCase(),
  }));
};

const searchByName = (query: string, limit: number = 20): NodeSearchResult[] => {
  const normalizedQuery = query.toLowerCase();
  const results: NodeSearchResult[] = [];

  for (const nodeType of this.nodeTypes) {
    // Use pre-calculated lowercase name
    if (nodeType.nameLower.includes(normalizedQuery)) {
      // Score calculation logic...
    }
  }
  // ...
};

Consistent naming patterns

Maintain consistent naming conventions throughout the codebase to improve readability and maintainability. This applies to translation keys, command names, variables, and terminology.

For translation keys:

For command and function names:

For terminology:

Consistency in naming reduces cognitive load for developers, prevents bugs from mismatched references, and makes the codebase more maintainable over time.


Optimize algorithm implementations

When implementing algorithms, ensure they are both efficient and correct across all input cases. Key considerations:

  1. Pattern matching edge cases: Ensure regex patterns handle all edge cases, including matches at the beginning of strings. For example, replace /[^\\][^\n]+/ with /(?:^ [^\])[^\n]+/ to catch backticks at string start.
  2. Algorithmic complexity: Prevent potential denial-of-service vulnerabilities by analyzing time complexity of algorithms, especially regular expressions on user input. For example, avoid patterns like /^\[([^\]]*)\]\s*(.*)$/ that can cause performance issues with certain inputs.

  3. False positive prevention: Configure pattern detection algorithms to avoid false matches. Start pattern searches from length 2 instead of 1 to prevent single repeated elements from being incorrectly identified as patterns:
    // Instead of:
    for (let patternLength = 1; patternLength <= maxPatternLength; patternLength++) {
    // Use:
    for (let patternLength = 2; patternLength <= maxPatternLength; patternLength++) {
    
  4. Precise matching: For keyword detection, use word boundaries instead of simple substring matching to improve accuracy:
    // Instead of:
    return keywords.some((keyword) => text.includes(keyword))
    // Use:
    return keywords.some((keyword) => new RegExp(`\\b${keyword}\\b`).test(text))
    

Following these practices helps create algorithms that are not only computationally efficient but also robust against edge cases and potential security exploits.


Explicit API parameters

Design APIs with explicit parameters rather than implicit defaults or hidden behavior. When an API function requires specific data or configuration, make those requirements clear through the function signature instead of relying on optional parameters with complex fallback logic.

This approach improves developer experience by making the API contract obvious and reducing confusion about what inputs are actually needed. Developers should be able to understand the API requirements without reading implementation details or documentation.

For example, instead of having optional parameters with hidden default resolution:

// Avoid: Hidden default behavior
async function routeEmail(email: Email, env: Env, options?: {
  defaultAgentName?: string;
  defaultAgentId?: string;
}) {
  // Complex internal logic to determine routing
}

// Prefer: Explicit resolver requirement  
async function routeEmail(
  email: Email, 
  env: Env,
  resolver: EmailResolver<Env> // Required, not optional
) {
  // Clear contract - resolver is always needed
}

Similarly, extract and pass only the specific data needed rather than entire objects:

// Instead of passing entire request object
const error = await doStub.onSSEMcpMessage(sessionId, request);

// Extract and pass only what's needed
const messageBody = await request.json();
const error = await doStub.onSSEMcpMessage(sessionId, messageBody);

This principle applies to method parameters, configuration options, and data extraction - always favor explicit, clear interfaces over implicit behavior that requires developers to understand internal implementation details.


Use established configuration patterns

Always access and set configuration values using established patterns and correct property names. Understanding the structure of configuration objects is essential to prevent bugs in your application.

When working with external services:

When handling persistent configurations:

When setting conditional configuration values:

// Incorrect
if (defaultModel?.provider === "anthropic") { ... }
const storedId = localStorage.getItem("lastSessionId");
const alwaysApply = newRuleType !== RuleType.AgentRequested;

// Correct
if (defaultModel?.underlyingProviderName === "anthropic") { ... }
const storedId = getLocalStorage("lastSessionId");
const alwaysApply = newRuleType === RuleType.Always || newRuleType === RuleType.AutoAttached;

Prevent React race conditions

When building React components that handle rapid user input or manage complex interdependent state, consolidate state management to prevent race conditions that occur when multiple events are processed in the same React event loop.

Key strategies:

  1. Use useReducer for complex interdependent state instead of multiple useState calls. This centralizes state logic, improves performance by reducing re-renders, and eliminates potential race conditions from multiple state updates.

  2. Integrate utility functions with centralized state rather than operating on potentially stale closures or separate state variables.

Example:

// ❌ Problematic: Multiple useState calls for interdependent state
const [mode, setMode] = useState('NORMAL');
const [count, setCount] = useState(0);
const [pendingG, setPendingG] = useState(false);
const [pendingD, setPendingD] = useState(false);

// ❌ Utility functions operating separately
const findNextWordStart = (text: string, offset: number) => {
  // May operate on stale state when multiple keystrokes occur rapidly
};

// ✅ Better: Single useReducer for interdependent state
const [state, dispatch] = useReducer(vimReducer, {
  mode: 'NORMAL',
  count: 0,
  pendingG: false,
  pendingD: false,
});

// ✅ Integrate utilities with centralized state management
// Move utility functions into the same state management system
// to ensure they operate on current state

This approach prevents issues where “multiple keystrokes need to be processed in the same React event loop” and eliminates race conditions from managing complex state machines in React components.


Use idiomatic optional patterns

Prefer Rust’s built-in optional handling methods over manual checks and intermediate variables. Use if let Some(value) = option for pattern matching, option.map(|x| x.field).unwrap_or(default) for transformations with fallbacks, and option.is_some_and(|x| condition) for conditional checks.

Instead of creating intermediate variables:

let is_recipe_execution = recipe.is_some();
let recipe_name_for_telemetry = recipe.clone().unwrap_or_default();

Use direct pattern matching:

if let Some(recipe_name) = recipe {
    // use recipe_name directly
}

Instead of verbose match statements:

let recipe_version = match load_recipe(&name, params) {
    Ok(recipe) => recipe.version,
    Err(_) => "unknown".to_string(),
};

Use method chaining:

let recipe_version = load_recipe(&name, params)
    .map(|r| r.version)
    .unwrap_or_else(|| "unknown".to_string());

These patterns reduce boilerplate, improve readability, and leverage Rust’s type system for safer null handling.


Complete error handling cycle

Implement comprehensive error handling that covers prevention, recovery, and diagnosis:

  1. Prevent errors through thorough validation before enabling actions
    • Validate that all required data exists before allowing operations
      // Instead of just checking mime type and filename
      function isDownloadable(index, key) {
      const { mimeType, fileName } = binaryData[index][key];
      return !!(mimeType && fileName && (binaryData[index][key].id || binaryData[index][key].data));
      }
      
  2. Ensure recovery by properly resetting state flags in finally blocks
    • Don’t leave UI in disabled states after operations complete or fail
      try {
      cancellingTestRun.value = true;
      await evaluationStore.cancelTestRun(workflowId, runId);
      } catch (error) {
      // Error handling
      } finally {
      cancellingTestRun.value = false;
      }
      
  3. Enable diagnosis by preserving and exposing error details
    • Log complete error objects, not just generic messages
      } catch (error) {
      console.error(chalk.red(`An error occurred during the build process: ${error}`));
      }
      

Each layer of error handling contributes to a more robust application that prevents user frustration and simplifies troubleshooting.


optimize React hooks usage

Avoid useRef unless strictly necessary and ensure useEffect has proper dependencies to prevent unnecessary re-renders. useRef makes logic harder to reason about and should be replaced with more straightforward patterns when possible. For useEffect, extract values outside the effect when they don’t need to be dependencies, and ensure the dependency array accurately reflects what the effect actually uses.

Example of avoiding useRef:

// Instead of using useRef for callbacks
() => toggleVimModeRef.current?.()

// Use a generic function approach
const handleSettingsUpdate = (updateFn) => updateFn();

Example of optimizing useEffect:

// Extract values that don't need to be dependencies
const prompt = config.getQuestion();
useEffect(() => {
  // Use prompt here
}, [/* proper dependencies only */]);

This approach improves code maintainability by making component logic more predictable and reducing unnecessary re-renders that can impact performance.


Prefer lightweight composable APIs

When designing APIs, favor lightweight, composable solutions that allow callers to maintain control over their specific use cases, rather than imposing centralized, monolithic systems that take control away from the caller.

This principle emerges from recognizing that different parts of an application often have unique requirements that are difficult to accommodate in a one-size-fits-all solution. Lightweight APIs that provide building blocks for callers to compose are more flexible and easier to adopt incrementally.

For example, instead of creating a centralized service that “requires taking control of all useInput in the application,” design an API that “allows callers to resolve whether specific input matches a specific keybinding.” This approach respects existing code patterns and reduces the risk of breaking changes during adoption.

Similarly, when handling user input or arguments, prefer simple, predictable approaches like direct appending rather than complex parsing mechanisms with special separators. This makes the API more intuitive and reduces cognitive overhead for both implementers and users.

// Avoid: Centralized control that requires major refactoring
const keybindingService = new KeybindingService();
keybindingService.takeControlOfAllInput();

// Prefer: Composable utilities that work with existing patterns
const isMatch = keybindingResolver.matches(input, 'save-file');
if (isMatch) handleSave();

Complete locale translations

Ensure that all text strings in locale-specific files are properly translated into their respective languages. Leaving untranslated English text in non-English locale files creates an inconsistent user experience and reduces the effectiveness of localization efforts.

When adding new features or UI elements:

  1. Identify all strings that need translation
  2. Ensure translations are provided for every supported language
  3. Verify that no English text remains in non-English locale files
  4. Use native punctuation conventions of the target language

Example of a problem:

// webview-ui/src/i18n/locales/es/mcp.json
{
  "serverStatus": {
    "retrying": "Reintentando...",
    "retryConnection": "Reintentar conexión",
    "disabled": "Server is disabled"  // English text in Spanish file
  }
}

Correct implementation:

// webview-ui/src/i18n/locales/es/mcp.json
{
  "serverStatus": {
    "retrying": "Reintentando...",
    "retryConnection": "Reintentar conexión",
    "disabled": "Servidor deshabilitado"  // Properly translated to Spanish
  }
}

Internationalize all text

All user-facing text must be wrapped with translation functions instead of using hardcoded English strings. This includes regular UI text, accessibility attributes (aria-label, title, alt), and screen reader announcements. Using translation keys creates a consistent, maintainable internationalization system and ensures the application is accessible to users in all supported languages.

When using translation functions:

// Incorrect
<h2 className="text-lg font-bold">Something went wrong</h2>
<button title="Add reaction" aria-label="Collapse command management section">
  {screenReaderAnnouncement}
</button>

// Correct
<h2 className="text-lg font-bold">{t("errorBoundary.title")}</h2>
<button 
  title={t("emojiReactions.add")} 
  aria-label={t("chat:commandExecution.collapseManagement")}>
  {t("chat:screenReader.announcement")}
</button>

For string interpolation, use translation parameters rather than concatenating strings:

// Incorrect
<span>{`File: ${selectedOption.value}, ${selectedMenuIndex + 1} of ${options.length}`}</span>

// Correct
<span>
  {t("chat:contextMenu.announceFile", { 
    name: selectedOption.value, 
    position: t("chat:contextMenu.position", { 
      current: selectedMenuIndex + 1, 
      total: options.length 
    })
  })}
</span>

Centralize configuration management

Prefer centralized configuration objects over environment variables for application settings. Environment variables create inconsistent configuration sources and can lead to maintenance challenges.

Guidelines:

For feature flags or experimental options, use structured configuration with appropriate prefixes:

// Preferred
config.experimental_resume = true;

// Instead of
if std::env::var("CODEX_EXPERIMENTAL_RESUME").is_ok() { ... }

When environment variables must be used:

Remember that modifying environment variables is inherently racy in multi-threaded contexts and has been marked as unsafe in recent Rust editions.


Choose efficient data structures

Select data structures and algorithms that match your performance requirements rather than defaulting to simple but inefficient approaches. Consider the time complexity of operations and use specialized libraries when appropriate.

Key principles:

Example from the discussions:

// Avoid: O(n) splice operations on arrays
if (this.events.length >= this.max_events) {
  const eventsToRemove = this.events.length - this.max_events + 1;
  this.events.splice(0, eventsToRemove); // O(n) operation
}

// Prefer: O(1) operations with appropriate data structure
import { FixedDeque } from 'mnemonist';
// FixedDeque automatically handles overflow with O(1) operations
this.events = new FixedDeque(this.max_events);
this.events.push(newEvent); // O(1) with automatic FIFO overflow

Similarly, prefer glob libraries over recursive directory traversal, and minimatch over custom regex implementations for pattern matching. The performance benefits compound significantly as data sizes grow.


Validate API data contracts

Always validate API request and response data using schema validation to ensure type safety and prevent runtime errors. Define explicit schemas (e.g., using Zod or similar) for all API interfaces rather than relying on TypeScript types alone.

Example:

// Before
interface ChatMessage {
  action: string;
  chatInput: string;
  sessionId: string;
}

async function handleMessage(data: RawData) {
  const message = jsonParse<ChatMessage>(data.toString());
  // No validation, could fail at runtime
  await processMessage(message);
}

// After
const chatMessageSchema = z.object({
  action: z.enum(['user', 'system']),
  chatInput: z.string(),
  sessionId: z.string().uuid()
});

type ChatMessage = z.infer<typeof chatMessageSchema>;

async function handleMessage(data: RawData) {
  const rawMessage = jsonParse(data.toString());
  const message = chatMessageSchema.parse(rawMessage);
  // Validated data, guaranteed to match schema
  await processMessage(message);
}

This practice:


Minimize blocking operations

When writing concurrent code, minimize blocking operations to maintain responsiveness and prevent performance bottlenecks. This applies especially to async contexts and lock usage.

For asynchronous operations:

For lock handling:

Example - Before:

{
    let mut running_requests_id_to_codex_uuid = running_requests_id_to_codex_uuid.lock().await;
    running_requests_id_to_codex_uuid.insert(request_id.clone(), session_id);
}

After:

running_requests_id_to_codex_uuid.lock().await.insert(request_id.clone(), session_id);

For mutex usage:

// Bad: Lock held longer than necessary
let mut flag = self.pending_redraw.lock().unwrap();
if *flag {
    return;
}
*flag = true;
// Lock still held here when it's no longer needed

// Good: Lock released as soon as possible
{
    let mut flag = self.pending_redraw.lock().unwrap();
    if *flag {
        return;
    }
    *flag = true;
} // Lock released here
// Continue with operations that don't need the lock

Organize code top down

Structure code files with a clear top-down organization, placing primary functions and important declarations at the top, followed by helper functions and implementation details below. This improves code readability and maintainability by establishing a clear hierarchy.

Key principles:

  1. Place core public interfaces and primary functions at the top
  2. Move helper functions and implementation details to the bottom
  3. Extract large code blocks into separate files when they represent distinct functionality
  4. Position shared computations before their usage points

Example:

// Primary public interface first
pub fn process_event(&mut self, event: Event) {
    self.dispatch_event(event)
}

// Main implementation functions next
fn dispatch_event(&mut self, event: Event) {
    let common_data = self.prepare_common_data();  // Shared computation moved up
    match event {
        Event::A => self.handle_a(common_data),
        Event::B => self.handle_b(common_data),
    }
}

// Helper functions last
fn prepare_common_data(&self) -> Data {
    // Implementation details...
}

fn handle_a(&mut self, data: Data) {
    // Implementation details...
}

fn handle_b(&mut self, data: Data) {
    // Implementation details...
}

Secure credential data handling

Always protect sensitive credential data through proper encryption, secure storage, and careful handling in code. Key requirements:

  1. Never store credentials in plaintext within source code
  2. Use appropriate encryption for sensitive fields
  3. Preserve user-configured security settings
  4. Handle credential updates safely

Example - Instead of:

class Config {
  password: string = 'admin';  // BAD: Hardcoded credential
  
  constructor(options) {
    this.tls = {};  // BAD: Overwrites user TLS settings
  }
}

Use:

class Config {
  @Env('DB_PASSWORD')  // GOOD: Environment variable
  password: string = '';
  
  constructor(options) {
    this.tls = options.tls ?? {};  // GOOD: Preserves settings
  }
}

// GOOD: Proper credential field protection
class Credentials {
  @Column({
    type: 'string',
    typeOptions: { password: true }  // Enables encryption
  })
  sslKey: string;
}

---

## Prevent unnecessary processing

<!-- source: RooCodeInc/Roo-Code | topic: Performance Optimization | language: TSX | updated: 2025-07-22 -->

Optimize React component performance by minimizing unnecessary operations that can slow down your application:

1. **Memoize stable components** to prevent unnecessary re-renders when parent components update:
```typescript
// Instead of using components directly
<DeleteMessageDialog {...props} />

// Memoize components that receive the same props frequently
const MemoizedDeleteMessageDialog = React.memo(DeleteMessageDialog);
<MemoizedDeleteMessageDialog {...props} />
  1. Debounce frequent effect triggers to avoid performance bottlenecks: ```typescript useEffect(() => { if (!someCondition) return;

const timeoutId = setTimeout(() => { // Perform the operation after a brief delay }, 100);

return () => clearTimeout(timeoutId); }, [frequentlyChangingDependency]);


3. **Avoid inefficient deep comparisons** on large objects:
```typescript
// Avoid this pattern on large objects
if (JSON.stringify(objA) !== JSON.stringify(objB)) {
  // Update logic
}

// Instead, use dedicated comparison libraries or memoized selectors
import { isEqual } from 'lodash';
if (!isEqual(objA, objB)) {
  // Update logic
}
  1. Lift providers to appropriate levels in your component tree to reduce overhead: ```typescript // Instead of creating providers in each component: function MyComponent() { return (

    ); }

// Create providers once at a higher level: function App() { return ( ); }


These optimizations should be applied thoughtfully where measurements show actual performance impact, rather than as premature optimization.

---

## Avoid unnecessary operations

<!-- source: openai/codex | topic: Performance Optimization | language: Rust | updated: 2025-07-22 -->

Optimize performance by eliminating operations that don't contribute meaningful value to your code's functionality. Look for three common performance drains:

1. **Redundant I/O operations**: Avoid unnecessary file system operations like flushing a file that has already been flushed or has no new content.
   
2. **Excessive UI rendering**: Implement throttling at the appropriate architectural level rather than in individual components. Consider centralizing performance controls in higher-level components where they can be applied globally.

3. **Unnecessary memory allocations**: Use references or smarter allocation patterns instead of blindly cloning data structures.

```rust
// Instead of always cloning:
let prompt = if missing_calls.is_empty() {
    prompt.clone()
    // ...
}

// Use Cow to avoid unnecessary cloning:
let prompt: Cow<'_, Prompt> = if missing_calls.is_empty() {
    Cow::Borrowed(prompt)
} else {
    // Only clone when necessary
    Cow::Owned(prompt.clone().with_additional_items(missing_calls))
}

Each unnecessary operation compounds to create performance bottlenecks. Regularly review your code for these patterns and refactor when identified.


extract duplicated code

Identify and eliminate code duplication by extracting shared logic into reusable functions, components, or type definitions. When you notice similar code patterns appearing in multiple places, refactor them into a single, well-named abstraction.

This applies to:

For example, instead of duplicating JSX:

{extensionTooltip ? (
  <TooltipWrapper tooltipContent={extensionTooltip}>
    <span className="ml-[10px]">
      {getToolDescription() || snakeToTitleCase(toolCall.name)}
    </span>
  </TooltipWrapper>
) : (
  <span className="ml-[10px]">
    {getToolDescription() || snakeToTitleCase(toolCall.name)}
  </span>
)}

Extract the shared element:

const toolLabel = (
  <span className="ml-[10px]">
    {getToolDescription() || snakeToTitleCase(toolCall.name)}
  </span>
);

return extensionTooltip ? (
  <TooltipWrapper tooltipContent={extensionTooltip}>{toolLabel}</TooltipWrapper>
) : (
  toolLabel
);

Similarly, extract repeated function calls:

// Instead of repeating setMentionPopover(prev => ({ ...prev, isOpen: false }))
const closeMentionPopover = () => {
  setMentionPopover(prev => ({ ...prev, isOpen: false }));
};

This improves maintainability, reduces the chance of inconsistencies, and makes the code more readable by giving meaningful names to repeated patterns.


Avoid premature memoization

Don’t automatically reach for useMemo and useCallback for every computation or function. These hooks add complexity and should only be used when there’s a measurable performance benefit. Consider the actual cost of the operation and frequency of re-renders before memoizing.

Use memoization when:

Avoid memoization for:

Example of appropriate memoization:

// Good: Component re-renders frequently, URL construction has dependencies
const clineUris = useMemo(() => {
  const base = new URL(clineUser?.appBaseUrl || CLINE_APP_URL)
  const dashboard = new URL("dashboard", base)
  const credits = new URL(activeOrganization ? "/organization" : "/account", dashboard)
  credits.searchParams.set("tab", "credits")
  return { dashboard, credits }
}, [clineUser?.appBaseUrl, activeOrganization])

Remember: “Premature optimization is the root of all evil.” Profile first, optimize second.


Use appropriate logging levels

Use console.debug() for debug information instead of console.log() to prevent cluttering user-facing output. Debug information should be hidden from normal users but available when debugging is enabled.

When logging information that is primarily useful for developers or troubleshooting, use console.debug() rather than console.log(). This ensures that users don’t see unnecessary technical details during normal operation, while still making the information available when needed for debugging.

Example:

// Bad - users will see this debug information
console.log("buildImangeName:imageName ", imageName);
console.log(`Discovered tool: ${funcDecl.name}`);

// Good - debug information is properly categorized
console.debug("buildImangeName:imageName ", imageName);
console.debug(`Discovered tool: ${funcDecl.name}`);

This practice improves user experience by keeping the console output clean while maintaining valuable debugging capabilities for developers.


Consider semantic context

When choosing names for variables, methods, classes, or configuration sections, consider both the current purpose and potential future extensions. Names should be semantically accurate and align with established conventions in the codebase.

For configuration sections or groupings, choose names that can accommodate related functionality rather than being overly specific. For example, prefer “triggers” over “keybindings” if the section might later include other trigger types like diagnostics or watch triggers.

Always verify that naming choices follow existing team conventions and documented rules. Consistency with established patterns is crucial for maintainability.

Example:

// Instead of overly specific:
"keybindings": { ... }

// Choose semantically broader:
"triggers": { 
  "keybindings": { ... },
  // Future: "diagnostics": { ... }
}

Generic security configuration naming

When implementing security-related configuration options, use generic, implementation-agnostic naming conventions rather than tying them to specific tools or runtimes. This approach ensures flexibility as the underlying technology stack evolves and prevents vendor lock-in in security configurations.

For example, when adding container security flags, prefer generic names like SANDBOX_FLAGS over tool-specific names like DOCKER_RUN_FLAGS. This allows the same configuration to work across different container runtimes (Docker, Podman, etc.) without requiring changes to user configurations.

Example:

# Good: Generic naming that works across container runtimes
export SANDBOX_FLAGS="--security-opt label=disable"

# Avoid: Tool-specific naming that limits flexibility  
export DOCKER_RUN_FLAGS="--security-opt label=disable"

This principle is especially important for security configurations because:

When reviewing security-related configuration code, ensure that environment variables, configuration keys, and API parameters use descriptive, generic names that reflect their security purpose rather than the specific tool being configured.


Protect shared state access

Ensure thread-safe access to shared state by using appropriate synchronization mechanisms and atomic operations. Avoid race conditions by:

  1. Using atomic operations or locks when modifying shared state
  2. Acquiring locks in a consistent order to prevent deadlocks
  3. Ensuring state consistency during async operations
  4. Properly handling cleanup of async resources

Example of unsafe code:

class StateManager {
    private cachedInfo: ModelInfo | null = null;
    
    async getInfo() {
        if (!this.cachedInfo) {  // Race condition: multiple threads might pass this check
            this.cachedInfo = await fetchModelInfo();  // Multiple simultaneous fetches possible
        }
        return this.cachedInfo;
    }
}

Safe version:

class StateManager {
    private cachedInfo: ModelInfo | null = null;
    private fetchPromise: Promise<ModelInfo> | null = null;
    
    async getInfo() {
        if (this.fetchPromise) {
            return this.fetchPromise;  // Reuse in-flight request
        }
        
        if (!this.cachedInfo) {
            this.fetchPromise = fetchModelInfo();
            try {
                this.cachedInfo = await this.fetchPromise;
            } finally {
                this.fetchPromise = null;  // Clear promise reference
            }
        }
        return this.cachedInfo;
    }
}

This pattern prevents multiple simultaneous fetches, handles errors gracefully, and maintains state consistency across async operations.


Extract reusable patterns

Extract repetitive or complex code into reusable functions, components, or custom hooks. This improves code organization, reduces duplication, and enhances readability.

For UI components:

For logic patterns:

Example (Before):

// Complex event handling logic embedded in component
const className = primaryButtonText === t("chat:startNewTask.title") && currentTaskItem?.id
  ? "flex-1 mr-[6px]"
  : secondaryButtonText
    ? "flex-1 mr-[6px]"
    : "flex-[2] mr-0";

// Repeated pattern for extracting values from events
const value = (e as unknown as CustomEvent)?.detail?.target?.value || 
              ((e as any).target as HTMLTextAreaElement).value;

Example (After):

// Helper function for className logic
function getButtonClassName(primaryButtonText, t, currentTaskItem, secondaryButtonText) {
  const showShareButton = primaryButtonText === t("chat:startNewTask.title") && currentTaskItem?.id;
  return showShareButton || secondaryButtonText 
    ? "flex-1 mr-[6px]" 
    : "flex-[2] mr-0";
}

// Reusable event value extractor
function getEventValue(e: React.SyntheticEvent | CustomEvent): string {
  return (e as unknown as CustomEvent)?.detail?.target?.value || 
         ((e as React.ChangeEvent<HTMLTextAreaElement>).target).value;
}

Configure with care

Always validate configuration values before use, provide sensible defaults, and centralize constants in shared modules. When implementing configuration handling:

  1. Use explicit undefined checks instead of truthy checks to properly handle zero values: ```typescript // Incorrect: Will skip valid zero values if (configuration.commandExecutionTimeout) { // Handle timeout }

// Correct: Properly handles zero values if (configuration.commandExecutionTimeout !== undefined) { // Handle timeout }


2. Apply bounds checking for numerical values to ensure they're within acceptable ranges:
```typescript
// Validate within reasonable bounds
const maxImagesPerResponse = Math.max(1, Math.min(100, state?.mcpMaxImagesPerResponse ?? 20));
const maxImageSizeMB = Math.max(0.1, Math.min(50, state?.mcpMaxImageSizeMB ?? 10));
  1. Parse or validate types for configuration fields to prevent propagating invalid values:
    // Ensure configuration value is a valid number
    this.modelDimension = typeof config.modelDimension === 'number' && !isNaN(config.modelDimension) 
      ? config.modelDimension 
      : DEFAULT_MODEL_DIMENSION;
    
  2. Extract repeated literal values into named constants to maintain consistency: ```typescript // Define in a shared constants file export const DEFAULT_CLAUDE_CODE_MAX_OUTPUT_TOKENS = 8000;

// Use the constant throughout the codebase return settings.claudeCodeMaxOutputTokens || DEFAULT_CLAUDE_CODE_MAX_OUTPUT_TOKENS;


Proper configuration handling prevents subtle bugs, improves maintainability, and makes your code more resilient to external changes.

---

## Document i18n string usage

<!-- source: RooCodeInc/Roo-Code | topic: Documentation | language: TypeScript | updated: 2025-07-21 -->

All user-facing strings must be documented with translation function usage to ensure proper internationalization support. This includes error messages, notifications, labels, and any text displayed to users.

Example:
```typescript
// ❌ Don't use hardcoded user-facing strings
const notice = `Image file is too large (${imageSizeInMB} MB). The maximum allowed size is 5 MB.`

// ✅ Document translation key usage for user-facing strings
const notice = t('tools:readFile.imageTooLarge', { 
  size: imageSizeInMB,
  max: 5 
})

Key requirements:

This ensures maintainable internationalization support and clear documentation of translatable content throughout the codebase.


Conditional debug logging

Remove or conditionally disable console.log and console.debug statements before committing code to production. These debugging statements create noise in browser consoles, may expose sensitive information, and can impact runtime performance.

Instead of using direct console logging statements, implement a logging utility that respects environment settings:

// logger.ts
export const logger = {
  debug: (message: string, ...args: any[]) => {
    if (process.env.NODE_ENV === 'development' || localStorage.getItem('debug-enabled') === 'true') {
      console.debug(`[DEBUG] ${message}`, ...args);
    }
  },
  log: (message: string, ...args: any[]) => {
    if (process.env.NODE_ENV === 'development' || localStorage.getItem('debug-enabled') === 'true') {
      console.log(`[LOG] ${message}`, ...args);
    }
  },
  // Always show warnings and errors
  warn: (message: string, ...args: any[]) => console.warn(`[WARN] ${message}`, ...args),
  error: (message: string, ...args: any[]) => console.error(`[ERROR] ${message}`, ...args),
};

// Usage example - replaces instances like:
// console.log(`McpErrorRow level: ${error.level} for message: ${error.message.substring(0, 20)}...`)
// With:
logger.debug(`McpErrorRow level: ${error.level} for message: ${error.message.substring(0, 20)}...`);

For test files, remove all debugging statements entirely to keep test output clean. Consider adding a linting rule to catch accidental console statements before they reach code review.


Optimize React components

Apply these React optimization techniques to improve component performance and maintainability:

  1. Use stable, unique keys for list items - Avoid using array indices as keys when rendering lists that can change. Instead, use unique identifiers from your data.
{/* Avoid this */}
{patterns.map((item, index) => (
  <div key={`${item.pattern}-${index}`} className="ml-5 flex items-center gap-2">
    {/* content */}
  </div>
))}

{/* Prefer this */}
{patterns.map((item) => (
  <div key={item.pattern} className="ml-5 flex items-center gap-2">
    {/* content */}
  </div>
))}
  1. Memoize computed values and callbacks - Use React.useMemo() for arrays/objects and useCallback() for functions to prevent unnecessary recreations during renders.
// Avoid recreating arrays/objects on every render
const toolGroups = React.useMemo(() => [
  // array contents
], [/* dependencies */]);
  1. Use React refs instead of direct DOM manipulation - Avoid document.querySelector and similar methods in favor of React’s ref system.
// Instead of:
const enhanceButton = document.querySelector('[aria-label*="enhance"]');

// Prefer:
const enhanceButtonRef = useRef(null);
// Then pass the ref to the component
<Button ref={enhanceButtonRef} aria-label="enhance" />
  1. Simplify state management - Keep state minimal and focused on what’s needed. Use simple values over complex collections when possible.
// Instead of tracking all instances in a collection:
const [followUpAnswered, setFollowUpAnswered] = useState<Set<number>>(new Set());

// Consider tracking just what's needed:
const [currentFollowUpTs, setCurrentFollowUpTs] = useState<number | null>(null);

leverage TypeScript nullability

When dealing with values that may be null or undefined, explicitly leverage TypeScript’s nullable types to identify dependencies and guide null handling decisions. Make values nullable when their availability is uncertain, then let TypeScript reveal where null checks are needed.

For runtime scenarios where the type system cannot guarantee non-null values (like providers or external dependencies), use defensive null checks with optional chaining:

// When type system can't guarantee non-null at runtime
if (chatContext?.setRecipeParameters) {
  chatContext.setRecipeParameters(inputValues);
}

For values you control, make them explicitly nullable and let TypeScript guide you to handle all null cases:

// Make uncertain values explicitly nullable
let pid: number | null;
// TypeScript will now enforce null checks wherever pid is used

This approach combines the safety of explicit nullable types with defensive programming for runtime uncertainties, ensuring comprehensive null handling coverage.


Optimize algorithmic efficiency

Always consider the computational complexity of your algorithms and leverage efficient built-in methods when available. Look for opportunities to reduce time complexity and avoid unnecessary operations like redundant loops or object creation.

Common inefficiencies to watch for:

Examples of improvements:

Before (O(n^2) deduplication):

promptParams.forEach((promptParam) => {
  if (!allParams.some((param) => param.key === promptParam.key)) {
    allParams.push(promptParam);
  }
});

After (O(n) with Map):

const paramMap = new Map(allParams.map(p => [p.key, p]));
promptParams.forEach(p => paramMap.set(p.key, p));
const allParams = Array.from(paramMap.values());

Before (unnecessary string creation):

const beforeCursor = text.slice(0, cursorPosition);
const lastAtIndex = beforeCursor.lastIndexOf('@');

After (direct method usage):

const lastAtIndex = text.lastIndexOf('@', cursorPosition - 1);

Validate object availability

Always verify that objects and their properties exist before accessing them to prevent null reference errors. This includes checking for undefined global objects, optional parameters, and nested properties.

When you know an object or property is guaranteed to exist (like when checking param.default exists), keep the logic simple and avoid unnecessary validation:

// Good: Simple check when we know default exists
if (param.requirement === 'optional' && param.default) {
  initialValues[param.key] = param.default;
}

When accessing potentially undefined objects, add explicit checks:

// Good: Check object existence before use
useEffect(() => {
  if (window.electron) {
    const currentVersion = window.electron.getVersion();
    setUpdateInfo((prev) => ({ ...prev, currentVersion }));
  }
}, []);

This prevents runtime errors and makes your code more robust by handling null/undefined cases explicitly rather than assuming objects will always be available.


Validate nullable values explicitly

Always handle potentially null or undefined values explicitly using type guards, null coalescing operators, and proper fallback values. This ensures type safety and prevents runtime errors from null references.

Key practices:

  1. Use the nullish coalescing operator (??) instead of OR (||) when 0 or empty string are valid values:
    // Good
    const reservedTokens = maxTokens ?? DEFAULT_TOKENS
    // Bad - will override 0 with default
    const reservedTokens = maxTokens || DEFAULT_TOKENS
    
  2. Add explicit type guards when checking object properties:
    // Good
    if (typeof data === "object" && data !== null && "property" in data) {
      return data.property
    }
    // Bad
    return data?.property || defaultValue
    
  3. Provide explicit fallbacks for optional values:
    // Good
    const description = mode.description ?? mode.whenToUse ?? mode.roleDefinition ?? ''
    // Bad
    const description = mode.description || mode.whenToUse || mode.roleDefinition
    

This approach prevents subtle bugs from implicit type coercion and makes null handling intentions clear in the code.


Maintain consistent naming patterns

Use consistent naming patterns throughout the codebase. When adding new identifiers, follow existing patterns in similar contexts. This includes:

  1. Consistent prefix/suffix patterns in related identifiers
  2. Consistent casing (camelCase, PascalCase, etc.)
  3. Consistent naming patterns for configuration keys and constants

Example of inconsistent naming:

// Inconsistent - mixing patterns
alwaysAllowReadOnly: true,
alwaysAllowWrite: true,
alwaysApproveResubmit: true,  // Should be alwaysAllowResubmit

// Inconsistent casing
const getLmStudioModels = ...
const getLMStudioModels = ...  // Inconsistent LM vs LM

// Inconsistent constant naming pattern
const SEARCH_MIN_SCORE = 0.4
const DEFAULT_MAX_SEARCH_RESULTS = 50  // Pattern mismatch

Corrected version:

// Consistent prefix pattern
alwaysAllowReadOnly: true,
alwaysAllowWrite: true,
alwaysAllowResubmit: true,  // Follows established pattern

// Consistent casing
const getLMStudioModels = ...  // Standardized on LM
const getLMStudioModels = ...

// Consistent constant naming pattern
const DEFAULT_SEARCH_MIN_SCORE = 0.4
const DEFAULT_MAX_SEARCH_RESULTS = 50  // Consistent pattern

When adding new identifiers:

  1. Look for similar existing identifiers and follow their pattern
  2. Maintain consistent casing for acronyms (e.g., API, LM, URL)
  3. Use consistent prefixes/suffixes for related configurations
  4. Follow established patterns for constants and configuration keys

Document non-obvious aspects

Documentation should explain what isn’t obvious from the code itself. Focus on providing context about “why” certain decisions were made rather than restating what the code does.

Key practices:

Good example:

// Number of terminal rows consumed by the textarea border (top + bottom).
const TEXTAREA_BORDER_LINES: u16 = 2;

Not as useful:

// Render the main paragraph
paragraph.render_ref(area, buf);

When writing tests, include docstrings that explain what behavior is being verified, especially when the test involves complex setup code. For public functions, ensure return values are documented when their meaning isn’t immediately clear from the function name or signature.


Sanitize user inputs

Always validate and sanitize user-provided inputs before using them in security-sensitive operations to prevent XSS attacks and unsafe redirections.

When handling URLs from user input:

When inserting content into the DOM:

Example (improved URL validation):

function loadUrl(url) {
  try {
    // Parse and validate URL
    const urlObj = new URL(url, window.location.origin);
    
    // Only allow http and https protocols
    if (urlObj.protocol !== 'http:' && urlObj.protocol !== 'https:') {
      console.error('Invalid URL protocol');
      return;
    }
    
    // Use the validated URL
    iframe.src = urlObj.toString();
  } catch (e) {
    console.error('Invalid URL format', e);
  }
}

This practice helps prevent client-side open redirect vulnerabilities and cross-site scripting (XSS) attacks that could compromise user security.


Contextualize, don’t swallow

Always propagate errors with appropriate context rather than silently ignoring them. This makes debugging easier and prevents unexpected behavior.

Do:

Don’t:

Example - Bad:

// Silently ignoring errors
parser.set_language(&lang).expect("load bash grammar");

// Ignoring I/O errors
async fn rollout_writer(...) {
    if let Some(meta) = meta {
        // I/O errors ignored here
    }
}

Example - Good:

// Adding context to errors
parser
    .set_language(&lang)
    .context("failed to load bash grammar")?;

// Properly handling utf8 conversion errors
let text = node
    .utf8_text(bytes)
    .map_err(|e| anyhow::anyhow!("failed to interpret heredoc body as UTF-8: {e}"))?;

// Properly propagating I/O errors
async fn rollout_writer(...) -> std::io::Result<()> {
    if let Some(meta) = meta {
        // Return I/O errors
    }
    Ok(())
}

Critical system dependencies failing should cause immediate failure rather than silent recovery. For common error patterns, consider creating utility functions that handle errors consistently.


AI terminology consistency

Maintain consistent terminology when describing AI systems, capabilities, and workflows throughout documentation and content. This includes using standardized terms for AI entities (consistently choosing between “AI”, “assistant”, “model”, or “agent”), technical processes, and capability descriptions.

Key areas to standardize:

Example of inconsistent terminology:

The AI can help with data analysis. The model explores data through execution. 
The assistant understands and builds upon existing state.

Example of consistent terminology:

The assistant can help with data analysis. The assistant explores data through execution.
The assistant understands and builds upon existing state.

This consistency helps readers better understand AI system capabilities and creates more professional, trustworthy documentation. It’s particularly important when describing AI workflows, limitations, and collaborative processes between humans and AI systems.


validate configuration values

Always verify configuration values against official documentation and test across target platforms before committing. Invalid configuration values can cause build failures, runtime errors, or platform-specific issues that are difficult to debug.

Key validation practices:

Example of problematic configuration:

// tsconfig.json - Invalid lib value
{
  "compilerOptions": {
    "lib": ["es2022", "esnext.disposable", "DOM"] //  "esnext.disposable" is not valid
  }
}

// Fixed version
{
  "compilerOptions": {
    "lib": ["es2022", "DOM"] //  Valid lib values only
  }
}

This prevents configuration-related build failures and ensures consistent behavior across development environments.


reuse existing code

Before implementing new functionality, check if similar utilities or patterns already exist in the codebase. Consolidate duplicate logic and leverage existing libraries to maintain consistency and reduce maintenance overhead.

Key practices:

Example:

// Instead of creating new utility
out := util.StripAnsi(fmt.Sprintf("%s", stdout))

// Reuse existing library
out := ansi.Strip(fmt.Sprintf("%s", stdout))

This approach improves code maintainability, reduces duplication, and ensures consistent patterns across the codebase.


Configure formatting tools consistently

Properly configure development tools to maintain consistent code formatting across the entire codebase and development environments. This includes setting up formatter ignore files, git attributes, and other configuration files that ensure uniform code style regardless of developer setup or platform differences.

Key areas to configure:

Example configuration:

# .prettierignore
evals/
docs/
out/

# .gitattributes  
* text=auto eol=lf

This approach prevents formatting inconsistencies that can cause unnecessary diff noise and ensures all team members work with the same code style standards, regardless of their local development environment.


Clean and consistent code

Maintain clean and consistent code by removing unnecessary elements and following standard practices:

  1. Remove commented-out code and unused imports - Don’t leave commented-out code in the codebase. If code is no longer needed, delete it entirely rather than commenting it out. Similarly, remove unused imports to reduce bundle size and avoid linting errors.
// Bad
import { computed, watch } from 'vue'; // watch is never used

// Good
import { computed } from 'vue';

// Bad
// const { getReportingURL } = useBugReporting();
// <LogoText v-if="showLogoText" :class="$style.logoText" />

// Good
// Import only what's needed, remove completely when no longer used
  1. Follow CSS best practices - Use standard CSS properties and valid values. Avoid non-standard attributes and properties that may not work across all browsers.
/* Bad */
.container {
  justify-content: right; /* Invalid value */
}
<style v-if="content.css" type="text/css" scoped> /* Non-standard usage */

/* Good */
.container {
  justify-content: flex-end; /* Standard value */
}
  1. Avoid dead code - Remove CSS selectors that don’t correspond to elements in your templates, and delete unused functions and variables.
/* Bad - selector with no matching elements */
.titleInput input {
  /* styles that will never be applied */
}
  1. Don’t disable lint rules inline - Instead of disabling lint rules with inline comments, fix the underlying issue or configure the rule project-wide if necessary.
// Bad
// eslint-disable-next-line @typescript-eslint/return-await
return await somePromise();

// Good
return somePromise(); // Fix the underlying issue instead

Following these practices improves code readability, reduces maintenance overhead, and prevents subtle bugs from entering your codebase.


AI model integration patterns

When integrating with AI models and LLMs, structure your code to properly handle model responses, separate concerns between layers, and implement robust failure detection mechanisms.

Core Principles:

  1. Separate raw model data from presentation logic: Core libraries should emit raw model responses (like finish reasons, confidence scores) while UI layers handle user-facing formatting and messages. This ensures library consumers aren’t forced to receive UI-specific content.

  2. Design schemas with proper field ordering: When using structured generation with AI models, place reasoning fields before conclusion fields in your schema. This encourages the model to think through the problem before providing final answers, improving response quality.

  3. Implement systematic failure detection: For long-running AI interactions, implement detection mechanisms for common failure modes like repetitive loops or unproductive states. Use dynamic check intervals based on confidence levels rather than fixed intervals.

  4. Handle streaming and incomplete responses safely: When processing streaming AI output, use permissive parsing that can handle incomplete or improperly formatted content, prioritizing safe rendering over strict specification compliance.

Example Implementation:

// Good: Core library emits raw finish reason
if (finishReason && finishReason !== FinishReason.STOP) {
  yield {
    type: GeminiEventType.Finished,
    value: finishReason  // Raw enum value
  };
}

// Good: UI layer handles user-facing messages
const finishReasonMessages: Record<string, string> = {
  'MAX_TOKENS': '⚠️ Response truncated due to token limits.',
  'SAFETY': '⚠️ Response stopped due to safety reasons.'
};

// Good: Schema with reasoning before conclusion
const schema = {
  type: Type.OBJECT,
  properties: {
    reasoning: {
      type: Type.STRING,
      description: 'Your reasoning process'
    },
    confidence: {
      type: Type.NUMBER,
      description: 'Confidence level 0.0-1.0'
    }
  }
};

This approach ensures maintainable, robust AI integrations that can handle the unpredictable nature of model responses while providing clean separation of concerns.


CI script reliability practices

Ensure CI/CD workflows maintain reliability by following these practices:

  1. Use explicit script paths - Always use explicit paths when invoking scripts (e.g., ./build.ps1 for PowerShell or ./build.sh for bash) rather than relying on implicit path resolution. This ensures the runner can locate and execute scripts regardless of the current working directory.

  2. Verify script existence - Confirm that all referenced script files and directories exist in the repository before merging workflow changes: ```yaml

    Before merging, verify that these paths exist:

    • name: Build packages (Windows) run: ./scripts/build-packages.ps1

    • name: Build packages (Unix) run: ./scripts/build-packages.sh ```

  3. Set execute permissions - Include a step to set execute permissions for shell scripts on Unix systems: ```yaml
    • name: Set permissions run: chmod +x ./build.sh

    • name: Build run: ./build.sh ```

  4. Handle secrets securely - Add conditional guards when using repository secrets to accommodate PRs from forks where secrets aren’t available: ```yaml
    • name: Run tests requiring API keys if: ${{ github.event_name != ‘pull_request’ || github.event.pull_request.head.repo.full_name == github.repository }} run: npm test env: API_KEY: ${{ secrets.API_KEY }} ```

These practices will prevent common CI/CD failures and improve workflow reliability across different environments and contributor scenarios.


Test behavioral differences

Tests should verify that different states, modes, or inputs produce meaningfully different behaviors, not just that code doesn’t crash. Focus on testing state transitions, edge cases, and behavioral changes rather than basic existence checks.

Use creative mocking strategies to make visual or complex behaviors testable. For UI components, mock styling functions to produce detectable output differences:

// Mock chalk.inverse to make highlighting testable
jest.mock('chalk', () => ({
  inverse: (text) => `[${text}]`
}));

// Test that different states produce different outputs
expect(focusedOutput).toContain('t[e]st'); // highlighted
expect(unfocusedOutput).toContain('test'); // not highlighted
expect(focusedOutput).not.toEqual(unfocusedOutput); // crucial difference check

Test comprehensive edge cases and scenarios:

Verify actual behavioral changes rather than just testing that functions were called. For example, test that undo actually restores previous text content, not just that buffer.undo() was invoked.


Maintain test state isolation

Ensure each test runs in isolation by properly managing test state, mocks, and timers. Clean up all test artifacts in beforeEach/afterEach hooks rather than within individual tests to prevent state leakage and test interdependence.

Example:

describe('MyComponent', () => {
  // ❌ Bad: Global mock without cleanup
  const globalMock = vi.spyOn(global, 'setTimeout');

  // ✅ Good: Proper setup and cleanup
  let timeoutSpy: SpyInstance;
  
  beforeEach(() => {
    timeoutSpy = vi.spyOn(global, 'setTimeout');
  });

  afterEach(() => {
    vi.restoreAllMocks();
    vi.useRealTimers();
  });

  it('should handle timeouts', () => {
    vi.useFakeTimers();
    // Test implementation
  });
});

Key practices:


Test actual functionality

Ensure tests verify real operations and integration scenarios rather than just basic concepts or type definitions. Many test suites contain placeholder tests that only check if functions exist or verify simple type structures, but fail to test the actual behavior and interactions that matter in production.

Tests should cover:

Example of inadequate testing:

it("should understand queue concepts", () => {
  type QueueItem = { id: string; callback: string; payload: unknown; };
  const testQueueItem: QueueItem = { id: "queue-123", callback: "processData", payload: { data: "test" } };
  expect(testQueueItem.id).toBeDefined(); // Only tests type structure
});

Example of proper functional testing:

it("should process queue items and handle retries", async () => {
  const agent = await getAgentByName(env.TEST_AGENT, "queue-test");
  
  // Test actual queue operations
  await agent.enqueue("processData", { data: "test" });
  const result = await agent.processQueue();
  
  expect(result.processed).toBe(1);
  expect(result.failed).toBe(0);
});

it("should sync state between multiple clients", async () => {
  const client1 = new AgentClient({ agent: "TestAgent", name: "client1" });
  const client2 = new AgentClient({ agent: "TestAgent", name: "client2" });
  
  const client2Updates = [];
  client2.onStateUpdate = (state) => client2Updates.push(state);
  
  client1.setState({ count: 5 });
  
  // Verify real multi-client synchronization
  expect(client2Updates).toContainEqual({ count: 5 });
});

This approach ensures tests provide meaningful coverage of how systems actually behave in production rather than just verifying that code compiles or basic structures exist.


Handle unsafe operations safely

Always wrap potentially unsafe operations (like JSON parsing, Buffer operations, or API calls) in try-catch blocks with appropriate error handling. Ensure error messages are user-friendly and actionable.

Example:

// Bad: Unsafe operation without error handling
const data = Buffer.from(input, "base64").toString("utf8");
const config = JSON.parse(toolCall.function.arguments);

// Good: Proper error handling with user-friendly messages
try {
  const data = Buffer.from(input, "base64").toString("utf8");
  return data;
} catch (error) {
  throw new Error("Invalid data format provided. Please check your input.");
}

try {
  const config = JSON.parse(toolCall.function.arguments);
  return config;
} catch (error) {
  throw new Error("Invalid configuration format. Please verify the syntax.");
}

Key points:

  1. Identify potentially unsafe operations in your code
  2. Always wrap them in try-catch blocks
  3. Handle errors gracefully with appropriate recovery or fallback logic
  4. Provide clear, user-friendly error messages that help users understand and resolve the issue
  5. Avoid exposing technical details in user-facing error messages unless necessary

Never swallow errors silently

Always handle errors explicitly and preserve their context. Never silently catch and discard errors as this hides bugs and makes debugging difficult. When re-throwing errors, include the original error as the cause to maintain the stack trace. In UI components, convert errors to user-friendly messages while logging technical details at appropriate levels.

Example of proper error handling:

// ❌ Bad - Silently swallowing error
try {
  await apiRequest();
} catch {
  // Error silently ignored
}

// ❌ Bad - Losing error context
try {
  await apiRequest(); 
} catch (error) {
  throw new Error('API request failed');
}

// ✅ Good - Preserving context and handling appropriately
try {
  await apiRequest();
} catch (error) {
  // Log technical details
  logger.error('API request failed', error);
  
  // In UI: Show user-friendly message
  toast.showError(
    new Error('Unable to complete request', { cause: error }),
    'Action failed'
  );
  
  // In services: Re-throw with context
  throw new OperationalError(
    'API request failed',
    { cause: error }
  );
}

Standardize LLM interface parameters

Maintain consistent parameter names and interface patterns across LLM implementations to improve maintainability and prevent integration issues. This includes:

  1. Use standard parameter names across all LLM integrations (e.g., ‘maxTokens’ instead of ‘maxTokensToSample’)
  2. Check for specific required capabilities rather than assuming implementation details
  3. Use consistent property access patterns for LLM responses

Example:

// INCORRECT
if (!llm.bindTools) {
  throw new LLMServiceError("LLM doesn't support binding tools");
}
const tokens = llmOutput?.tokenUsage?.completionTokens;

// CORRECT
if (typeof llm.withStructuredOutput !== 'function') {
  throw new LLMServiceError("LLM doesn't support structured output");
}
const tokens = llmResult?.llmOutput?.tokenUsage?.completionTokens;

This standardization:


Document why not what

Documentation should explain rationale and be technically precise. Focus on:

  1. Including all required parameters with correct names in examples and documentation
  2. Explaining the reasoning behind code decisions rather than just describing functionality
  3. Ensuring technical accuracy in all comments and documentation

Good example:

// editor.selectionHighlightBackground is used because it's always 
// partially transparent, which prevents obscuring the selection
// when repurposed here
this.decorationType = vscode.window.createTextEditorDecorationType({
  backgroundColor: new vscode.ThemeColor("editor.selectionHighlightBackground")
});

Bad example:

// Check if there is a trailing line
// This trims the selection if needed

Better example:

// If the user selected onto a trailing line but didn't actually include
// any characters in it, they don't want to include that line, so trim it off

For API documentation and examples, always verify that parameter names match the actual implementation and all required parameters are included with appropriate descriptions of their purpose.


Robust comparison algorithms

Ensure your comparison algorithms handle edge cases properly and avoid common pitfalls:

  1. Normalize values before comparison - When comparing strings, consider if you need to normalize whitespace, case, or other variants:
// Problematic: Direct comparison may fail due to trailing whitespace
if (lineA === lineB) { /* ... */ }

// Better: Normalize before comparing when appropriate
if (lineA.trimEnd() === lineB.trimEnd()) { /* ... */ }
  1. Avoid variable shadowing in comparisons - Be careful with variable names in loops and nested scopes:
// Problematic: 'model' shadows the outer parameter
for (const model of specificModels) {
  if (model.toLowerCase() === model) { // Always true!
    return true;
  }
}

// Better: Use distinct variable names
for (const specificModel of specificModels) {
  if (model.toLowerCase() === specificModel.toLowerCase()) {
    return true;
  }
}
  1. Check termination conditions carefully - Ensure loops don’t break prematurely:
// Problematic: Breaking loop on first non-match may skip valid items
for (let i = chatHistory.length - 1; i >= 0; i--) {
  if (item.message.role !== "assistant") {
    break; // Stops looking at earlier messages
  }
}

// Better: Continue searching when appropriate
for (let i = chatHistory.length - 1; i >= 0; i--) {
  if (item.message.role !== "assistant") {
    continue; // Skips this item but continues searching
  }
  // Process assistant messages
}
  1. Consider equality semantics - Think about what “equal” means in your context (identity, content, references?):
// Problematic: Strict equality might miss semantically equivalent items
if (i.id.providerTitle === item.id.providerTitle) {
  // Only checks exact IDs, might miss different references to same resource
}

// Better: Consider what equality means in this context
if ((i.id.providerTitle === item.id.providerTitle) ||
    (i.uri && item.uri && i.uri.value === item.uri.value)) {
  // Checks both ID equality and URI reference equality
}

prefer settings over environment

Prefer settings.json over environment variables and CLI flags for user configuration options. Environment variables should be reserved for system-level configuration or cases where the setting must be available before settings.json is loaded. CLI flags should be used for options that users frequently change between invocations.

Settings.json provides better user experience because:

Example of migrating an environment variable to settings:

// Before: checking environment variable directly
const maxDirs = parseInt(process.env.GEMINI_MEMORY_DISCOVERY_MAX_DIRS ?? '', 10) || 200;

// After: using settings.json
interface Settings {
  memoryDiscoveryMaxDirs?: number;
}

// In code:
const maxDirs = settings.memoryDiscoveryMaxDirs ?? 200;

Reserve CLI flags for options that users need to change frequently (like --model for testing different models) and environment variables for system-level configuration that must be available during early initialization.


Provide configuration fallbacks

Always provide sensible default or fallback values for configuration properties to prevent undefined states that can block users or cause application errors. Configuration properties should never be left in an undefined state that prevents normal application functionality.

When defining configuration properties, especially those that come from external sources (servers, user settings, migrations), include appropriate fallback values using logical OR operators or default parameter values.

Example of proper fallback implementation:

// Good: Provides fallback to prevent undefined state
const selectedProvider = 
    (currentMode === "plan" ? apiConfiguration?.planModeApiProvider : apiConfiguration?.actModeApiProvider) || "cline"

// Good: Default parameter with fallback URL
const CreditLimitError: React.FC<CreditLimitErrorProps> = ({
    buyCreditsUrl = "https://api.cline.bot/dashboard/account?tab=credits&redirect=true",
    // other props...
}) => {

// Good: Explicit default value to prevent UI flashing
const defaultState = {
    welcomeViewCompleted: false, // Default to show welcome unless overridden
    // other defaults...
}

This practice is especially critical for:

The fallback values should represent the most sensible default behavior for new users or error recovery scenarios.


Set evidence-based timeouts

Configure timeout values based on empirical testing and user experience requirements rather than arbitrary durations. Analyze actual system behavior to determine appropriate timeout thresholds that balance responsiveness with reliability.

For user-facing operations, implement progressive feedback mechanisms - start with shorter timeouts for warnings while allowing longer timeouts for actual failures. For example, warn users after 7 seconds but don’t abandon the operation until 15 seconds.

For system operations, test with realistic scenarios to determine optimal values. Shell integration consistently emits initial chunks within milliseconds, so a 500ms timeout is sufficient for detecting unresponsive processes.

// Good: Evidence-based timeout with progressive feedback
let checkpointsWarningTimer: NodeJS.Timeout | null = null
checkpointsWarningTimer = setTimeout(async () => {
    if (!checkpointsWarningShown) {
        checkpointsWarningShown = true
        this.taskState.checkpointTrackerErrorMessage = 
            "Checkpoints are taking longer than expected to initialize..."
        await this.postStateToWebview()
    }
}, 7_000) // Warn at 7s, but don't abandon until 15s

// Good: Tested timeout for system operations  
const timeoutMs = 500 // Verified: shell integration emits chunks within milliseconds
firstChunkTimeout = setTimeout(() => {
    // Handle timeout case
}, timeoutMs)

Always include timeout handling to prevent indefinite blocking and maintain application responsiveness, especially for network operations and external process interactions.


Handle null values safely

When handling potentially null or undefined values, implement explicit null checks and provide safe default values rather than allowing null values to propagate through the system. This prevents null reference errors and ensures predictable behavior.

Key practices:

Example from MultiselectInput validation:

@field_validator("value", mode="before")
@classmethod
def validate_value(cls, v: Any, _info):
    # Handle None safely during construction
    if v is None:
        return []
    
    if not isinstance(v, list):
        msg = f"MultiselectInput value must be a list. Got: {type(v)}"
        raise TypeError(msg)
    # ... rest of validation

This pattern ensures that null values are caught early and converted to safe, usable defaults, preventing downstream null reference issues while maintaining clear error messages for invalid non-null values.


Test security boundaries

Security mechanisms should be tested for both success and failure scenarios to ensure they properly enforce boundaries. Don’t just test that security features work when enabled - also verify they correctly block unauthorized access when disabled or misconfigured.

For CORS implementations, test that cross-origin requests fail without proper headers:

it("should reject cross-origin requests without CORS headers", async () => {
  const request = new Request("http://localhost/agents/TestAgent/test", {
    method: "POST",
    headers: {
      Origin: "https://malicious-site.com"
    }
  });

  const response = await routeAgentRequest(request, env, { cors: false });
  
  expect(response.status).toBe(403); // or appropriate error status
  expect(response.headers.get("Access-Control-Allow-Origin")).toBeNull();
});

For authentication flows, create comprehensive test suites that cover edge cases, error conditions, and security boundaries rather than just happy path scenarios. Complex security mechanisms like OAuth require dedicated test coverage to ensure all attack vectors are properly defended against.


organize environment configurations

Environment variables in CI/CD workflows should be organized consistently using structured env sections rather than inline declarations, and should account for platform-specific requirements. This improves maintainability, readability, and prevents environment-related failures across different operating systems.

Use the env field at the step or job level instead of inline variable assignments:

# Preferred approach
- name: Package and Publish Extension
  env:
    VSCE_PAT: ${{ secrets.VSCE_PAT }}
    OVSX_PAT: ${{ secrets.OVSX_PAT }}
    CLINE_ENVIRONMENT: production
  run: vsce package --out "cline-${{ steps.get_version.outputs.version }}.vsix"

# Instead of inline
run: CURRENT_ENVIRONMENT=production vsce package --out "file.vsix"

For cross-platform compatibility, explicitly set platform-specific environment variables when needed:

run: |
  # Default the encoding to UTF-8 - It's not the default on Windows
  PYTHONUTF8=1 PYTHONPATH=.github/scripts python -m coverage_check

This approach centralizes environment configuration, makes dependencies explicit, and prevents platform-specific failures in automated workflows.


Provider-agnostic API design

Design your API interfaces to be provider-agnostic rather than tightly coupled to specific service providers. This improves flexibility, maintainability, and makes future provider changes less disruptive.

Key practices:

  1. Use generic naming conventions for constants, functions, and types
  2. Centralize common API interaction code in core modules
  3. Use configuration objects to inject provider-specific details
  4. Create abstractions that can work with multiple providers

Example - Instead of:

const OPENAI_STREAM_IDLE_TIMEOUT_MS: u64 = 300_000;
const OPENAI_STREAM_MAX_RETRIES: u64 = 10;

// Direct provider-specific implementation
async fn generate_summary(transcript: &[TranscriptEntry], model: &str) -> Result<String> {
    // Provider-specific implementation
    let api_key = get_openai_api_key()?;
    let url = "https://api.openai.com/v1/chat/completions";
    // Rest of implementation...
}

Prefer:

const DEFAULT_STREAM_IDLE_TIMEOUT_MS: u64 = 300_000;
const DEFAULT_STREAM_MAX_RETRIES: u64 = 10;

// Provider-agnostic implementation using configuration
async fn generate_summary(
    transcript: &[TranscriptEntry],
    model: &str,
    config: &Config,
) -> Result<String> {
    // Use configuration for provider details
    let api_key = config.get_api_key()?;
    let base = config.model_provider.base_url.trim_end_matches('/');
    let url = format!("{}/chat/completions", base);
    // Rest of implementation...
}

This approach makes your codebase more resilient to changes in provider APIs and allows for easier testing and switching between different service providers.


Escape XML content securely

Always use proper XML entity escaping instead of CDATA blocks when embedding XML-like content within XML documents. CDATA sections can be vulnerable to XML injection attacks if the content isn’t properly validated or controlled.

For example, instead of:

<tool_use><![CDATA[
<update_todo_list>
<todos>
  [ ] First item
  [ ] Second item
</todos>
</update_todo_list>
]]></tool_use>

Use properly escaped XML entities:

<tool_use>
  &lt;update_todo_list&gt;
    &lt;todos&gt;
      [ ] First item
      [ ] Second item
    &lt;/todos&gt;
  &lt;/update_todo_list&gt;
</tool_use>

This practice prevents XML injection vulnerabilities that could allow attackers to manipulate XML processing, potentially leading to data exposure, unauthorized access, or other security breaches in systems that parse and process your XML documents.


Use structured logging

Always use the project’s structured logger instead of direct console methods (console.log, console.error, etc.). This ensures consistent log formatting, proper level-based filtering, and integration with monitoring systems.

Problems with direct console logging:

  1. Bypasses log level controls (making it impossible to silence debug logs in production)
  2. Creates inconsistent log formats that are harder to parse
  3. Misses enrichment with contextual metadata
  4. Bypasses centralized logging configuration

Good logging practice:

// AVOID: Direct console logging
console.log('Database pool created'); // Hard to filter out in production
console.error('Error handling streaming chunk:', error); // Bypasses error tracking

// BETTER: Use the structured logger with appropriate levels
this.logger.debug('Database pool created'); // Can be silenced in production
this.logger.info(`Generated workflow for prompt: ${flags.prompt}`); // Informational messages
this.logger.warn('The output file already exists. It will be overwritten.'); // Warnings
this.logger.error(`Error processing prompt "${flags.prompt}": ${errorMessage}`); // Actual errors

For debug-only logging, conditionally log based on environment or debug flags rather than leaving console statements that will always execute:

// BETTER: Conditional debug logging
if (isDebugMode) {
  this.logger.debug(`Connection parameters for ${nodeType}:`, warnings);
}

Ensure log levels match the message severity - use error only for actual failures, and info/debug for status messages to prevent false alarms in monitoring systems.


Extract into helper functions

Break down complex or deeply nested code into smaller, well-named helper functions to improve readability and maintainability. Extract code into helpers when:

  1. A function contains deeply nested logic
  2. Similar logic is repeated
  3. A function handles multiple concerns
  4. A block of code is complex enough to benefit from its own descriptive name

Example of improving complex nested code:

Before:

function processNextEditData(filePath, beforeContent, afterContent, cursorPosBeforeEdit, ...) {
  // Get the current context data
  const currentData = (global._editAggregator as any).latestContextData || {
    configHandler: data.configHandler,
    getDefsFromLspFunction: data.getDefsFromLspFunction,
    recentlyEditedRanges: [],
    recentlyVisitedRanges: [],
  };

  void processNextEditData(
    beforeAfterdiff.filePath,
    beforeAfterdiff.beforeContent,
    beforeAfterdiff.afterContent,
    cursorPosBeforeEdit,
    cursorPosAfterPrevEdit,
    this.ide,
    currentData.configHandler,
    currentData.getDefsFromLspFunction,
    currentData.recentlyEditedRanges,
    currentData.recentlyVisitedRanges,
    currentData.workspaceDir,
  );
}

After:

interface ProcessNextEditDataParams {
  filePath: string;
  beforeContent: string;
  afterContent: string;
  cursorPosBeforeEdit: Position;
  cursorPosAfterPrevEdit: Position;
  ide: IDE;
  configHandler: ConfigHandler;
  getDefsFromLspFunction: GetLspDefinitionsFunction;
  recentlyEditedRanges: RecentlyEditedRange[];
  recentlyVisitedRanges: AutocompleteCodeSnippet[];
  workspaceDir: string;
}

function getCurrentContextData(): ContextData {
  return (global._editAggregator as any).latestContextData || {
    configHandler: data.configHandler,
    getDefsFromLspFunction: data.getDefsFromLspFunction,
    recentlyEditedRanges: [],
    recentlyVisitedRanges: [],
  };
}

function processNextEditData(params: ProcessNextEditDataParams) {
  const currentData = getCurrentContextData();
  // Process using structured parameters...
}

---

## Sanitize all dynamic content

<!-- source: n8n-io/n8n | topic: Security | language: Other | updated: 2025-07-17 -->


Always sanitize dynamic content before rendering to prevent XSS and injection attacks. This includes HTML content, CSS styles, and executable scripts. Use appropriate sanitization methods based on content type:

1. For HTML content:
```javascript
// Bad
return props.content.html;

// Good
return DOMPurify.sanitize(props.content.html, {
  ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'span', 'div'],
  ALLOWED_ATTR: ['class']
});
  1. For template rendering: ```html

{{{message}}}

{{message}}


3. For CSS:
- Use strict whitelisting of allowed properties
- Validate against injection patterns
- Consider using CSS-in-JS solutions with built-in sanitization

4. For scripts:
- Avoid dynamic script execution (new Function(), eval())
- Use strict CSP headers
- Implement proper sandboxing for user-provided code

Never trust user input or third-party content. Always validate and sanitize before rendering.


---

## centralize configuration management

<!-- source: cline/cline | topic: Configurations | language: TypeScript | updated: 2025-07-17 -->

Consolidate related configuration settings into dedicated config objects or files rather than scattering hardcoded values throughout the codebase. Separate different types of configuration (API endpoints, timeouts, credentials) into distinct config sections to improve maintainability and avoid coupling.

Use environment variables for sensitive data like API keys and DSNs instead of hardcoding them. Organize configuration with clear separation of concerns - for example, having separate `mcpBaseUrl` and `apiBaseUrl` rather than reusing the same URL for different purposes.

Create centralized configuration objects for related constants:

```typescript
// Instead of scattered constants
const DEBUG_PORT = 9222
const TIMEOUT_MS = 4000
const DEFAULT_RETRIES = 3

// Use centralized config
const browserConfig = {
  debugPort: 9222,
  timeoutMs: 4000,
  defaultRetries: 3
}

// Separate API configurations
const apiConfig = {
  baseUrl: process.env.API_BASE_URL || "https://api.example.com",
  mcpBaseUrl: process.env.MCP_BASE_URL || "https://mcp.example.com"
}

Move shared configuration to dedicated config files in shared folders, and provide sensible defaults for all configuration values to ensure robust fallback behavior.


use semantic naming

Choose variable, function, and type names that clearly communicate their purpose and meaning without requiring additional context or comments. Names should be self-documenting and unambiguous to future developers.

Replace generic or unclear identifiers with descriptive alternatives:

For complex types, ensure the type structure is self-explanatory:

// Instead of unclear typing
private contextHistoryUpdates: Map<number, [number, Map<number, ContextUpdate[]>]>

// Use descriptive types
private contextHistoryUpdates: Map<number, [EditType, Map<number, ContextUpdate[]>]>

When names become long for clarity, prioritize understanding over brevity. A longer, clear name is preferable to a short, ambiguous one that requires documentation to understand.


document current functionality

Documentation should focus exclusively on current, active functionality rather than including historical context, deprecated features, or legacy modes. Remove sections that explain how things “used to work” or provide extensive support for outdated approaches that have minimal user adoption.

Avoid making unverified claims about external implementations or including speculative information. If historical context is truly necessary, move it to pull request comments or separate historical documentation rather than cluttering user-facing docs.

For example, instead of:

> **Note:** The Memory Import Processor has evolved to support both modern compatibility with CLAUDE.md and the original GEMINI.md modular import philosophy. This dual-mode approach reflects feedback from the community...

## Import Modes: CLAUDE.md Compatibility vs. Original GEMINI.md
| Feature | CLAUDE.md Compatibility Mode (Current Default) | Original GEMINI.md Mode (Legacy) |

Write:

# Memory Import Processor

The Memory Import Processor allows you to modularize your files by importing content from other markdown files using the `@file.md` syntax.

Similarly, replace generic template text with actual current information, and remove unnecessary elements like table of contents for short documents. Keep documentation concise and focused on what users need to know to use the current version effectively.


Use structured logging

Replace direct console.log, console.warn, and console.error calls with a centralized logging abstraction. This ensures logs are consistently formatted, properly categorized by severity, and can be filtered or disabled in production environments.

Benefits:

Implementation:

  1. Create or use an existing logging service/abstraction
  2. Use appropriate logging levels based on the message purpose:
    • logger.debug() - For development-only information
    • logger.info() - For normal operational messages
    • logger.warn() - For concerning but non-critical issues
    • logger.error() - For failures that require attention

Example:

Instead of:

console.log("[CodeIndexManager] Attempting to recover from error state before starting indexing.")
console.log("APi Protocol:", apiProtocol)
console.error(`Error parsing Ollama models response: ${JSON.stringify(parsedResponse.error, null, 2)}`)

Use a logger:

logger.info("[CodeIndexManager] Attempting to recover from error state before starting indexing.")
logger.debug("API Protocol:", apiProtocol)
logger.error("Error parsing Ollama models response:", { error: parsedResponse.error })

Semantic naming patterns

Use names that clearly convey purpose and maintain consistency across related components. Avoid generic identifiers (like dir) in favor of descriptive ones (like codex_home), and ensure placeholder names in string templates are self-explanatory (prefer SUMMARY_TEXT over {}). For related functions or elements, establish consistent naming patterns with meaningful symmetry, particularly for operations that are conceptually opposite.

When naming variables, functions, or constants:

  1. Choose semantically rich names that reveal intent
  2. Remove unnecessary prefixes for general-purpose elements (e.g., avoid openai_request_max_retries when it applies to all providers)
  3. Ensure naming symmetry between related functions (if you have fully_qualified_tool_name(), its counterpart should be parse_fully_qualified_tool_name())

Example:

// Poor naming
const TEMPLATE: &str = "Summary: {}";
fn get_name(s: &str, t: &str) -> String { /* ... */ }
fn extract(name: &str) -> (&str, &str) { /* ... */ }

// Better naming
const SUMMARY_TEMPLATE: &str = "Summary: {SUMMARY_TEXT}";
fn fully_qualified_tool_name(server: &str, tool: &str) -> String { /* ... */ }
fn parse_fully_qualified_tool_name(name: &str) -> (&str, &str) { /* ... */ }

Centralize proxy configuration

Avoid duplicate proxy configuration across your application by establishing a single point of proxy setup and leveraging built-in proxy support where available. Multiple proxy configurations can lead to conflicts, inconsistent behavior, and maintenance overhead.

Key principles:

  1. Use global configuration: Set up proxy handling once at the application entry point rather than in individual modules
  2. Leverage built-in support: Many libraries automatically read proxy settings from environment variables - avoid manual configuration when this exists
  3. Avoid hardcoded network resources: Use dynamic allocation for ports and endpoints to prevent conflicts when multiple instances run

Example from the discussions:

// ❌ Avoid: Multiple proxy configurations
export class MCPOAuthProvider {
  private static readonly REDIRECT_PORT = 7777; // Hardcoded port causes conflicts
}

// In another file
const client = new OAuth2Client({
  transporter: new Gaxios({ proxy: proxyUrl }) // Duplicate proxy setup
});

// ❌ Avoid: Redundant proxy setup
if (config.getProxy()) {
  // setGlobalDispatcher already called in core/client.ts
}

// ✅ Better: Centralized approach
// In core/client.ts - set once globally
setGlobalDispatcher(proxyAgent);

// OAuth2Client automatically reads from environment
const client = new OAuth2Client({
  // No manual transporter needed - uses env proxy settings
});

// Use dynamic port allocation
const server = http.createServer();
server.listen(0); // Let Node.js choose available port

This approach ensures consistent proxy behavior across all network requests while avoiding configuration conflicts and reducing maintenance burden.


Consistent output path specification

Configuration files defining operations that generate data outputs must always include a <save_to> element specifying the output location. Follow established patterns for similar operations, typically using predictable paths like .roo/temp/pr-[PR_NUMBER]/[operation]-output.{json|diff}. This ensures operation outputs are consistently stored and easily locatable by other processes.

Example:

<operation name="fetch_comments">
  <description>Get all comments on the PR</description>
  <command>gh pr view [PR_NUMBER] --repo [owner]/[repo] --json comments --jq '.comments'</command>
  <output_format>JSON array of comments</output_format>
  <save_to>.roo/temp/pr-[PR_NUMBER]/pr-comments.json</save_to>
</operation>

Prevent element double-counting

When working with graph structures, collections, or relationship mappings, ensure each element is processed exactly once to maintain algorithmic integrity. Implement proper tracking mechanisms to prevent duplicate counting or processing of elements, especially in scenarios involving:

  1. Bi-directional relationships where an element might be both source and target
  2. Self-referential connections or cycles
  3. Multiple traversal paths that converge
  4. Collection operations where uniqueness must be preserved

For example, instead of unconditionally adding items to collections:

// Problematic: Elements may be added multiple times
this.runOrder.push(runKey);

// Better: Check before adding to prevent duplicates
if (!this.runOrder.includes(runKey)) this.runOrder.push(runKey);

When counting connections in graphs, track which connections have been counted:

// Problematic: May count self-loops twice
function countNodeConnections(nodeId, connections) {
  let count = 0;
  
  // Count outgoing connections
  if (connections[nodeId]) {
    // Count outgoing logic...
    count += outgoingCount;
  }
  
  // Count incoming connections (may include duplicates with self-loops)
  for (const [sourceNodeId, nodeConnections] of Object.entries(connections)) {
    // Count incoming logic that doesn't account for sourceNodeId === nodeId
    count += incomingCount;
  }
  
  return count;
}

// Better: Use a Set to track unique connections
function countNodeConnections(nodeId, connections) {
  const countedConnections = new Set();
  let count = 0;
  
  // Add logic to track unique connection IDs to prevent double-counting
  // Only increment count for connections not already in the Set
  
  return count;
}

This approach prevents algorithmic errors that affect calculations, state management, and the correctness of graph operations.


Avoid hardcoded configurations

Never hardcode environment-specific values or feature states directly in your code. Instead, use environment variables, configuration files, or feature flag systems to manage these values dynamically.

For environment URLs:

// BAD
window.location.replace('https://stage.ciaraai.com/workflows');

// GOOD
window.location.replace(process.env.VUE_APP_PLATFORM_URL + '/workflows');

For feature flags and UI components:

// BAD
<N8nBadge class="ml-4xs">{{ i18n.baseText('generic.upgrade') }}</N8nBadge>

// GOOD
<N8nBadge v-if="!settingsStore.isEnterpriseFeatureEnabled[EnterpriseEditionFeature.EnforceMFA]" class="ml-4xs">
  {{ i18n.baseText('generic.upgrade') }}
</N8nBadge>

Hardcoded configurations are difficult to maintain, lead to environment-specific bugs, and can result in misleading UI elements for users. Always retrieve configuration values from the appropriate source at runtime to ensure your application behaves correctly across all environments and user scenarios.


Optimize Vue watchers

When implementing watchers in Vue applications, ensure they are configured appropriately for the data structures they observe. Two common pitfalls to avoid:

  1. Use deep: true for complex data structures: When watching arrays or objects that might be modified in-place (push, pop, property updates), enable deep watching to detect these changes:
watch(
  () => props.messages,
  async (messages) => {
    // Handler logic
  },
  { immediate: true, deep: true } // Enable deep watching for arrays/objects
)

Without deep watching, the watcher will only trigger when the reference changes, not when items are added or properties modified.

  1. Watch specific properties instead of whole objects: For better performance and stability, watch the specific primitive property you care about rather than the entire object:
// Less optimal - watches entire object reference
watch(
  () => selected,
  // Handler logic
)

// More optimal - watches just the ID property
watch(
  () => selected?.id,
  // Handler logic
)

This prevents unnecessary watcher triggers when unrelated properties change and makes your reactivity system more predictable and efficient.


Avoid hardcoded credentials

Never hardcode sensitive information such as passwords, API keys, or authentication tokens in source code, configuration files, or container definitions. These can be exposed through version control systems, shared repositories, or compromised container images.

Instead:

  1. Use environment variables or secure runtime configuration
  2. Implement a secrets management solution
  3. For Docker specifically, utilize build arguments that aren’t persisted in the final image

Example - Instead of:

FROM n8nio/n8n

ENV N8N_BASIC_AUTH_ACTIVE=true
ENV N8N_BASIC_AUTH_USER=Tre
ENV N8N_BASIC_AUTH_PASSWORD=Npt9854$

Better approach:

FROM n8nio/n8n

ENV N8N_BASIC_AUTH_ACTIVE=true
# Credentials will be provided at runtime
# docker run -e N8N_BASIC_AUTH_USER=username -e N8N_BASIC_AUTH_PASSWORD=password n8n-image

For build-time configuration, use ARG instead of ENV for sensitive values that shouldn’t persist in the image.


Secure input validation

Always validate and sanitize user inputs, especially when constructing commands or file paths. Use established security libraries instead of implementing custom parsing logic, and implement proper validation that prevents attacks while avoiding false positives.

Key practices:

Example of secure command parsing:

// Instead of unsafe split
const parts = command.split(/\s+/); // Unsafe - doesn't handle quotes

// Use secure parsing
const parts = splitCommandSafely(command);
if (!parts) {
  return 'Command parsing failed: unmatched quotes';
}

// Validate path traversal
const rootDir = path.resolve(this.config.getTargetDir());
const resolvedDir = path.resolve(rootDir, params.directory);
if (!resolvedDir.startsWith(rootDir + path.sep) && resolvedDir !== rootDir) {
  return 'Directory traversal is not allowed. Path must be within the project root.';
}

This approach prevents injection attacks, handles edge cases properly, and maintains functionality while ensuring security.


Enforce API format consistency

Maintain consistent data formats, parameter units, and interface patterns across API implementations. This includes:

  1. Consistent type mappings and format handling
  2. Standardized parameter units and descriptions
  3. Uniform message format processing

Example of problematic inconsistencies:

// Inconsistent MIME type mapping
const mimeTypes: Record<string, string> = {
    ".png": "image/png",
    ".jpg": "image/jpeg",
    // Missing MIME type for supported format
    // .avif is in SUPPORTED_IMAGE_FORMATS but not mapped here
}

// Inconsistent parameter unit description
openAiApiTimeout: z.number().optional().describe("Timeout in milliseconds"),
// But actually handled as minutes in implementation:
const timeoutMs = (options.timeout ?? 10) * 60 * 1000

// Inconsistent message format handling
// Don't convert structured data to plain text when the API supports JSON
const args = [
    "-p",
    JSON.stringify(messages),  // Correct: Preserve message structure
    "--system-prompt",
    systemPrompt
]

To maintain consistency:

  1. Document and implement complete type mappings for all supported formats
  2. Use consistent units across parameter definitions and implementations
  3. Preserve data structures when APIs support them natively
  4. Document format requirements and conversions in interface definitions

Enforce resource usage limits

Implement explicit resource limits and monitoring to prevent performance degradation and memory issues. This includes:

  1. Define maximum sizes for buffers and caches
  2. Implement early size checking
  3. Reuse buffers for large operations
  4. Add monitoring/warnings when approaching limits

Example implementation:

class ResourceAwareProcessor {
  private static readonly MAX_BUFFER_SIZE = 1024 * 1024; // 1MB
  private static readonly MAX_CACHE_ENTRIES = 1000;
  private buffer: Buffer | null = null;

  async processData(data: string): Promise<void> {
    // Early size check
    if (Buffer.byteLength(data) > this.MAX_BUFFER_SIZE) {
      throw new Error(`Data exceeds maximum size of ${this.MAX_BUFFER_SIZE} bytes`);
    }

    // Reuse buffer if possible
    if (!this.buffer) {
      this.buffer = Buffer.alloc(this.MAX_BUFFER_SIZE);
    }

    // Process with size awareness
    try {
      // ... processing logic
    } catch (error) {
      console.warn(`Processing warning: ${error.message}`);
    }
  }

  clearBuffer(): void {
    this.buffer = null;
  }
}

This approach:


Validate before data access

Always validate data existence and type before accessing properties or methods to prevent runtime errors from null/undefined values. This includes:

  1. Array bounds checking before indexing
  2. Object property existence verification
  3. Type validation before method calls
  4. Use of optional chaining and nullish coalescing operators

Example of unsafe code:

function toolCallStateToSystemToolCall(state: ToolCallState): string {
  return state.toolCall.function.name;  // Unsafe - multiple potential null points
}

Safe version:

function toolCallStateToSystemToolCall(state: ToolCallState): string {
  if (!state?.toolCall?.function) {
    throw new Error("Invalid tool call state");
  }
  return state.toolCall.function.name ?? "unknown";
}

Key practices:

This prevents the most common causes of runtime errors and improves code reliability.


Prevent async deadlocks

Avoid circular dependencies in asynchronous code paths that can lead to deadlocks or indefinite blocking. When using async/await, ensure that promise chains have clear resolution paths and aren’t dependent on their own completion. Be particularly careful with initialization patterns and refresh mechanisms.

Example of problematic code:

// PROBLEMATIC: Creates a deadlock
public async getSessions(): Promise<AuthSession[]> {
  await this.initialRefreshAttempt; // Waits for refresh to complete
  // ...
}

private async refreshSessions(): Promise<void> {
  const sessions = await this.getSessions(); // Calls getSessions which waits for refreshSessions
  // ...
}

constructor() {
  this.initialRefreshAttempt = this.refreshSessions();
}

Example of fixed code:

// FIXED: Avoids deadlock by breaking circular dependency
public async getSessions(): Promise<AuthSession[]> {
  // Don't await initialRefreshAttempt here
  // ...
}

private async refreshSessions(): Promise<void> {
  const sessions = await this.getSessions();
  // ...
}

constructor() {
  this.initialRefreshAttempt = this.refreshSessions();
}

Additionally:

  1. Always provide ways to cancel async operations (e.g., expose AbortController) to prevent resource leaks
  2. Be careful with race conditions when checking state that might change during async operations
  3. Analyze promise chains during code review to identify potential circular dependencies
  4. Use centralized managers for coordinating related async operations when appropriate

Working configuration examples

Configuration examples should be complete, accurate, and ready to use without modification. This applies to both code snippets and configuration file examples.

For code examples that use configuration:

For configuration file examples:

Example of good practice:

# Complete example with imports
import os

# Configure Bearer authorization
configuration = openapi_client.Configuration(
    access_token = os.environ["BEARER_TOKEN"]
)

Example of good configuration documentation:

{
  "name": "commit",
  "description": "Generate a commit message for staged changes",
  "params": { "includeUnstaged": true }
}

With explanation: “If includeUnstaged is set to true, then unstaged changes are also included in the prompt, otherwise only staged changes are included.”


Consistent identifier naming

Follow consistent naming conventions for all identifiers to improve code quality, accessibility, and test reliability. Ensure correct spelling and adhere to established project patterns.

Key practices:

  1. Use precise spelling in HTML attributes and test IDs
    // ❌ Incorrect
    <label for="avalableInMCP">
    data-test-id="workflow-settings-vailable-in-mcp"
       
    // ✅ Correct
    <label for="availableInMCP">
    data-test-id="workflow-settings-available-in-mcp"
    
  2. Establish and follow consistent casing conventions:
    • For Vue events: decide between camelCase (thumbsUp) or kebab-case (thumbs-up) and use consistently
    • For component props: follow project conventions for complex types
  3. Use IDE tools and linters to enforce naming standards
    • Consider disabling overly restrictive rules team-wide rather than repeatedly suppressing them
    • Document naming conventions in your style guide for team alignment

This approach helps prevent broken references between HTML elements, ensures tests target the correct elements, and makes code more maintainable by following predictable patterns.


Memoize expensive calculations

Cache computation results in React components to prevent unnecessary recalculations during re-renders, which can significantly impact application performance. Apply these optimization techniques in three key areas:

  1. Redux selectors: Ensure selectors return stable references or use memoization libraries like reselect: ```tsx // Suboptimal approach const currentToolCall = useAppSelector(selectCurrentToolCall);

// Optimized approach import { createSelector } from ‘reselect’; const memoizedSelector = createSelector( [selectCurrentToolCall], (toolCall) => toolCall ); const currentToolCall = useAppSelector(memoizedSelector);


2. **Expensive calculations**: Move computations with O(n) or higher complexity outside render loops and cache them:
```tsx
// Suboptimal approach - O(n²) complexity
{history.map(item => {
  const latestSummaryIndex = findLatestSummaryIndex(history);
  // rest of render logic
})}

// Optimized approach - O(n) complexity
const latestSummaryIndex = useMemo(() => 
  findLatestSummaryIndex(history), 
  [history]
);
{history.map(item => {
  // use latestSummaryIndex
  // rest of render logic
})}
  1. Frequently called functions: Extract calculations into custom hooks or memoize them to prevent recalculation on every render: ```tsx // Suboptimal approach

<div style={{ fontSize: getFontSize() }}>

// Optimized approach const fontSize = useFontSize(); <div style={{ fontSize }}>


When implementing these optimizations, focus on functions that perform expensive calculations or create new object references, especially those called frequently during renders or within loops.


---

## Tests must assert

<!-- source: continuedev/continue | topic: Testing | language: Python | updated: 2025-07-16 -->

Test methods should contain active, uncommented code that includes at least one assertion to verify expected behavior. Commented-out test code provides zero value and creates a false sense of security by appearing to test functionality while actually testing nothing.

Instead of:
```python
def testGetResponse(self):
    # inst = self.make_instance(include_optional=False)
    # self.assertEqual(inst.message, "Expected message")

Write:

def testGetResponse(self):
    inst = self.make_instance(include_optional=False)
    self.assertIsNotNone(inst)
    self.assertEqual(inst.message, "Expected message")

Every test method should verify specific functionality by executing the code under test and validating results through appropriate assertions. Tests without assertions or with only commented code will always pass regardless of code correctness, defeating the purpose of having tests.


Centralize configuration constants

Always centralize configuration constants in a shared location and import them rather than duplicating values across the codebase. This prevents drift between frontend and backend configurations, reduces errors from manual updates, and makes configuration changes easier to manage.

For example, instead of:

// In UI component
<input
  type="range"
  min="0"
  max="1" 
  step="0.05"
  value={codebaseIndexConfig.codebaseIndexSearchMinScore || 0.4}
/>

// In another file
const defaultMinScore = 0.4;

Do this:

// In shared constants file
export const SEARCH_MIN_SCORE = 0.4;

// In UI component
import { SEARCH_MIN_SCORE } from "@/constants/config";

<input
  type="range"
  min="0"
  max="1"
  step="0.05"
  value={codebaseIndexConfig.codebaseIndexSearchMinScore || SEARCH_MIN_SCORE}
/>

This approach also applies to default values derived from dynamic sources, where you should establish a clear fallback chain:

const displayValue = value ?? modelInfo?.maxTokens ?? DEFAULT_MAX_TOKENS

When centralizing configuration constants:

  1. Create dedicated files for related configuration constants
  2. Use descriptive names that indicate purpose and context
  3. Document expected value ranges or formats when needed
  4. Consider using TypeScript const assertions for added type safety

Explicit environment configuration handling

Environment and configuration values should be explicit, visible, and environment-aware. Avoid hardcoded production values, hidden configuration properties, and complex environment variable logic. Instead:

  1. Use clear environment variable defaults: ```typescript // Bad export const skipAuth = process.env.SKIP_AUTH !== ‘false’;

// Good export const skipAuth = process.env.SKIP_AUTH === ‘true’ || false;


2. Make configuration properties visible and customizable:
```typescript
// Bad
class Config {
  @Env('DB_NAME')
  database: string = 'production_db';  // Hardcoded production value
}

// Good
class Config {
  @Env('DB_NAME')
  database: string = 'local_db';  // Development-friendly default

  @Env('API_URL')
  apiUrl: string = 'http://localhost:3000';  // Visible and configurable
}
  1. Ensure paths resolve in all environments: ```typescript // Bad const DIST_DIR = join(__dirname, ‘..’, ‘..’, ‘..’, ‘packages/frontend/dist’);

// Good const DIST_DIR = process.env.DIST_DIR || join(__dirname, ‘dist’);


This approach improves maintainability, prevents production issues, and makes configuration more transparent for developers and operators.

---

## Pin actions securely

<!-- source: n8n-io/n8n | topic: CI/CD | language: Yaml | updated: 2025-07-15 -->


Always pin GitHub Actions to specific commit hashes rather than version tags to prevent supply chain attacks and ensure build reproducibility. This practice ensures that your workflow remains stable and secure even if the action's version tag is compromised or modified.

For example, use:
```yaml
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0

Additionally:

  1. Use appropriate authentication tokens with minimal required permissions for external operations. Default GITHUB_TOKEN lacks permissions for cross-repository operations, so use dedicated tokens for these scenarios: ```yaml
    • name: Generate GitHub App Token id: generate_token uses: actions/create-github-app-token@v2 with: app-id: ${{ secrets.APP_ID }} private-key: ${{ secrets.PRIVATE_KEY }}
  1. Leverage reusable actions for common workflows to ensure consistency and reduce maintenance overhead:
    - name: Setup Environment and Build Project
      uses: ./.github/actions/setup-and-build
      with:
     node-version: 20.x
     enable-caching: true
    

Validate model capabilities first

Always validate AI model capabilities and configurations before attempting to use them. This includes checking:

  1. Feature support (e.g., images, embeddings)
  2. Model-specific parameters (e.g., dimensions, context windows)
  3. Model availability and correct configuration

Example:

// Before using model features, validate capabilities
const provider = await client.providerRef.deref();
const modelCapabilities = {
  supportsImages: provider?.apiHandler?.getModel()?.info?.supportsImages ?? false,
  supportedDimensions: [768, 1536, 3072],
  isModelAvailable: Boolean(routerModels[provider]?.[modelId])
};

// Use capabilities to make decisions
const imagesToInclude = modelCapabilities.supportsImages ? allImages : [];
if (!modelCapabilities.isModelAvailable) {
  throw new Error(`Model ${modelId} is not available`);
}

This prevents runtime errors, improves reliability, and ensures optimal resource usage. It’s particularly important in AI applications where different models may have varying capabilities and requirements.


Minimize database roundtrips

Avoid making multiple database queries when a single query can retrieve the required data. Each database roundtrip adds latency and increases system load. Before making a database call, check if the data is already available or if multiple queries can be combined into one.

Common patterns to avoid:

Example of inefficient pattern:

// Inefficient: Two separate queries for the same job
const job = await supabaseGetJobByIdOnlyData(req.params.jobId);
if (!job || job.team_id !== req.auth.team_id) {
  return res.status(403).json({ success: false, error: "Access denied" });
}

const jobData = await supabaseGetJobsById([req.params.jobId]);

Better approach:

// Efficient: Single query with proper error handling
const jobData = await supabaseGetJobsById([req.params.jobId]);
if (!jobData || jobData.length === 0 || jobData[0].team_id !== req.auth.team_id) {
  return res.status(403).json({ success: false, error: "Access denied or not found" });
}

When pagination is necessary due to database limits, ensure it’s truly required and document the reasoning clearly.


Restrict database access

Never allow unrestricted public access (0.0.0.0/0) to database instances. Restrict database network access to only specific trusted IP ranges or VPC networks that require it, following the principle of least privilege. This prevents potential unauthorized access and data breaches.

Example of problematic configuration:

postgres_authorized_networks = [
  {
    name  = "all"
    value = "0.0.0.0/0"
  }
]

Example of improved configuration:

postgres_authorized_networks = [
  {
    name  = "internal-network"
    value = "10.0.0.0/8"
  },
  {
    name  = "office-network"
    value = "203.0.113.0/24"
  }
]

Organize documentation content

Structure documentation to prevent information overload and improve readability by using appropriate organizational elements and callouts judiciously.

Key principles:

  1. Break up complex information: When a single section contains multiple concepts or choices, use tabs, collapsible details, or separate sections to organize the content logically.

  2. Use callouts appropriately: Reserve “important” admonitions for truly critical information. Use “tip” for helpful but non-essential information, and regular text for general explanations.

  3. Avoid empty headings: Don’t have empty space between headings. Each heading should immediately be followed by content or subheadings.

  4. Group related content: When documenting multiple related items (like components from the same provider), group them together under a common section.

  5. Minimize visual clutter: Wrap lengthy code outputs or JSON responses in collapsible <details> sections when only specific parts are relevant to the reader.

Example of good organization:

## Configure MCP servers

### Install the server locally

1. Install the weather server:
   ```bash
   uv pip install mcp_weather_server
  1. Configure the server connection:
Configure using JSON format... Configure using STDIO format...

:::tip Environment variables Langflow passes environment variables from the .env file to MCP, but not global variables declared in the UI. :::


This approach separates installation from configuration, uses tabs for different options, and reserves the tip callout for helpful supplementary information rather than critical instructions.

---

## AI response variability

<!-- source: langflow-ai/langflow | topic: AI | language: Markdown | updated: 2025-07-14 -->

When documenting AI model interactions, account for the non-deterministic nature of AI responses and avoid assumptions about specific outputs. AI models can produce different responses to identical inputs, and model behavior changes over time through updates and improvements.

Write documentation that remains accurate regardless of response variations:

```markdown
# Instead of assuming specific responses:
The LLM response is vague, though the Agent does know the current date.

# Use generic descriptions that account for variability:
This query demonstrates how an LLM, by itself, might not have access to 
information or functions designed to address specialized queries. In this 
example, the default OpenAI model provides a vague response, although the 
agent does know the current date by using its internal `get_current_date` function.

Avoid describing models with performance or cost specifics that may become outdated. Instead of “this model is a good balance of performance and cost,” use “this model is a balanced model” or reference the provider’s current recommendations.

Include disclaimers when showing example AI responses: “The following is an example of a response returned from this tutorial’s flow. Due to the nature of LLMs and variations in your inputs, your response might be different.”

This approach ensures documentation remains useful as AI models evolve and helps users understand the inherent variability in AI systems.


minimize performance overhead

Reduce unnecessary overhead in performance-related code by creating reusable patterns and avoiding verbose implementations. This applies to both production performance monitoring and development workflows like testing.

For performance measurement, avoid repetitive timing logic by creating wrapper functions that encapsulate the boilerplate:

// Instead of repeated start/end timing:
const authStart = performance.now();
await config.refreshAuth(settings.merged.selectedAuthType);
const authEnd = performance.now();
const authDuration = authEnd - authStart;

// Use a reusable wrapper:
trackStartupPerformance(async () => {
  await config.refreshAuth(settings.merged.selectedAuthType);
}, 'authentication');

In tests, minimize execution time by avoiding unnecessary delays. Use minimal wait times when async operations require synchronization:

// Avoid: await wait(100); // Slows down test suite
// Prefer: await wait(1); // Minimal delay when needed

This approach reduces both runtime overhead in production code and development-time overhead in test execution, improving overall system efficiency and developer productivity.


Write comprehensive test assertions

Instead of making multiple small assertions that check individual fields or conditions, write single comprehensive assertions that verify the complete expected state. This approach makes tests more maintainable, provides better documentation of expected behavior, and makes test failures more informative.

Example - Instead of:

assert_eq!(tools[0]["type"], "function");
assert_eq!(tools[0]["name"], "shell");
assert!(tools.iter().any(|t| t.get("name") == Some(&name.clone().into())));

Prefer:

assert_eq!(tools, vec![
    json!({
        "type": "function",
        "name": "shell"
    }),
    json!({
        "type": "function", 
        "name": name
    })
]);

This practice:

When dealing with complex objects that don’t implement PartialEq, consider implementing it to enable comprehensive assertions rather than checking fields individually.


Configuration consistency check

Ensure that configuration files and settings are consistent with their intended functionality and maintain portability across different environments.

Key aspects to verify:

  1. Avoid hardcoded paths - Use relative paths, environment variables, or configuration variables instead of absolute paths
  2. Align permissions with functionality - Make sure that permissions or access groups in configurations match the tools and capabilities referenced in descriptions
  3. Properly configure special files - Use appropriate attributes and settings for files that require special handling

Example of improving path configuration:

// Problematic - hardcoded absolute path
const templatePath = 'C:\\Users\\orphe\\Downloads\\playwright-mcp.yaml';

// Better - relative path using Node.js path module
const templatePath = path.join(__dirname, 'playwright-mcp.yaml');

Example of aligning permissions with functionality:

# Problematic - empty groups but roleDefinition mentions using tools
roleDefinition: |-
  You can use the `new_task` tool...
groups: []

# Better - groups include all necessary permissions
roleDefinition: |-
  You can use the `new_task` tool...
groups:
  - read
  - edit
  - command
  - new_task

Semantically consistent naming

Names should accurately reflect their purpose and be used consistently throughout the codebase. This applies to props, function names, variables, and UI labels.

  1. Maintain prop naming consistency: When components share similar functionality, ensure prop names are consistent. If a component expects a specific prop structure, all implementations should use the same naming pattern.
// Inconsistent - avoid this:
<EditFile changes={args.diff ?? ""} />
<EditFile changes={args.changes ?? ""} />

// Consistent - do this:
<EditFile changes={args.changes ?? ""} />
<EditFile changes={args.changes ?? ""} />
  1. Match UI labels to actions: Ensure that button labels and UI text accurately reflect the actions they perform.
// Misleading - avoid this:
<span onClick={() => void dispatch(cancelStream())}>Pause</span>

// Clear and accurate - do this:
<span onClick={() => void dispatch(cancelStream())}>Cancel</span>
  1. Use semantically clear prop names: Choose prop names that clearly reflect their purpose. Avoid using event handler prefixes (‘on-‘) for props that aren’t event handlers.
// Unclear semantics - avoid this:
<Switch onWarningText="This is a warning" />

// Clear semantics - do this:
<Switch warningText="This is a warning" />
  1. When renaming variables or props: Ensure all references are updated throughout the codebase to maintain consistency and prevent runtime errors.

Following these guidelines helps prevent bugs, improves code readability, and makes the codebase more maintainable.


Prevent broken interactions

Ensure UI elements’ visual state (e.g., disabled, active) always matches their actual behavior. When an element appears disabled, completely prevent the associated actions by:

  1. Blocking event handlers for disabled elements
  2. Maintaining appropriate disabled states for features that would lead to broken experiences
  3. Ensuring all user interaction methods (mouse, keyboard, programmatic) respect these constraints

This prevents users from encountering unexpected errors or broken states.

Example fix:

// Before: UI looks disabled but handler still works
<div 
  className={`${disabled ? "cursor-not-allowed" : "cursor-pointer"}`}
  onClick={(e) => {
    dispatch(toggleToolSetting(props.tool.function.name));
    e.stopPropagation();
  }}
>

// After: Handler respects disabled state
<div 
  className={`${disabled ? "cursor-not-allowed" : "cursor-pointer"}`}
  onClick={(e) => {
    if (!disabled) {
      dispatch(toggleToolSetting(props.tool.function.name));
      e.stopPropagation();
    }
  }}
>

Similarly, when providing keyboard shortcuts or handlers (like Escape to close dialogs), ensure the handlers are accessible in all relevant contexts to prevent broken interaction patterns.


prevent unnecessary operations

Identify and eliminate redundant computations, network requests, and re-renders in React components to improve performance. Common patterns include memoizing functions that recreate on every render, debouncing user input to reduce API calls, and conditionally triggering side effects only when necessary.

Use useCallback for functions passed as props or used in dependency arrays:

const renderSegment = useCallback((segment: DisplaySegment): JSX.Element => {
  // render logic
}, [dependencies])

Implement debouncing for user input to prevent excessive state updates:

const [localValue, setLocalValue] = useDebouncedInput(initialValue, onChange)

Separate side effects to trigger only when specific conditions change:

// Instead of combining multiple concerns in one useEffect
useEffect(() => {
  if (isVisible) {
    vscode.postMessage({ type: "fetchLatestMcpServersFromHub" })
  }
}, [isVisible]) // Only fetch when visibility changes, not on dimension changes

Before implementing expensive operations, ask: “Is this computation/request/re-render actually necessary?” and “Can I reduce the frequency or scope of this operation?”


Sanitize untrusted content

Always sanitize user-generated or externally sourced content before rendering it to prevent Cross-Site Scripting (XSS) vulnerabilities. Never use dangerouslySetInnerHTML with unsanitized content.

When handling user input or external data:

  1. Use a trusted HTML sanitization library (such as DOMPurify)
  2. Validate and sanitize URLs before rendering images or links
  3. Consider alternative rendering methods that don’t require raw HTML injection

Bad practice:

// Dangerous - susceptible to XSS attacks
const renderTableCell = (content: string) => {
  return <div dangerouslySetInnerHTML={{ __html: content }} />;
};

Good practice:

import DOMPurify from 'dompurify';

// Safe - content is sanitized before rendering
const renderTableCell = (content: string) => {
  if (needsHtmlRendering(content)) {
    const sanitizedContent = DOMPurify.sanitize(content);
    return <div dangerouslySetInnerHTML={{ __html: sanitizedContent }} />;
  }
  return <span>{content}</span>;
};

// For image URLs
const renderImage = (imageUrl: string) => {
  const sanitizedUrl = sanitizeImageUrl(imageUrl);
  // Skip rendering if URL is invalid/unsafe
  if (!sanitizedUrl) {
    return null;
  }
  return <img src={sanitizedUrl} alt="User content" />;
};

Logging levels hierarchy

Use appropriate logging levels to prevent debug noise from leaking into production environments. Reserve console.log() for important application events, and use console.debug() for development information that should not be visible to end users.

Example:

// Avoid: Debug information using console.log
console.log("Required fields values:", required);

// Better: Use console.debug for development information
console.debug("Required fields values:", required);

// Best: Remove debug logs before production deployment or implement
// a logging framework that controls log visibility by environment

This practice reduces noise in production logs, making important messages more visible while still allowing developers to include helpful debugging information during development.


Accessible security controls

Security controls and interactive elements must be accessible to all users to prevent unequal security access. When non-standard elements (like divs) are used for interaction, they must include proper accessibility attributes to ensure users with disabilities can access security features.

For any clickable element:

  1. Add role=”button” for screen reader identification
  2. Include tabIndex=”0” for keyboard focus
  3. Implement keyboard event handlers (onKeyDown) for activation via keyboard

Code example (fixing the accessibility issue):

return (
  <div
    role="button"
    tabIndex={0}
    onClick={handleClick}
    onKeyDown={(e) => {
      if (e.key === 'Enter' || e.key === ' ') {
        handleClick();
      }
    }}
    className={`flex cursor-pointer items-center gap-1 ${className}`}
    onMouseEnter={() => setIsHovered(true)}
    onMouseLeave={() => setIsHovered(false)}
  >
    {renderIcon()}
    {children}
  </div>
);

This prevents security vulnerabilities for users who rely on assistive technologies by ensuring they have equal access to security-related controls and features.


Actions configuration best practices

When working with GitHub Actions workflows, follow these configuration best practices:

  1. Boolean inputs comparison: GitHub Actions boolean inputs are actually strings. Always use string comparison with quotes:
# ❌ Incorrect - may never evaluate as expected
if: ${{ inputs.enable-docker-cache == true }}

# ✅ Correct - properly compares string values
if: ${{ inputs.enable-docker-cache == 'true' }}
  1. Version pinning: Always pin external GitHub Actions to specific commit SHAs rather than using major version tags:
# ❌ Insecure - may pull unexpected updates
uses: actions/checkout@v4

# ✅ Secure - pins to specific commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
  1. Input naming consistency: Maintain consistent input naming across workflow triggers. Ensure variables referenced in workflows match the input names defined in workflow_call and workflow_dispatch events to avoid undefined values.

  2. Dynamic identifiers: Include both run ID and attempt ID in dynamically generated values like branch names to ensure uniqueness across workflow reruns:

# ✅ Better uniqueness for branches created in workflows
branch: 'chore/openapi-sync-${{ github.run_id }}-${{ github.run_attempt }}'

These practices improve security, reliability, and maintainability of workflow configurations.


Document configurations completely

Ensure configuration documentation is comprehensive, clear and actionable for developers. This includes:

  1. Document all possible configuration options and behaviors, not just defaults:
    # Good example: Explicitly documenting all behaviors
    - alwaysApply: true    # Always include the rule, regardless of file context
    - alwaysApply: false   # Only include if globs exist AND match file context
    - alwaysApply: undefined # Default: include if no globs exist OR globs exist and match
    
  2. Clearly document configuration storage locations with platform-specific paths:
    Configuration is stored in ~/.continue directory (or %USERPROFILE%\.continue on Windows)
    
  3. Use consistent, platform-appropriate formats for configuration examples. When showing multiple formats (YAML/JSON), use the appropriate tab components for your documentation system:
<Tab title="YAML">
  // YAML configuration example
</Tab>
<Tab title="JSON">
  // JSON configuration example  
</Tab>

Proper configuration documentation reduces developer confusion, prevents misconfigurations, and simplifies troubleshooting.


Keep dependencies current

Always use the latest stable versions of dependencies in configuration files like Cargo.toml, and avoid deprecated or unmaintained packages. Outdated dependencies can introduce security vulnerabilities, compatibility issues, and technical debt.

When reviewing dependency changes:

Example of problematic dependency management:

# Outdated - current version is 0.30
opentelemetry = "0.27"

# Deprecated package
serde_yaml = "0.9"

# Outdated - current version is 0.30  
jsonschema = "0.18"

Make dependency version reviews a standard part of configuration file changes to maintain a healthy and secure codebase.


secure authentication flows

Authentication flows should be designed to provide a seamless user experience while maintaining security standards. Avoid implementing temporary workarounds that require users to perform multiple steps, quit and restart applications, or follow complex sequences to authenticate successfully.

When designing OAuth or other authentication mechanisms, especially in CLI or no-browser environments, ensure the flow can be completed in a single session without requiring application restarts or complex user interactions. Poor authentication UX often leads to user frustration and may encourage insecure workarounds.

Example of what to avoid:

if (
  settings.merged.selectedAuthType === AuthType.LOGIN_WITH_GOOGLE &&
  config.getNoBrowser()
) {
  // This requires users to: select auth type, quit, restart app
  await getOauthClient(settings.merged.selectedAuthType, config);
}

Instead, design authentication flows that can handle the complete process in one session, with clear user guidance and fallback options that don’t compromise security or require application restarts.


Consistent localization formatting

Ensure all localization strings maintain consistent formatting patterns within each locale file. This includes:

  1. Terminal punctuation: All similar messages should consistently end with appropriate punctuation marks for the locale (periods in English/French, “।” in Hindi, etc.).

  2. Locale-specific punctuation: Use the correct width/style of punctuation marks for each language (e.g., full-width colons “:” in Chinese and Japanese, not ASCII colons “:”).

  3. Variable interpolation syntax: Maintain consistent variable placeholder syntax. Use double curly braces for all variables: {{variableName}} not {variableName}.

Example (incorrect):

{
  "errors": {
    "invalidApiKey": "Invalid API key. Please check your API key configuration.",
    "apiKeyRequired": "An API key is required for this embedder",
    "vectorDimensionMismatch": "Failed to update vector index. Details: {errorMessage}"
  }
}

Example (correct):

{
  "errors": {
    "invalidApiKey": "Invalid API key. Please check your API key configuration.",
    "apiKeyRequired": "An API key is required for this embedder.",
    "vectorDimensionMismatch": "Failed to update vector index. Details: {{errorMessage}}"
  }
}

Consistent formatting makes localization files more maintainable and ensures a uniform appearance throughout the application.


Preserve error context chain

When catching and re-throwing errors, always preserve the original error context using the cause option of the Error constructor. This maintains the complete error chain for debugging and ensures no critical information is lost when translating errors between layers.

Instead of:

try {
  await deletePoints(filePaths)
} catch (error) {
  throw new Error(`Failed to delete points: ${error.message}`)
}

Use:

try {
  await deletePoints(filePaths)
} catch (error) {
  throw new Error(
    `Failed to delete points: ${error instanceof Error ? error.message : String(error)}`,
    { cause: error }
  )
}

This practice:

When handling errors across system boundaries (e.g., API calls, file operations), this becomes especially important as it helps track down issues through multiple abstraction layers.


Descriptive parameter names

Use specific, descriptive parameter names for API resources rather than generic identifiers. Parameter names should clearly indicate the resource type they refer to by using namespaced identifiers (e.g., userId instead of id). This improves API readability, reduces ambiguity in code, and prevents confusion when multiple resource types are used in the same context.

When designing API endpoints:

For example, instead of:

# In users parameter schema
name: id

Use:

# In users parameter schema
name: userId

This practice is especially important in OpenAPI specifications where parameter names directly impact client implementations. Changing parameter names after an API is published can break clients and require comprehensive updates across endpoint definitions, routes, controllers, and documentation.


Prevent async race conditions

Identify and prevent race conditions in asynchronous operations, especially when operations depend on each other’s completion state. Race conditions occur when the timing or order of async operations affects program correctness, often leading to intermittent failures that are difficult to debug.

Common scenarios include:

Instead of using arbitrary timeouts, use proper synchronization mechanisms like condition waiting, promises, or explicit state checking.

Example from the codebase:

// Problem: Race condition - command returns before UI is ready
await vscode.commands.executeCommand("cline.focusChatInput")
// This executes too early, before focus is actually set
visibleWebview?.controller.fixWithCline(...)

// Better: Use proper waiting mechanism
await vscode.commands.executeCommand("cline.focusChatInput")
await pWaitFor(() => webviewIsFocused()) // Wait for actual condition
visibleWebview?.controller.fixWithCline(...)

Always consider: What assumptions am I making about timing? Could this operation execute before its dependencies are ready? What happens if this code runs concurrently with itself?


Complete dependency arrays

Always include all referenced variables in React hook dependency arrays (useEffect, useCallback, useMemo). Missing or incorrect dependencies can lead to stale closures, unexpected behavior, and difficult-to-diagnose bugs.

When using hooks with dependency arrays:

// ❌ Incorrect: Missing dependency
const handleSubmit = useCallback(() => {
  if (currentState.isValid) {
    submitData(formData);
  }
}, [formData]); // currentState is missing

// ✅ Correct: Complete dependency array
const handleSubmit = useCallback(() => {
  if (currentState.isValid) {
    submitData(formData);
  }
}, [formData, currentState]);

// ✅ Correct: useEffect with event listener cleanup
useEffect(() => {
  // Only add the listener if condition is met
  if (toolCallState?.status === "generated") {
    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }
}, [toolCallState, handleKeyDown]);

Consider using the ESLint plugin ‘eslint-plugin-react-hooks’ with the exhaustive-deps rule to automatically detect missing dependencies.


Avoid duplicated code

Identify and extract shared functionality between classes into reusable components. Code duplication increases maintenance burden and risk of inconsistent behavior when changes are needed.

Use these approaches to eliminate duplication:

  1. Create abstract base classes for related services
  2. Extract common functionality into utility methods
  3. Encapsulate data structures with their utility methods in dedicated classes

Example of problematic duplication:

// In NextEditService
fun triggerNextEdit() {
    // Almost identical code to triggerCompletion() in AutocompleteService
    // with minor differences
}

// In AutocompleteService  
fun triggerCompletion() {
    // Almost identical code to triggerNextEdit() in NextEditService
    // with minor differences
}

Better approach:

// In a shared abstract base class or utility class
abstract class EditServiceBase {
    protected fun triggerEdit(editType: String, parameters: Map<String, Any>) {
        // Common implementation
    }
}

// In concrete implementations
class NextEditService : EditServiceBase() {
    fun triggerNextEdit() {
        triggerEdit("nextEdit", specificParameters)
    }
}

class AutocompleteService : EditServiceBase() {
    fun triggerCompletion() {
        triggerEdit("completion", specificParameters)
    }
}

For data types with associated utilities, follow the pattern demonstrated in RangeInFileWithContents where data and its manipulation methods are encapsulated together.


Configuration documentation clarity

Ensure configuration documentation clearly distinguishes between deployment contexts and uses consistent terminology throughout. When documenting configuration procedures, explicitly specify the target deployment type (Langflow Desktop vs OSS) and platform (macOS vs Windows) to avoid user confusion.

Key requirements:

Example of improved configuration documentation:

## Set environment variables for Langflow Desktop

### macOS
Langflow Desktop for macOS cannot automatically use variables set in your terminal, such as those in `.zshrc` or `.bash_profile`, when launched from the macOS GUI.

To make environment variables available to GUI apps on macOS, you need to use `launchctl` with a `plist` file:

1. Create the `LaunchAgents` directory if it doesn't exist:
```bash
mkdir -p ~/Library/LaunchAgents

Windows

Langflow Desktop for Windows cannot automatically use variables set in your terminal, such as those defined with set in cmd or $env:VAR=... in PowerShell, when launched from the Windows GUI.

To make environment variables available to the Langflow Desktop app, you must set them at the user or system level using the System Properties interface or the Terminal.


This approach prevents user confusion about which instructions apply to their specific setup and ensures consistent experience across different deployment scenarios.

---

## Maintain configuration consistency

<!-- source: browser-use/browser-use | topic: Configurations | language: Other | updated: 2025-07-09 -->

When modifying configuration settings, especially environment variables, ensure changes are consistent with existing codebase usage patterns and maintain backward compatibility. Before changing configuration names or values, audit the codebase to understand current usage and dependencies.

For environment variables, check how they are referenced throughout the application, including tests, documentation, and third-party integrations. Consider that different libraries may expect different variable names for the same functionality.

Example from Azure OpenAI configuration:
```python
# Check existing usage before changing variable names
return AzureChatOpenAI(
    model='gpt-4o',
    api_version='2024-10-21',
    azure_endpoint=os.getenv('AZURE_OPENAI_ENDPOINT', ''),
    api_key=SecretStr(os.getenv('AZURE_OPENAI_KEY', '')),  # Keep existing name
)

For related configuration values, ensure they are compatible with each other. For instance, when setting viewport and window sizes, account for UI chrome and ensure viewport dimensions don’t exceed window dimensions to prevent content cutoff.


API authentication requirements

Ensure all API documentation and code examples include proper authentication headers and clearly explain authentication requirements. As of Langflow v1.5, all API requests require a Langflow API key, even when AUTO_LOGIN is enabled. The only exceptions are MCP endpoints (/v1/mcp, /v1/mcp-projects, /v2/mcp) which don’t require authentication regardless of the AUTO_LOGIN setting.

All curl examples, code snippets, and API documentation should include the x-api-key header:

curl -X POST \
  "http://localhost:7860/api/v1/run/FLOW_ID" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $LANGFLOW_API_KEY" \
  -d '{"input_value": "Hello"}'

When documenting API endpoints, explicitly state authentication requirements and provide guidance on obtaining API keys. Update any legacy examples that assume no authentication is needed, and ensure consistency across all API-related documentation. This prevents user confusion and ensures examples work out of the box with current Langflow versions.


Consistent semantic naming

Use clear, consistent, and semantic naming patterns across your codebase to improve readability and maintainability:

  1. Start function names with verbs that describe the action being performed: ```typescript // Good createProviderDefinedToolFactory() parseJson()

// Avoid providerDefinedToolFactory() jsonParser()


2. **Use descriptive names for generics** rather than single letters:
```typescript
// Good
interface Provider<LANGUAGE extends string, CONTEXT extends string>

// Avoid
interface Provider<L extends string, C extends string>
  1. Follow consistent case conventions:
    • Use camelCase for object properties and variables
    • Start non-class/type variables (including schemas) with lowercase
    • Use consistent naming across similar APIs
  2. Include units in variable names to prevent ambiguity: ```typescript // Good durationInSeconds: number maxParallelRequests: number

// Avoid duration: number concurrency: number


5. **Use standard terminology** in field names (e.g., `mediaType` for IANA media types)

6. **Ensure test naming matches implementation** to avoid confusion and maintenance issues

Following these conventions makes your code more self-documenting, easier to understand, and reduces the cognitive load for developers reading and maintaining the code.

---

## Type-safe null handling

<!-- source: vercel/ai | topic: Null Handling | language: TypeScript | updated: 2025-07-08 -->

Use TypeScript's type system and modern JavaScript features to prevent null reference errors. 

**TypeScript type safety:**
- Prefer `never` over `undefined` for properties that shouldn't have values
- Use `unknown` instead of `any` when working with data of uncertain structure
- Validate data with zod schemas instead of using type assertions (`as`)
- Use proper type narrowing with type guards

**Modern JavaScript null checks:**
- Use nullish coalescing (`??`) for default values:
```typescript
// Instead of this:
const citations = response.message.citations ? response.message.citations : [];

// Do this:
const citations = response.message.citations ?? [];

// Do this: const contentType = requestClone.headers.get(‘content-type’); if (contentType?.startsWith(‘multipart/form-data’)) { // }


Following these patterns leads to more robust, self-documenting code and fewer runtime errors from unexpected null/undefined values.

---

## Verify AI model capabilities

<!-- source: vercel/ai | topic: AI | language: Other | updated: 2025-07-08 -->

Always verify and accurately document AI model capabilities, supported formats, and limitations before implementation. Use consistent terminology (e.g., "multi-modal" instead of "multimodal") and validate model features against official documentation sources. When documenting AI functionalities:

1. Be explicit about supported features and limitations
2. Link to official documentation when describing specific capabilities
3. Don't assume cross-functionality unless confirmed
4. Use clear, concise language when describing input formats and parameters

Example:
```typescript
// GOOD: Accurate, verified documentation with specific capabilities
// Groq's multi-modal models like `meta-llama/llama-4-scout-17b-16e-instruct` 
// support image inputs via URLs or base64-encoded data
// Source: https://groq.com/docs/models/llama-4-scout

// BAD: Unverified or inaccurate information
// OpenAI's o4 model is available (incorrect - only o4-mini is publicly available)
// Assuming a model supports certain parameter formats without verification

Maintaining accurate documentation saves development time, prevents integration errors, and helps teams properly utilize AI capabilities within their applications.


Maintain semantic naming consistency

Names should be semantically meaningful and consistent across related concepts in the codebase. This applies to variables, functions, components, and types. When naming:

  1. Use consistent suffixes/prefixes for related concepts
  2. Choose descriptive verbs for functions
  3. Avoid abbreviations unless widely understood
  4. Maintain naming patterns across similar features

Example of poor naming consistency:

// Inconsistent naming pattern
interface User {
  customer_id: string;  // Uses _id suffix
  group: string;        // Missing _id suffix
}

function enableStreaminOption() {}  // Misspelled, unclear verb

Improved version:

// Consistent naming pattern
interface User {
  customerId: string;   // Consistent camelCase
  groupId: string;      // Consistent naming pattern
}

function createStreamingOption() {}  // Clear verb, correct spelling

This helps maintain code readability and reduces cognitive load when working across different parts of the codebase.


Consistent camelCase naming

Use camelCase consistently for all property names, method names, and configuration options, even when interacting with external APIs that use different conventions (like snake_case). This maintains codebase consistency and makes interfaces more predictable for developers.

When encountering inconsistencies:

// INCORRECT: Using external snake_case convention in internal code
const options = {
  file_format: 'mp3',
  timestamp_granularities: ['word']
};

// CORRECT: Maintaining camelCase in internal code
const options = {
  fileFormat: 'mp3',
  timestampGranularities: ['word']
};

// When sending to external API, transform as needed
sendToExternalApi({
  file_format: options.fileFormat,
  timestamp_granularities: options.timestampGranularities
});

This approach creates a clear separation between internal naming conventions and external API requirements, leading to more consistent and maintainable code.


Format for rendering compatibility

Documentation should be formatted appropriately for its intended rendering context and ensure discoverability. Consider how documentation files will be displayed in different environments (GitHub, websites, etc.) and choose appropriate file formats and structures.

Key practices:

Example:

<!-- Good practice: Using appropriate extension and avoiding formatting that breaks rendering -->
# Contributing Guide

## Overview
Brief introduction to contribution process

## Detailed Guides
For more information, see:
- [How to create a codemod](./contributing/how-to-create-a-codemod.md)
- [Package structure](./contributing/packages.md)

## Changelog Format
When creating a changeset, avoid using headings at the beginning of the message:

feat(embedding-model-v2): add providerOptions

By considering the rendering context, you ensure documentation remains accessible and displays correctly across different platforms.


Choose hooks wisely

Use React hooks only when you need reactivity and component re-rendering. For accessing instantaneous values or one-time data retrieval, prefer plain functions to avoid unnecessary re-renders and improve performance.

When you only need current state values without subscribing to changes, use direct selector calls instead of hooks:

// ❌ Avoid - causes unnecessary re-renders for instantaneous values
export const useMainInterfaceAnalytics = (): MainInterfaceAnalyticsData => {
  const session = useSessionStore(sessionSelectors.currentSession);
  // ... other hook calls
}

// ✅ Prefer - direct access for one-time values
export const getMainInterfaceAnalytics = (): MainInterfaceAnalyticsData => {
  const session = sessionSelectors.currentSession(getSessionStoreState());
  // ... direct selector calls
}

Consider component lifecycle when deciding state placement. If components unmount and remount frequently, evaluate whether state should persist in a global store or reset with component lifecycle.


Externalize hardcoded configurations

Configuration values should be externalized to environment variables rather than hardcoded in the source code. This improves flexibility, security, and deployment across different environments.

Hardcoded configuration values make applications inflexible and difficult to deploy across different environments. Instead, use environment variables with sensible defaults.

Example of the improvement:

# Bad: Hardcoded configuration
self.client = openai.OpenAI(
    api_key="ollama",
    base_url="http://localhost:11434"
)

# Good: Environment-configurable
self.client = openai.OpenAI(
    api_key=os.getenv("OLLAMA_API_KEY", "ollama"),
    base_url=os.getenv("OLLAMA_HOST", "http://localhost:11434")
)

This approach allows the same code to work in development, testing, and production environments by simply changing environment variables, without requiring code modifications or rebuilds.


Follow established naming conventions

Adhere to established naming conventions consistently throughout the codebase, prioritizing official documentation standards when available. Use appropriate case conventions (ALL_CAPS for constants, descriptive names for variables) and maintain consistency with external API standards.

When naming conflicts arise between internal consistency and official documentation, prefer the official documentation approach. For constants, use ALL_CAPS to clearly indicate their global scope and immutable nature.

Examples:

# Good: Constant with proper naming
MODEL_PARAMETERS = ModelParameters(...)

# Good: API key following official documentation
API_KEY = os.getenv("GEMINI_API_KEY")  # Following Google's official docs

# Avoid: Inconsistent constant naming
model_parameters = ModelParameters(...)

# Avoid: Internal naming that conflicts with official docs
API_KEY = os.getenv("GOOGLE_API_KEY")  # When official docs specify GEMINI_API_KEY

This approach enhances code readability, reduces confusion for new team members, and ensures compatibility with external documentation and examples.


Robust error handling

Implement comprehensive error handling to prevent crashes and aid debugging. This includes:

  1. Use try/catch blocks for risky operations - Especially when parsing JSON or using browser APIs that might throw exceptions:
// Before
const data = JSON.parse(message.text || "{}");

// After
let data;
try {
  data = JSON.parse(message.text || "{}");
} catch (error) {
  console.error("Failed to parse message data:", error);
  data = {}; // Provide fallback value
}
  1. Enhance React error boundaries - Capture and log detailed error context:
class ErrorBoundary extends Component<ErrorProps, ErrorState> {
  constructor(props: ErrorProps) {
    super(props);
    this.state = {};
  }

  static getDerivedStateFromError(error: unknown) {
    return {
      error: error instanceof Error ? (error.stack ?? error.message) : `${error}`,
    };
  }
  
  // Add this method to capture additional context
  componentDidCatch(error: Error, info: React.ErrorInfo) {
    // Log to monitoring system with context
    logErrorToService({
      error,
      componentStack: info.componentStack,
      timestamp: new Date().toISOString(),
      additionalContext: this.props.contextData
    });
  }
  
  render() {
    if (this.state.error) {
      return <ErrorDisplay error={this.state.error} />;
    }
    return this.props.children;
  }
}
  1. Include helpful context - When handling errors, capture relevant details like timestamps, component stacks, or state information to make debugging easier.

This approach ensures your application degrades gracefully when errors occur while providing the information needed to fix underlying issues.


Simplify algorithmic approaches

When implementing functionality, evaluate whether simpler algorithmic approaches or more appropriate data structures can achieve the same result with less complexity. Look for opportunities to eliminate unnecessary conditional branching, use built-in operations for common tasks, and leverage established patterns like regex for pattern matching.

Common simplifications include:

Before implementing complex logic, ask: “Is there a simpler way to achieve this using standard algorithms, data structures, or library functions?” This approach typically results in more maintainable, readable, and efficient code.


Thread safety first

When implementing features that may run concurrently, always ensure thread safety using appropriate synchronization mechanisms:

  1. Use thread-safe context variables for isolating execution contexts:
    # Good: Using contextvars-based solutions for thread isolation
    ctx = baggage.set_baggage(...)  # Uses contextvars internally for thread safety
    
  2. Protect shared mutable state with locks:
    # Good: Adding locks to prevent race conditions
    _lock: Lock = threading.Lock()
       
    def singleton_method(self):
        with self._lock:
            # Access or modify shared state safely
    
  3. Implement thread-based timeouts efficiently:
    # Better: Simple thread-based timeout pattern
    thread = threading.Thread(target=target, daemon=True)
    thread.start()
    thread.join(timeout=timeout)
       
    if thread.is_alive():
        # Handle timeout case
    

These patterns help prevent hard-to-debug race conditions, ensure consistent behavior in concurrent environments, and make code more maintainable by clearly indicating thread safety considerations.


Consistent formatting standards

Maintain consistent formatting and syntax across all documentation and code examples to improve readability and functionality. Follow established style guides and ensure uniformity in presentation.

For documentation formatting, use consistent patterns for optional steps and procedures. For example, format optional steps as “Optional:” rather than “(Optional)” following Google’s style guide:

3. Optional: Install pre-commit hooks to help keep your changes clean and well-formatted.

For code examples, standardize quote usage throughout all examples. Use double quotes for headers and variables that need expansion:

curl -X POST \
  "http://localhost:7860/api/v1/webhook/YOUR_FLOW_ID" \
  -H "Content-Type: application/json" \
  -H "x-api-key: $LANGFLOW_API_KEY" \

This ensures both visual consistency and functional correctness, as single quotes prevent variable expansion while double quotes allow it.


Validate environment bindings

Always validate that environment bindings exist and are of the expected type before using them, and ensure external dependencies are properly configured in build scripts. Runtime binding validation prevents cryptic errors when bindings are missing or misconfigured, while proper build configuration prevents dynamic import issues in serverless environments.

For runtime validation, check both existence and type:

const bindingValue = env[binding as keyof typeof env] as unknown;

// Ensure we have a binding of some sort
if (bindingValue == null || typeof bindingValue !== "object") {
  console.error(
    `Could not find binding for ${binding}. Did you update your wrangler configuration?`
  );
  return new Response("Invalid binding", { status: 500 });
}

// Ensure that the binding is to a DurableObject
if (bindingValue.toString() !== "[object DurableObjectNamespace]") {
  return new Response("Invalid binding", { status: 500 });
}

For build configuration, include external packages in your build scripts and use top-level imports instead of dynamic imports:

// In build.ts - add external packages
external: ["cloudflare:email", "other-external-packages"]

// In code - use top-level imports
import { createMimeMessage } from "mimetext";
import { EmailMessage } from "cloudflare:email";

Configuration documentation completeness

Configuration documentation should include all necessary constraints and limitations while avoiding redundant information that’s already documented elsewhere. Always document critical constraints that could cause runtime issues, such as resource conflicts or usage limitations. Remove duplicate explanations that repeat information available in other parts of the documentation to maintain clarity and reduce verbosity.

Example of good constraint documentation:

# Create browser config with user_data_dir
config = BrowserConfig(
    headless=False,
    user_data_dir="/path/to/your/user_data_dir"
)

The browser will use this directory to store all profile data, which will persist between browser sessions. Only one browser at a time can be running with this user_data_dir, make sure to close any browsers using it before starting browser-use.

Avoid duplicating parameter explanations that are already covered in function signatures or other documentation sections.


Use async/await pattern

Prefer async/await syntax over promise chains or callback patterns when working with asynchronous operations. This improves code readability, makes error handling more straightforward, and maintains consistency across the codebase.

Example (converting from promise chain to async/await):

// Instead of this:
ideMessenger
  .request("controlPlane/getFreeTrialStatus", undefined)
  .then(response => {
    // handle response
  })
  .catch(error => {
    // handle error
  });

// Prefer this:
async function getFreeTrialStatus() {
  try {
    const response = await ideMessenger.request("controlPlane/getFreeTrialStatus", undefined);
    // handle response
  } catch (error) {
    // handle error
  }
}

This pattern not only enhances readability but also helps avoid the “callback hell” that can occur with chained promises in complex asynchronous operations. Code written with async/await tends to follow a more natural top-to-bottom execution flow that’s easier to reason about when dealing with concurrent operations.


Use fake sample data

Always use completely fictional personal information in sample files, documentation, test data, and code examples to prevent privacy violations and unintentional exposure of real people’s data. Real names, email addresses, phone numbers, and social media profiles should never appear in sample data as they can link to actual individuals and create privacy risks.

Example of what to avoid:

Emily J. Wilson
Email: emilyjwilson@example.com
Phone: 555-789-0123
LinkedIn: linkedin.com/in/emilyjwilson

Instead, use clearly fictional data:

Jane Doe
Email: jane.doe@example.com
Phone: 555-000-0000
LinkedIn: linkedin.com/in/janedoe-sample

This practice protects individual privacy and prevents potential legal or ethical issues that could arise from using real personal information without consent.


Use cryptographic randomness

Always use cryptographically secure random number generation for security-sensitive operations such as generating session IDs, authentication tokens, or unique identifiers. Standard random number generators like Math.random() are designed for statistical randomness, not security, making them vulnerable to prediction and exploitation by attackers.

// Insecure - using Math.random() for session IDs:
const sessionId = `roo-${Date.now()}-${Math.random().toString(36).substring(7)}`;

// Secure - using cryptographic randomness:
import crypto from 'crypto';
// In Node.js:
const sessionId = `roo-${Date.now()}-${crypto.randomBytes(16).toString('hex')}`;
// OR
const sessionId = `roo-${Date.now()}-${crypto.randomUUID()}`;

For browser environments, use the Web Crypto API:

// Browser environment:
const array = new Uint8Array(16);
window.crypto.getRandomValues(array);
const sessionId = `roo-${Date.now()}-${Array.from(array).map(b => b.toString(16).padStart(2, '0')).join('')}`;

Predictable randomness can lead to session hijacking, token guessing, and other security vulnerabilities that may compromise user data or system integrity.


Clean code formatting rules

Maintain consistent and clean code formatting to improve readability and maintainability. Follow these guidelines:

  1. Use correct syntax for utility classes:
    // ❌ Bad
    className="gap 1.5 flex-row"
    className={`${toolsSupported ? "md:flex" : "int:flex"} hover:underline"`}
       
    // ✅ Good
    className="gap-1.5 flex-row"
    className={`hover:underline ${toolsSupported ? "md:flex" : ""}`}
    
  2. Keep class strings organized and manageable:
    • Extract complex conditional classes into variables
    • Use template literals for dynamic classes
    • Maintain consistent ordering (layout → spacing → visual)
  3. Avoid inline comments in expressions:
    // ❌ Bad
    ) : item.message.role === "tool" ? null : item.message.role === // comment here
       
    // ✅ Good
    // Comment above the expression
    ) : item.message.role === "tool" ? null : item.message.role === "assistant"
    
  4. Use appropriate import paths:
    • Import from main module exports rather than internal files
    • Maintain proper encapsulation of implementation details
    • Keep imports organized and grouped by type

These rules help maintain code consistency, improve readability, and make the codebase easier to maintain and refactor.


Provide actionable examples

Documentation should include concrete, executable code examples rather than vague instructions. Make your examples copy-paste ready with all necessary context and dependencies. When documenting features or APIs, show exactly how they should be used in practice.

For example, instead of just stating:

// Don't do this
// You can pass provider options as an argument

Provide a complete, executable example:

// Do this
const result = await embed({
  model: cohere.embedding('embed-english-v3.0'),
  input: 'Hello world',
  providerOptions: {
    cohere: {
      inputType: 'search_query'
    }
  }
});

For pre-release or alpha software, clearly state limitations and expectations (e.g., “not for production use”, “subject to breaking changes”). Always aim to create documentation that developers can immediately implement without needing to figure out missing pieces.


Remove unsupported runtime versions

When maintaining CI/CD pipelines, regularly audit and remove runtime versions that are no longer supported by your project’s dependencies or cause build failures. This prevents pipeline instability and reduces maintenance overhead.

Unsupported versions should be removed from all workflow matrices consistently across test, integration, and end-to-end testing jobs to maintain pipeline reliability.

Example:

strategy:
  matrix:
    # Remove 18.x due to dependency compatibility issues
    node-version: [20.x, 22.x, 24.x]

This practice ensures that CI resources are focused on supported runtime environments and prevents false negatives from incompatible version combinations. When removing versions, document the reasoning (e.g., “dependency requires Node 20+”) to help future maintainers understand the decision.


Decouple tests from implementation

Tests tightly coupled to implementation details break easily when the implementation changes, creating maintenance burden and reducing test reliability. Write tests that validate behavior rather than specific implementation details.

To avoid implementation coupling:

  1. Import constants from source rather than redefining them:
// GOOD
import { DEFAULT_GIT_DIFF_LINE_LIMIT } from "./viewDiff";

test("viewDiff should truncate diffs exceeding line limit", async () => {
  const largeInput = Array(DEFAULT_GIT_DIFF_LINE_LIMIT + 1).fill("test line");
  // ...
});

// BAD
test("viewDiff should truncate diffs exceeding line limit", async () => {
  const DEFAULT_GIT_DIFF_LINE_LIMIT = 5000; // Duplicated constant
  // Test will break if implementation changes the limit
  // ...
});
  1. Verify assumptions instead of hardcoding expected values:
// GOOD
test("should use the default TTL value", () => {
  const anthropic = new Anthropic({/* config */});
  const defaultTtl = anthropic.getDefaultTtl(); // Get actual implementation value
  
  const result = anthropic.convertMessages(messages);
  expect(result[0].content[0].cache_control.ttl).toBe(defaultTtl);
});

// BAD
test("should use default TTL when not specified", () => {
  // Assumes '5m' is the default without verification
  expect(result.content[0].cache_control.ttl).toBe("5m");
});
  1. Test behavior and outcomes instead of internal structure:
// GOOD - Tests behavior without assuming structure
test("should contain expected rule names", () => {
  const applicableRules = getApplicableRules();
  expect(getRuleNames(applicableRules)).toContain("Global Rule");
});

// BAD - Tightly coupled to structure
test("should contain expected rule names", () => {
  const applicableRules = getApplicableRules();
  expect(applicableRules.map(r => r.rule.name)).toContain("Global Rule");
});

When mocking, verify the right parameters are passed rather than just counting calls. This ensures tests remain valid even when implementation details change.


Document security implications clearly

When documenting features that involve sensitive data, authentication, or privileged operations, explicitly state the security implications and use appropriate warning levels to ensure users understand potential risks.

This includes:

Example from API key documentation:

:::warning
An API key represents the user who created it. If you create a key as a superuser, then that key will have superuser privileges.
Anyone who has that key can authorize superuser actions through the Langflow API, including user management and flow management.
:::

This practice helps users make informed security decisions and prevents inadvertent exposure of sensitive information through better awareness of security implications.


Prevent timeout race conditions

When working with timeouts and asynchronous operations that affect shared state, clear timeouts at the beginning of event handlers or user interactions to prevent race conditions. This defensive approach ensures that competing operations (like auto-approval timers and manual user actions) don’t conflict.

Always implement shared cancellation mechanisms when multiple components or functions interact with the same asynchronous process:

// GOOD: Clear timeouts at the beginning of handlers
function handleSendMessage(text, images) {
  // Clear auto-approval timeout FIRST to prevent race conditions
  if (autoApproveTimeoutRef.current) {
    clearTimeout(autoApproveTimeoutRef.current);
    autoApproveTimeoutRef.current = null;
  }
  
  // Now process the message safely
  if (messagesRef.current.length === 0) {
    vscode.postMessage({ type: "newTask", text, images });
  } else {
    // Other processing...
  }
}

// BAD: Clearing timeouts inside conditional blocks can lead to race conditions
function handleSendMessage(text, images) {
  if (messagesRef.current.length === 0) {
    vscode.postMessage({ type: "newTask", text, images });
  } else if (clineAskRef.current === "followup") {
    // Timeout might fire before reaching this point!
    if (autoApproveTimeoutRef.current) {
      clearTimeout(autoApproveTimeoutRef.current);
    }
    // Process message...
  }
}

For components with interdependent timers, consider using a shared state or context to coordinate cancellation across component boundaries.


Always use relative links instead of absolute links in documentation files to enable proper broken link detection and ensure compatibility with documentation generators like MkDocs.

Absolute links prevent documentation tools from detecting broken links and can cause navigation issues. MkDocs specifically does not support absolute links by default and will generate warnings for unrecognized absolute paths.

Problematic (absolute links):

- [Building AI Agents with DSPy](/tutorials/customer_service_agent/)
- [Set Up Observability](../tutorials/observability/#tracing)

Correct (relative links):

- [Building AI Agents with DSPy](../customer_service_agent/index.ipynb)
- [Set Up Observability](../tutorials/observability/index.md#tracing)

When linking to sections within other pages, include the full file path with index.md to help MkDocs understand the relative link structure. This prevents warnings like “contains an unrecognized relative link” and ensures proper link resolution in the generated documentation.


Standardize naming patterns consistently

Establish and follow consistent naming conventions for similar types of elements throughout the codebase and documentation. When multiple instances of the same type of element exist, ensure they follow the same naming pattern to avoid confusion and improve maintainability.

For documentation placeholders and variables, standardize on a single format (e.g., $VARIABLE_NAME vs VARIABLE_NAME) and apply it consistently across all documentation. For section headers and labels, ensure the naming accurately reflects the scope of content - use plural forms when covering multiple items and singular when covering a single concept.

Example issues to avoid:

# Bad: Inconsistent placeholder formats
--url "http://LANGFLOW_SERVER_ADDRESS/api/v1/run/FLOW_ID"
--header "x-api-key: $LANGFLOW_API_KEY"

# Good: Consistent placeholder format
--url "http://$LANGFLOW_SERVER_ADDRESS/api/v1/run/$FLOW_ID"  
--header "x-api-key: $LANGFLOW_API_KEY"

# Bad: Inaccurate scope naming
## Component menu  (when describing multiple menus)

# Good: Accurate scope naming  
## Component menus (when describing multiple menus)

This prevents confusion for users and developers, and makes the codebase more professional and maintainable.


Extract shared code patterns

Identify and extract duplicate code patterns into shared utility functions to improve maintainability and reduce redundancy. When similar logic appears in multiple places, create a reusable function in a shared utility file.

Example of problematic code:

// In openai.ts
private isInsufficientQuotaError(error: any): boolean {
    // Duplicate quota detection logic
}

// In openai-compatible.ts
private isInsufficientQuotaError(error: any): boolean {
    // Same quota detection logic repeated
}

Better approach:

// In shared/quota-utils.ts
export function isInsufficientQuotaError(error: any): boolean {
    // Centralized quota detection logic
}

// In both files:
import { isInsufficientQuotaError } from '../shared/quota-utils';

Key guidelines:

This improves code maintainability by:


Prevent duplicate keys

Always ensure configuration files, especially JSON files, have unique keys. Duplicate keys can cause unpredictable behavior as the last occurrence of a key will overwrite previous values, potentially leading to runtime errors or inconsistent application behavior.

When adding new configuration:

Example of problematic code:

{
  "codeIndex": {
    "setting1": "value1"
  },
  // Other settings...
  "codeIndex": {
    "setting2": "value2"
  }
}

Correct approach:

{
  "codeIndex": {
    "setting1": "value1",
    "setting2": "value2"
  }
  // Other settings...
}

This is especially critical in localization files and application configuration where duplicate keys can lead to missing translations or incorrect settings being applied.


Document configuration decisions

When modifying configuration files (package.json, tsconfig.json, etc.), document the reasoning behind significant changes and verify they don’t introduce unexpected side effects. This is especially important for changes affecting dependencies and build processes.

For dependency management:

For build configurations:

Example:

// package.json
{
  "dependencies": {
    // Fixed version for critical dependencies with compatibility requirements
    "prettier": "3.5.3",
    "prettier-plugin-svelte": "3.2.7",
    
    // Regular dependency for internal tools (not peer/dev)
    "zod": "3.23.8"
  }
}

// tsconfig.json
{
  "compilerOptions": {
    // Best practice for bundler targets (enables better dead code removal)
    "module": "ESNext",
    // Other settings...
  }
}

When making these changes, document your reasoning in commit messages or inline comments to provide context for other developers.


Validate configurations up front

Always validate configuration parameters and environment variables at initialization time, providing clear error messages for missing or invalid values. This helps catch configuration issues early and makes debugging easier.

Key practices:

  1. Check required environment variables before attempting to use associated features
  2. Validate configuration parameters at initialization
  3. Provide clear, actionable error messages
  4. Respect configuration hierarchy (passed parameters take precedence over environment variables)

Example:

def __init__(self, api_key: Optional[str] = None):
    # Check required env vars early
    if not api_key and "REQUIRED_API_KEY" not in os.environ:
        raise ValueError(
            "API key must be provided either through initialization parameter "
            "or REQUIRED_API_KEY environment variable"
        )
    
    # Respect parameter hierarchy
    self.api_key = api_key or os.environ["REQUIRED_API_KEY"]
    
    # Only import optional dependencies if configured
    if self.api_key:
        try:
            from optional_package import OptionalClient
            self.client = OptionalClient(self.api_key)
        except ImportError:
            raise ImportError(
                "Optional package is required when using this feature. "
                "Install it with: pip install optional_package"
            )

API endpoint documentation

Ensure API documentation includes all required networking components and uses proper syntax for shell commands. API examples must include authentication headers, use correct variable expansion syntax, and clearly state network configuration assumptions.

Key requirements:

Example of proper curl documentation:

curl -X POST "http://localhost:7860/api/v1/run/$FLOW_ID" \
-H "Content-Type: application/json" \
-H "x-api-key: $LANGFLOW_API_KEY" \
-d '{
    "input_value": "message",
    "input_type": "chat",
    "output_type": "chat"
}'

This ensures developers can successfully integrate with network services without encountering authentication failures or variable expansion issues that would prevent proper API communication.


Remove production console logs

Console logs should not appear in production code, especially debug statements that can expose sensitive information or clutter output. When error logging is necessary, log detailed information internally while presenting sanitized messages to users.

Remove debug console.log statements before merging to production. For legitimate error handling, use proper error logging that separates internal details from user-facing messages.

Example of proper error logging:

} catch (err) {
    // Log full error details internally for debugging
    console.error(`Error during Claude Code execution:`, err)
    
    // Show sanitized message to user
    throw new Error(`Claude Code process failed.${errorOutput ? ` Error: ${errorOutput}` : ""}`)
}

Be particularly strict with files that handle sensitive data or user interactions. Consider adding code comments or linting rules to prevent console logs from being reintroduced in critical files.


Justify configuration overrides

Before adding manual configuration entries, verify that the tool doesn’t already provide the desired behavior automatically. Document why the override is necessary and what specific problem it solves.

Many development tools have intelligent defaults and auto-discovery features. Adding unnecessary configurations can create maintenance overhead and potential conflicts.

When proposing configuration changes:

  1. Research the tool’s default behavior and auto-discovery capabilities
  2. Clearly explain what problem the configuration solves
  3. Consider potential conflicts with other extensions or tools
  4. Document any environment-specific exclusions with clear reasoning

Example from VS Code keybindings:

{
  "command": "editor.action.inlineSuggest.commit",
  "key": "tab",
  "when": "inlineSuggestionVisible && editorTextFocus && !editorTabMovesFocus && !inSnippetMode && !suggestWidgetVisible"
}

Instead of complex conditions, first verify if the desired behavior can be achieved through simpler means or if the tool already supports it in certain contexts.


organize test setup

Reduce test code duplication by organizing common setup logic and grouping related tests appropriately. Move repeated setup code into beforeEach hooks and use describe blocks to group tests that share similar setup or test the same feature area.

When tests have repeated setup code, extract it to beforeEach to improve maintainability. For feature-specific tests, group them in dedicated describe blocks with their own setup:

describe("AutocompleteProvider whitespace handling", () => {
    let mockContext: any
    let mockProvider: any
    let provideInlineCompletionItems: any

    beforeEach(() => {
        vi.clearAllMocks()
        
        mockContext = {
            subscriptions: [],
        }
        
        // Common setup for all whitespace tests
        vi.mocked(ContextProxy.instance.getGlobalState).mockReturnValue({
            autocomplete: true,
        })
    })

    // Individual tests here...
})

For test utilities that need global access, provide clear documentation explaining their purpose and scope, especially when exposing APIs for testing convenience.


Inline configuration dictionaries

Avoid storing simple configuration data in separate JSON files. Instead, define configuration as Python dictionaries directly within the relevant modules. This approach reduces file overhead, improves maintainability, and keeps related code together.

When configuration is static and doesn’t require external modification, inline dictionaries are preferred over separate JSON files. This pattern should be used for initialization parameters, default settings, and other module-specific configuration data.

Example transformation:

# Instead of loading from initialize_params.json
# with open('initialize_params.json') as f:
#     config = json.load(f)

# Define configuration directly in the module
INITIALIZE_PARAMS = {
    "processId": None,
    "clientInfo": {
        "name": "solidlsp",
        "version": "1.0.0"
    },
    "capabilities": {
        "textDocument": {
            "completion": {"completionItem": {"snippetSupport": True}}
        }
    }
}

Reserve external JSON files for configuration that needs to be modified by users or varies between environments.


Prevent injection vulnerabilities

When constructing templates or dynamic content that will be parsed, always implement robust escaping mechanisms to prevent injection vulnerabilities. Avoid using delimiters in template strings that might appear in the content itself, as this could break formatting or enable code injection attacks.

For example, instead of:

const template = "```{{{languageShorthand}}}\n{{{userExcerpts}}}```";

Consider using:

  1. Custom delimiters unlikely to appear in content
  2. Proper escaping functions for user-provided content
  3. Template libraries with built-in sanitization

This practice is critical for preventing cross-site scripting (XSS), SQL injection, command injection, and other security vulnerabilities that occur when user input is improperly handled in templates or dynamic content.


Component naming consistency

Ensure component usage in templates matches registered components. Vue components must be referenced in templates by either their kebab-case equivalent or by their exact registered name.

When registering a component:

components: {
  N8nIcon,
},

Use it in templates with the matching kebab-case name:

<n8n-icon v-bind="args" />

Or with the exact registered name:

<N8nIcon v-bind="args" />

Using inconsistent names like <flowstate-icon> when the component is registered as N8nIcon will cause runtime errors because Vue will not recognize the element.

This also applies to all component closing tags, which should match the opening tag. Consistent component naming helps prevent runtime errors, improves code readability, and follows Vue’s standard conventions.


Keep tests simple

Tests should be straightforward, explicit, and free from complex logic or indirection. Avoid “magic” in tests that makes them harder to understand at a glance. When designing tests:

  1. Prefer explicit setup over helper functions that hide details: ```javascript // Avoid: const store = initStore(chats);

// Prefer: const store = new ChatStore({ chats });


2. Inline test data directly rather than using complex extraction logic:
```javascript
// Avoid:
const text = content
  .filter(item => item.type === 'text' && !item.thought)
  .map(item => item.text)
  .join('');

// Prefer:
expect(content).toMatchInlineSnapshot(`
  [
    { "type": "text", "text": "Hello, World!" },
  ]
`);
  1. Test one behavior per test case so they can fail independently and provide clear signals about what’s broken.

  2. Make tests deterministic by stubbing variable elements like dates, timeouts, and IDs.

Simple tests are easier to understand, debug, and maintain, serving effectively as both verification tools and living documentation of expected behavior.


Use reactive hooks

Always use React’s reactive hook patterns instead of imperative state access or manual effect management. This ensures proper component re-rendering, better performance, and cleaner code architecture.

Avoid non-reactive state access:

// ❌ Bad - non-reactive, fixed value
const config = useAgentStore.getState().currentAgentChatConfig;
const inboxMessages = useChatStore.getState().messagesMap[messageMapKey(INBOX_SESSION_ID, activeTopicId)] || [];

// ✅ Good - reactive hook usage
const config = useAgentStore(agentSelectors.currentAgentChatConfig);
const inboxMessages = useChatStore(chatSelectors.inboxActiveTopicMessages);

Use proper data fetching patterns:

// ❌ Bad - manual useEffect for data fetching
useEffect(() => {
  const fetchData = async () => {
    const data = await api.getData();
    setData(data);
  };
  fetchData();
}, []);

// ✅ Good - use data fetching libraries
const { data, loading, error } = useSWR('/api/data', fetcher);

Leverage React’s built-in capabilities:


Optimize store selectors

Write store selectors with proper patterns to prevent unnecessary component re-renders. Use inline selector functions that extract only the needed data, and provide custom equality comparisons for complex data types like arrays and objects.

For simple value extraction, use inline selector functions:

// ❌ Incorrect - causes re-renders when unrelated store data changes
const config = useAgentStore(agentChatConfigSelectors.currentChatConfig);
const enableCompressHistory = config.enableCompressHistory;

// ✅ Correct - only re-renders when enableCompressHistory changes
const enableCompressHistory = useAgentStore(
  s => agentChatConfigSelectors.currentChatConfig(s).enableCompressHistory
);

For arrays and objects, use equality comparisons to prevent re-renders on reference changes:

import isEqual from 'fast-deep-equal';

// ✅ Correct - prevents re-renders when array contents are the same
const remoteModels = useUserStore(
  modelProviderSelectors.remoteProviderModelCards(provider), 
  isEqual
);

This prevents performance issues where components re-render unnecessarily when unrelated store data changes, improving overall application responsiveness.


Never commit credentials

Credentials, passwords, API tokens, and database connection strings must never be committed to version control in any form, even in configuration files or Kubernetes manifests. This practice exposes sensitive information to anyone with repository access and creates security vulnerabilities.

Instead:

  1. Use environment variables or secret injection at runtime
  2. Store credentials in a dedicated secrets management system
  3. Include placeholders in configuration files

Example - Replace hardcoded credentials:

# INSECURE - Don't do this
MONGODB_URI: "mongodb+srv://akaneai420:ilovehentai123@cluster0.jwyab3g.mongodb.net/?retryWrites=true"
LOGIN_PASSWORD: password

# SECURE - Do this instead
MONGODB_URI: "${MONGODB_URI}"
LOGIN_PASSWORD: ${LOGIN_PASSWORD}

For Kubernetes, use secrets management solutions rather than committing stringData values directly. When committing example configurations, always use placeholder values that make it clear a real value needs to be substituted.


Flexible API inputs

Design APIs to accept flexible input formats and schema structures, ensuring a better developer experience while maintaining consistency in internal implementation.

For input parameters, support multiple formats where reasonable:

// Instead of requiring only URL objects:
const { text } = await transcribe({
  model: revai.transcription('machine'),
  audio: new URL('https://example.com/audio.mp3'),
});

// Also support string URLs:
const { text } = await transcribe({
  model: revai.transcription('machine'),
  audio: 'https://example.com/audio.mp3',
});

For schema definitions, ensure support for flexible structures including additional properties where appropriate:

// Support additional properties in schemas
// e.g., using z.record(z.string()) or additionalProperties in JSON Schema

When implementing format flexibility:


prefer simple null-safe patterns

Use straightforward null-safe patterns instead of complex undefined/empty distinctions. Avoid any types that can hide potential null/undefined issues at runtime.

When handling optional values, prefer simple fallback patterns like || {} over complex checks that distinguish between undefined and empty objects. As noted in code reviews, “it’s tricky to depend on a distinction between undefined and empty” because developers often add || {} everywhere, making the distinction unreliable.

Example of preferred approach:

// Prefer this simple pattern
await updateGlobalState("customSupportPrompts", message.values || {})

// Over complex undefined/empty distinctions
if (Object.keys(message?.values ?? {}).length === 0) {
  // complex logic here
}

Also avoid any types that mask null safety:

// Avoid
const deleteMessagesForResend = async (cline: any, originalMessageIndex: number) => {

// Prefer explicit typing
const deleteMessagesForResend = async (cline: ClineProvider, originalMessageIndex: number) => {

Preserve icon font families

When working with icon elements in CSS, maintain the specialized font families designed for icon rendering. Replacing icon fonts (like ‘element-icons’) with standard text fonts (like ‘Inter’) will break icon displays that depend on specific glyph mappings in the icon font.

Example of correct usage:

[class^='el-icon-'],
[class*=' el-icon-'] {
  /* use !important to prevent issues with browser extensions that change fonts */
  font-family: 'element-icons' !important;
}

.selector::after {
  position: absolute;
  right: 20px;
  font-family: 'element-icons';
  content: '\e6da'; /* This glyph exists in the icon font */
}

Before changing font-family properties, understand their purpose in the styling system, especially when they relate to icon rendering or special visual elements.


Sanitize user input

Always sanitize and validate user-controlled input before using it in sensitive operations, and never hard-code credentials in source code.

For command execution:

For credential management:

Bad example (command injection vulnerability):

username = request.get_json().get('username')
os.system(f'docker compose -f {compose_file} -p n8n-{username} up -d')

Better example:

import shlex
import subprocess

username = request.get_json().get('username')
# Validate username format with a strict pattern
if not re.match(r'^[a-zA-Z0-9_-]+$', username):
    return jsonify({'error': 'Invalid username format'}), 400

# Use subprocess with parameters list instead of shell=True
subprocess.run(['docker', 'compose', '-f', compose_file, '-p', f'n8n-{username}', 'up', '-d'])

Bad example (credential management):

uri = "mongodb+srv://akaneai420:ilovehentai321@cluster0.jwyab3g.mongodb.net/?retryWrites=true"

Better example:

# Load from environment variables
db_user = os.getenv('DB_USER')
db_password = os.getenv('DB_PASSWORD')
db_host = os.getenv('DB_HOST')
uri = f"mongodb+srv://{db_user}:{db_password}@{db_host}/?retryWrites=true"

These practices help prevent both command injection attacks and credential leakage, which are common security vulnerabilities in web applications.


Secure credential management

Never hardcode sensitive information like passwords, API keys, or access tokens directly in code or configuration files (including Dockerfiles). These credentials can be exposed through version control systems, shared images, or when files are accessed by unauthorized users.

Instead:

Example - Insecure:

# Dockerfile.prod
FROM nginx:latest
ENV ADMIN_PASSWORD=supersecret123

Example - Secure:

# Dockerfile.prod
FROM nginx:latest
ENV ADMIN_PASSWORD=${ADMIN_PASSWORD}
# Password will be passed at build/runtime, not stored in file

Use descriptive names

Choose variable, method, class, and parameter names that clearly communicate their purpose and avoid ambiguity. Names should be self-documenting and specific rather than generic or vague.

Key principles:

Example:

# Poor naming - vague and confusing
def enumerate_fields(fields: dict) -> str:
    adapter_retry_count = 0
    input_opt_right = "test"
    
# Better naming - descriptive and clear  
def get_field_description_string(fields: dict) -> str:
    max_parse_retries = 0
    user_input = "test"

This approach makes code more maintainable and reduces the cognitive load for other developers reading your code.


Use specific configuration patterns

When defining exclusion patterns, file filters, or other configuration rules, use specific, targeted patterns rather than broad glob patterns. Overly broad patterns can lead to unintended exclusions and hard-to-debug issues in the future when legitimate files need to be included.

For example, instead of using a broad pattern like !dist/**/*.tgz that excludes all .tgz files from any subdirectory, use a specific pattern like !dist/google-gemini-cli-core-*.tgz that targets only the intended files. This approach:

{
  "files": [
    "dist",
    "!dist/google-gemini-cli-core-*.tgz"  // Specific pattern
  ]
}

This principle applies to all configuration contexts including package.json files arrays, .gitignore patterns, build tool configurations, and other rule-based settings.


Write resilient test assertions

Write test assertions that are resilient to implementation changes by focusing on behavior rather than implementation details. Avoid exact matches when partial or behavioral assertions would suffice.

Key practices:

  1. Use flexible matchers instead of exact equality
  2. Focus on behavior over implementation details
  3. Test for presence of required properties rather than exact object shape

Example - Instead of brittle exact matching:

// ❌ Brittle - breaks if new options are added
expect(options).toEqual({ 
  preview: false, 
  viewColumn: vscode.ViewColumn.Active 
})

// ✅ Resilient - verifies required properties
expect(options).toEqual(expect.objectContaining({ 
  preview: false,
  viewColumn: vscode.ViewColumn.Active 
}))

For token counting or similar approximate values:

// ❌ Brittle - breaks if tokenizer changes slightly
expect(tokenCount).toBe(14)

// ✅ Resilient - verifies reasonable range
expect(tokenCount).toBeGreaterThan(12)
expect(tokenCount).toBeLessThan(16)

This approach:


Use descriptive names

Choose descriptive, domain-specific names that clearly communicate intent and prevent confusion. Avoid generic names when more specific alternatives exist, especially when working alongside similar types or concepts from external libraries.

Key principles:

Example:

// Avoid generic names that could cause confusion
export interface Page extends PlaywrightPage { ... }

// Use descriptive, domain-specific names
export interface StagehandPage extends PlaywrightPage { ... }

// Avoid ambiguous parameter names
function configure(instructions?: string) { ... }

// Use semantically clear names
function configure(systemPrompt?: string) { ... }

This approach makes code self-documenting and reduces cognitive load when working with multiple similar concepts or external dependencies.


Safe property access

Always use proper null safety patterns when accessing properties that might be null or undefined. This prevents runtime errors and improves code robustness.

Key practices:

  1. Use optional chaining consistently at every level of nested property access: ```typescript // ❌ Inconsistent - still can cause runtime errors configResult.config?.selectedModelByRole.chat?.completionOptions

// ✅ Consistent optional chaining configResult.config?.selectedModelByRole?.chat?.completionOptions


2. Verify object type before accessing properties, especially with DOM elements:
```typescript
// ❌ Unsafe - activeElement could be null
document.activeElement.classList.contains("ProseMirror")

// ✅ Type-safe access
if (document.activeElement instanceof Element && 
    document.activeElement.classList.contains("ProseMirror"))
  1. Use nullish coalescing to provide safe defaults: ```typescript // ❌ Unsafe - will throw if nodeTextValue is null/undefined startIndex = nodeTextValue.indexOf(query, startIndex);

// ✅ Safe with fallback startIndex = nodeTextValue?.indexOf(query, startIndex) ?? -1;


4. Prefer positive conditions for null checks:
```typescript
// ❌ Less readable
onTitleClick={!item.content ? undefined : handleTitleClick}

// ✅ More readable
onTitleClick={item.content ? handleTitleClick : undefined}

Configuration consistency management

When modifying configuration files, ensure all references to the changed values are updated consistently across the entire project. Configuration changes rarely exist in isolation - they often have ripple effects throughout the codebase.

Key guidelines:

Example:

# If changing a package name in package.json:
-  "name": "n8n-monorepo",
+  "name": "n8n-official",

# Ensure all references are updated in dependent scripts:
- pnpm --filter n8n-monorepo
+ pnpm --filter n8n-official

Or when modifying workspace paths:

# In devcontainer.json:
-  "workspaceFolder": "/workspaces",
+  "workspaceFolder": "/workspaces/n8n",

# Ensure postCreateCommand and other scripts 
# are adjusted to work with the new path context

Similarly, when changing TypeScript references or path aliases, audit all dependent configurations to prevent build failures and ensure tooling compatibility.


Standardize LLM configurations

When configuring LLM providers and their capabilities, always use proper JSON syntax with quoted property names and explicitly declare all relevant capabilities. This ensures your AI models work as expected with the correct features enabled.

For third-party LLM providers:

  1. Always use quoted property names in JSON configuration
  2. Explicitly declare all model capabilities that are needed
  3. Verify configuration file paths and formats are correct

Example of proper LLM configuration:

{
  "models": [
    {
      "title": "Custom Provider",
      "provider": "openai",
      "model": "third-party-model",
      "contextLength": 8192,
      "apiBase": "https://your-api-provider/v1",
      "capability": {
        "uploadImage": true,
        "tools": true
      }
    }
  ]
}

Proper configuration prevents runtime errors when using AI features and ensures that all capabilities (like image uploads or tool use) are correctly recognized by the system.


Sanitize untrusted input

Always sanitize or escape untrusted input before using it in security-sensitive contexts to prevent injection attacks. This includes HTML content that could lead to XSS vulnerabilities and user-provided strings used in regex patterns.

For HTML content, avoid directly rendering untrusted data. Instead of passing raw HTML to iframe srcdoc or similar contexts, use a component library with controlled inputs or implement proper HTML escaping.

For regex patterns, escape special characters in user input before using it in regex construction:

// Vulnerable - user input could inject regex patterns
const regex = new RegExp(`{{${userKey}}}`);

// Safe - escape special characters to treat input as literal text
const regex = new RegExp(`{{\s*${userKey.replace(/[.*+?^${}()|[\]\\]/g, '\$&')}\s*}}`, 'g');

Consider the security implications of any user-controlled data and apply appropriate sanitization based on the context where it will be used.


Avoid hardcoded configurations

Always extract configuration values from appropriate sources (config files, environment variables, etc.) rather than hardcoding them in your code. Include validation to ensure the configuration is valid before use, and provide sensible defaults with the ability to override when needed.

Bad practice:

// Hardcoded values that are difficult to maintain
execSync(`code --uninstall-extension rooveterinaryinc.roo-cline`, { stdio: "inherit" })

Good practice:

// Dynamic configuration from package.json
const packageJson = JSON.parse(fs.readFileSync("./src/package.json", "utf-8"))
const publisher = packageJson.publisher
const name = packageJson.name
const extensionId = `${publisher}.${name}`

// Validation before use
const vsixFileName = `./bin/${name}-${version}.vsix`
if (!fs.existsSync(vsixFileName)) {
  console.error(`VSIX file not found: ${vsixFileName}`)
  process.exit(1)
}

// Allow for overriding defaults
const editorCommand = process.env.EDITOR_COMMAND || "code"
execSync(`${editorCommand} --uninstall-extension ${extensionId}`, { stdio: "inherit" })

This approach improves maintainability, prevents errors when configurations change, and allows your code to work in different environments without modification.


test security end-to-end

Security features must be tested using the actual executable or CLI rather than just module-level unit tests. This ensures the complete security mechanism works end-to-end in the real execution environment, not just individual components in isolation.

When implementing security controls like environment variable isolation, input validation, or authentication flows, create integration tests that invoke the actual product executable to validate the security behavior works as intended from the user’s perspective.

Example:

// Good: Test security feature with actual CLI
const output = execSync(
  `node packages/cli/index.js --ignore-local-env`,
  { cwd: testProjectDir, encoding: 'utf8' }
);
// Verify malicious .env files are NOT loaded

// Avoid: Only testing the security logic in isolation
const result = envLoader.loadWithIsolation(options);

This approach catches security vulnerabilities that might only manifest when all components work together, such as configuration precedence issues, CLI argument parsing bugs, or execution context problems that could bypass security controls.


Vue component test requirement

Every Vue component (.vue file) that is created or modified must have at least one corresponding unit test file. The test must import the component, mount it, and include assertions that validate its behavior.

When modifying an existing component, check for an existing test file (e.g., ComponentName.spec.ts or ComponentName.test.ts) in the same directory or in a dedicated tests directory. If a test exists, update it to cover your changes. If no test exists, create one.

Example test structure:

import { mount } from '@vue/test-utils';
import ComponentName from './ComponentName.vue';

describe('ComponentName', () => {
  it('renders correctly', () => {
    const wrapper = mount(ComponentName, {
      props: {
        // required props
      }
    });
    
    // Assert component renders correctly
    expect(wrapper.exists()).toBe(true);
    
    // Assert on specific behavior
    expect(wrapper.find('.some-class').exists()).toBe(true);
  });
  
  // Additional tests for component behavior
});

This requirement ensures that all Vue components are tested, making the codebase more maintainable and reducing the risk of regressions when components are modified. Tests should verify both rendering and functional aspects of components, particularly focusing on any new or modified features.


Follow standard naming

Use established naming patterns and correct capitalization throughout the codebase and documentation.

For test fixtures and recordings, follow common conventions like __snapshots__ instead of custom directory names:

// Preferred
// store test recordings in __snapshots__ directory
const testData = require('./__snapshots__/test-response.json');

// Avoid
// using custom or inconsistent directory names
const testData = require('./__data__/test-response.json');

For product and technology names, use proper capitalization and complete names:

// Correct
# Oracle AI Vector Search with LangChain.js Integration

// Incorrect
# Oracle Vector Search with LangchainJS Integration

Consistent naming improves readability, maintainability, and shows professionalism in your code and documentation.


Use theme-based styling

Always use CSS custom properties (CSS variables) for colors and include proper accessibility attributes instead of hard-coded values. This ensures consistency with the design system and improves accessibility for users with visual impairments or different theme preferences.

Color Usage: Replace hard-coded color values with theme-based CSS variables:

// ❌ Avoid hard-coded colors
style={{
  backgroundColor: "rgba(255, 191, 0, 0.1)",
  border: "1px solid rgba(255, 191, 0, 0.3)",
  color: "#FFA500"
}}

// ✅ Use theme-based colors
style={{
  backgroundColor: "var(--vscode-inputValidation-warningBackground)",
  border: "1px solid var(--vscode-inputValidation-warningBorder)", 
  color: "var(--vscode-inputValidation-warningForeground)"
}}

Accessibility Attributes: Include appropriate ARIA labels and roles for interactive elements:

// ❌ Missing accessibility attributes
<VSCodeButton onClick={handleCopyCode} title="Copy Code">

// ✅ Include aria-label for screen readers
<VSCodeButton onClick={handleCopyCode} title="Copy Code" aria-label="Copy Code">

// ❌ Clickable div without accessibility
<div onClick={() => { /* handler */ }}>

// ✅ Proper accessibility for interactive elements  
<div onClick={() => { /* handler */ }} aria-label="View HTML Content" role="button" tabIndex={0}>

This approach helps users with visual impairments, supports different VS Code themes, and maintains consistency across the application interface.


Include concrete examples

Technical documentation should always include concrete, working examples that demonstrate the described concepts in action. Examples clarify abstract ideas, illustrate correct usage patterns, and provide templates users can adapt to their needs.

When writing documentation:

For example, when documenting a prompt template feature:

# Example prompt template configuration
promptTemplates:
  autocomplete:
    template: |
      Complete the following code in {{language}}:
      File: {{{filename}}}
      
      {{{prefix}}}
      
      # Continue the code here, completing the current statement or function

Examples make documentation more effective by transforming abstract concepts into concrete implementations that users can understand and adapt to their specific needs.


Document configuration clarity

Ensure all configuration options and setup instructions are clearly documented with their intended purposes, use cases, and the most accessible implementation paths. When introducing new configuration classes or setup steps, include contextual descriptions that help users understand when and why to use each option.

For configuration classes, provide clear descriptions of their functionality:

Currently, there are three main agent classes:

* `DefaultAgentConfig`: This is the default agent.
* `RetryAgentConfig`: A "meta agent" that instantiates multiple agents for multiple attempts and then picks the best solution.
* `ShellAgentConfig`: An agent that provides shell-based interaction capabilities for experimental mode and quick interactive workflows.

For setup instructions, prioritize user-friendly approaches and link to simpler alternatives when available:

3. [Install Miniconda](https://docs.anaconda.com/free/miniconda/#quick-command-line-install), then create the `swe-agent` environment with `conda env create -f environment.yml`

This approach helps developers quickly understand available configuration options and reduces setup friction, leading to better adoption and fewer configuration-related issues.


Standardize AI model interfaces

When implementing AI model integrations, maintain consistent interfaces and proper type definitions across different providers. This ensures compatibility, prevents runtime errors, and simplifies maintenance.

Key guidelines:

  1. Define explicit interfaces for model-specific features
  2. Isolate provider-specific logic in dedicated classes
  3. Use proper type definitions for model responses
  4. Maintain consistent parameter naming across providers

Example of proper implementation:

// Define shared interface
interface ModelProvider {
  embed(chunks: string[], task: EmbeddingTasks): Promise<number[][]>;
  chat(messages: ChatMessage[], options: ChatOptions): AsyncGenerator<string>;
}

// Implement provider-specific class
class DeepSeekProvider implements ModelProvider {
  // Extend base types for provider-specific features
  interface DeepSeekMessage extends ChatMessage {
    reasoning_content?: string;
  }

  // Implement shared interface with provider-specific logic
  async embed(chunks: string[], task: EmbeddingTasks): Promise<number[][]> {
    // Provider-specific implementation
  }
}

This approach:


Simplify complex implementations

Replace verbose, complex code structures with simpler, more readable alternatives. Prefer existing methods over inline complex logic, use built-in functions instead of manual implementations, and leverage modern Python features for cleaner code.

Examples of improvements:

This approach reduces code complexity, improves maintainability, and makes the codebase more readable while preventing potential errors from overly complex implementations.


Consider async function contracts

Be intentional when marking functions as async, as it changes the function’s contract and caller expectations. Avoid using async unnecessarily when you’re just returning a promise explicitly, and consider whether making a function async implies that callers should await its completion.

For example, avoid this pattern where async adds no value:

// Unnecessary async - just returning a promise
private static async requestLLMFix(code: string, error: string): Promise<string | null> {
    return somePromiseReturningFunction(code, error)
}

Also consider the broader implications when converting functions to async:

// Before: synchronous activation
export function activate(context: vscode.ExtensionContext) {
    // setup code
    Promise.resolve(vscode.commands.executeCommand("command"))
}

// After: now returns Promise, implying callers should await
export async function activate(context: vscode.ExtensionContext) {
    // setup code  
    await vscode.commands.executeCommand("command")
}

The async version changes the contract - callers now expect to await the activation, which may not be the intended behavior for lifecycle functions.


prefer simpler implementations

When writing code, favor simpler, more straightforward implementations over complex ones. Look for opportunities to consolidate logic paths, reduce unnecessary branching, and reuse existing resources instead of recreating them.

This approach improves code readability, reduces maintenance burden, and often leads to better performance. Before implementing complex conditional logic or loading operations, consider if there’s a simpler way to achieve the same result.

Examples of simplification:

The goal is to write code that is easier to understand, test, and maintain while achieving the same functionality.


Use nullish coalescing

When providing default values for numeric properties, use the nullish coalescing operator (??) instead of logical OR (   ). This ensures that valid zero values are preserved rather than being replaced with defaults. Using   will treat 0 as a falsy value and replace it with the default, which is often unintended behavior for numeric settings.

This pattern is especially important for numeric configurations like thresholds, ranges, and input values where zero is a valid and meaningful value that should not be overridden.


Names reflect exact purpose

Choose names that precisely reflect the component’s purpose and behavior, avoiding ambiguous terms or shortcuts. Names should be self-documenting and consistent with related components.

Key guidelines:

  1. Use exact technical terms (e.g., ‘identity_loader’ not ‘noop_loader’ for a function that returns its input)
  2. Maintain semantic precision (e.g., ‘metadata_collection’ not ‘meta_collection’ since it stores data about data)
  3. Ensure component names match their behavior (e.g., ‘SchematicGenerator’ not ‘JSONGenerator’ if JSON is just an implementation detail)
  4. Use consistent terminology within related components

Example:

# Incorrect - ambiguous or imprecise names
class JSONGenerator:
    def generate(self, data: dict) -> dict:
        pass

meta_collection = db.get_collection("meta")
def noop_loader(doc: dict) -> dict:
    return doc

# Correct - precise, semantic names
class SchematicGenerator:
    def generate(self, data: dict) -> dict:
        pass

metadata_collection = db.get_collection("metadata")
def identity_loader(doc: dict) -> dict:
    return doc

Use semantic naming

Choose names that clearly communicate the purpose, behavior, or domain concept rather than generic or abbreviated terms. Names should be self-documenting and reflect what the entity actually does or represents.

Replace generic names with descriptive alternatives that convey meaning:

Maintain consistency in naming patterns across similar contexts. For example, if addressing an agent in test scenarios, consistently use second person (“when you do X”) rather than mixing with third person (“when the agent does X”).

This approach makes code more readable, reduces the need for additional documentation, and helps maintain consistency across the codebase by establishing clear semantic patterns.


Use descriptive specific names

Choose names that clearly communicate purpose and scope rather than generic or overly broad terms. Names should be specific enough to accommodate future variants and descriptive enough to indicate their function without requiring additional context.

Avoid generic package names like “util” in favor of descriptive ones that indicate the specific functionality. When naming themes, configurations, or variants, include distinguishing characteristics to prevent conflicts with future additions.

Examples:

This approach improves code maintainability, reduces naming conflicts, and makes the codebase more self-documenting.


Document configuration requirements

Always document configuration requirements, environment variables, and version specifications to ensure consistent development environments and proper system setup. This includes documenting environment variables that enhance workflow, specifying exact versions in configuration files, and providing clear setup instructions.

For environment variables, document their purpose and usage:

# Terminal sessions now automatically include a $WORKSPACE_ROOT environment variable 
# that points to your current workspace root directory
cd $WORKSPACE_ROOT

For development dependencies, reference version specification files and provide setup guidance:

## Prerequisites
1. **Node.js** (LTS version recommended) - see `.nvmrc` for exact version
2. **nvm** - recommended for Node.js version management

This ensures developers can reliably reproduce environments and understand how configuration affects system behavior.


Verify documentation references

Ensure all references in documentation (file paths, commands, code examples) actually exist in the codebase and accurately reflect the current system state. Additionally, verify that translations maintain correct meaning and grammar in all supported languages.

Examples:

# Incorrect - referencing non-existent script
node test-claude-code-integration.js

# Correct - reference actual test command
npm test -- claude-code.spec.ts

For translated content:

# Incorrect Hindi phrase
हमारी इस डेटा तक पहुंच नहीं है

# Correct Hindi phrase
हमें इस डेटा तक पहुंच नहीं है

Before submitting documentation changes, verify all referenced components exist and translations are grammatically correct and contextually accurate. This ensures documentation remains trustworthy and avoids confusion for developers using it as a reference.


Use comprehensive JSDoc

Always use JSDoc format (/** */) instead of regular comments (//) for documenting classes, functions, and interfaces. Documentation should be comprehensive, including:

  1. Clear purpose descriptions
  2. Usage examples where appropriate
  3. Proper tags like @internal for non-public API elements
  4. Cross-references using {@link ...} syntax
  5. Migration paths for deprecated features

This ensures that documentation integrates correctly with API reference generators and provides developers with sufficient context.

Example - Before:

// this class uses your clientId, clientSecret and redirectUri
// to get access token and refresh token, if you already have them,
// you can use AuthFlowToken or AuthFlowRefresh instead
export class AuthFlow {
  // ...
}

Example - After:

/**
 * Authentication flow for obtaining access and refresh tokens using clientId,
 * clientSecret and redirectUri.
 * 
 * @example
 * const auth = new AuthFlow({
 *   clientId: process.env.CLIENT_ID,
 *   clientSecret: process.env.CLIENT_SECRET,
 *   redirectUri: "http://localhost:3000/callback"
 * });
 * const tokens = await auth.getTokens();
 * 
 * @see If you already have tokens, consider using {@link AuthFlowToken} or
 * {@link AuthFlowRefresh} instead.
 */
export class AuthFlow {
  // ...
}

Avoid generic suffixes

Avoid using generic suffixes like “Response”, “Result”, or “Request” in type names, especially for non-request types. Instead, use semantic names that describe the actual data structure and can be reused throughout the codebase.

Generic suffixes make types less reusable and create unnecessary coupling to specific API contexts. Semantic names promote code reuse and better express the domain concepts.

Example:

// Avoid
message AvailableTerminalProfilesResponse {
  repeated string profiles = 1;
}

message StringArrayResponse {
  repeated string values = 1;
}

// Prefer
message TerminalProfiles {
  repeated string profiles = 1;
}

message StringArray {
  repeated string values = 1;
}

This approach makes types more generic and reusable across different parts of the codebase, not just in API handlers.


Complete model configurations

When adding new models to configuration files, ensure all required configuration fields are populated, not just the model name in the running_models list. Models need complete configuration in both JSON (known_models.json) and YAML (provider files) with all necessary fields specified.

Required fields typically include:

Example of complete configuration:

# In provider YAML file
running_models:
  - claude-4

chat_models:
  claude-4:
    n_ctx: 200000
    supports_tools: true
    supports_multimodality: true
    supports_clicks: true
    supports_agent: true
    supports_reasoning: anthropic
    tokenizer: hf://Xenova/claude-tokenizer

Incomplete configurations where only the model name is added to running_models without corresponding detailed configuration will result in runtime errors or unexpected behavior. Always cross-reference known_models.json to understand which configuration fields are required for proper model functionality.


Evaluate CI secret exposure

Before using secrets in CI/CD workflows that can be triggered by external contributors (forks, dependabot), assess the “blast radius” of potential secret compromise. Differentiate between high-risk secrets that provide infrastructure access and limited-scope secrets with constrained permissions.

High-risk secrets (avoid in external-triggerable workflows):

Limited-scope secrets (may be acceptable with proper controls):

Example from workflow configuration:

# Acceptable: Chromatic token only allows snapshot uploads
- name: Run Chromatic
  uses: chromaui/action@latest
  with:
    projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}

Always implement additional safeguards like requiring approval for external PR workflows, and document the security tradeoffs when using any secrets in publicly-triggerable workflows.


Structure configurations properly

Define a clear, hierarchical structure for application configurations with descriptive naming and proper organization. Avoid hardcoded values, use named constants for magic numbers, and ensure configuration is loaded only once at startup and passed through the application rather than loaded at arbitrary points.

Key practices:

  1. Use named constants instead of magic values:
    // Avoid
    const deadline = Date.now() + 1000;
       
    // Better
    const PROCESS_TERMINATION_TIMEOUT_MS = 1000;
    const deadline = Date.now() + PROCESS_TERMINATION_TIMEOUT_MS;
    
  2. Organize configurations hierarchically by functionality:
    // Avoid
    output: {
      maxBytes: 12410,
      maxLines: 256
    }
       
    // Better
    tools: {
      shell: {
        maxBytes: 12410,
        maxLines: 256
      }
    }
    
  3. Externalize hardcoded values:
    // Avoid
    client_id: "Iv1.b507a08c87ecfe98"
       
    // Better
    client_id: process.env.GITHUB_CLIENT_ID || config.github.clientId
    
  4. Load configuration once and thread it through:
    // Avoid
    function someFunction() {
      const config = loadConfig(); // Loading config at arbitrary points
      // ...
    }
       
    // Better
    function someFunction(config) { // Config passed as parameter
      // ...
    }
    
  5. Provide sensible defaults when configuration is missing:
    // Avoid
    const providersConfig = config.providers; // Could be undefined
       
    // Better
    const providersConfig = config.providers ?? defaultProviders;
    

Following these practices makes configurations more maintainable, testable, and prevents unpredictable behavior in long-running applications when configurations change during execution.


Extract reusable logic

Avoid duplicating logic across the codebase. Instead, extract common functionality into well-named helper functions or standalone utilities. This improves code readability, simplifies maintenance, and centralizes logic for easier updates.

Examples where this applies:

Before:

if (provider.toLowerCase() === "githubcopilot" && !apiKey) {
  apiKey = await fetchGithubCopilotApiKey();
  // Additional logic for handling the API key...
} else if (cli.flags.login) {
  if (provider.toLowerCase() === "githubcopilot") {
    apiKey = await fetchGithubCopilotApiKey();
    // Duplicate logic...
  }
}

After:

function handleGithubCopilotLogin() {
  // Centralized login logic
}

if (provider.toLowerCase() === "githubcopilot" && !apiKey) {
  apiKey = await handleGithubCopilotLogin();
} else if (cli.flags.login) {
  if (provider.toLowerCase() === "githubcopilot") {
    apiKey = await handleGithubCopilotLogin();
  }
}

Provider-agnostic AI code

Design AI integration code to be provider-agnostic, avoiding assumptions that all models will come from a single provider. Implement explicit handling for known models while maintaining fallback mechanisms for others.

For example, when determining model capabilities like context length:

function maxTokensForModel(model: string): number {
  // First check if it's a known model in our registry
  if (openAiModelInfo[model]) {
    return openAiModelInfo[model].maxContextLength;
  }
  
  // Fallback to pattern-based detection for other providers
  const lower = model.toLowerCase();
  if (lower.includes("32k")) {
    return 32000;
  }
  if (lower.includes("16k")) {
    return 16000;
  }
  if (lower.includes("8k")) {
    return 8000;
  }
  if (lower.includes("4k")) {
    return 4000;
  }
  return 128000; // Default fallback
}

Similarly, when instantiating clients, reuse existing ones when possible rather than creating provider-specific instances that duplicate logic and may drift in configuration.


avoid external test dependencies

Tests should not rely on external URLs, live websites, or internet connectivity to ensure reliability, consistency, and faster execution. External dependencies can cause tests to fail due to network issues, website changes, or unavailability, making CI/CD pipelines unstable.

Instead of using live URLs, use these alternatives:

Example of problematic code:

await page.goto('https://example.com')  # External dependency
await page.goto('https://browserleaks.com/javascript')  # External dependency

Example of improved code:

# Use pytest-httpserver (see test_controller.py)
await page.goto(f'http://localhost:{server.port}/test-page')

# Or use local browser pages
await page.goto('about:blank')
await page.goto('chrome://version')

This approach eliminates external dependencies, makes tests more reliable, reduces execution time, and ensures consistent results across different environments and network conditions.


Maintain API compatibility

When modifying existing APIs, ensure backward compatibility to prevent runtime failures and minimize migration effort for consumers. Breaking changes in function signatures, return types, or parameter requirements can cause cascading issues throughout a codebase.

Follow these practices for API evolution:

  1. Use optional parameters for new functionality instead of adding required parameters. This allows existing code to continue working without modification.
// Bad: Breaking change - adding a required parameter
- embed(chunks: string[]): Promise<number[][]>;
+ embed(chunks: string[], embedding_task: EmbeddingTasks): Promise<number[][]>;

// Good: Backward compatible change
+ embed(chunks: string[], embedding_task?: EmbeddingTasks): Promise<number[][]>;
  1. Preserve return type compatibility by using interface extension rather than changing the return type structure.
// Bad: Breaking return type change
- function compileChatMessages(...): ChatMessage[] {
+ function compileChatMessages(...): { compiledChatMessages: ChatMessage[]; lastMessageTruncated: boolean } {

// Good: Backward compatible approach
+ interface ChatMessagesResult {
+   messages: ChatMessage[];
+   lastMessageTruncated?: boolean;
+ }
+ function compileChatMessages(...): ChatMessagesResult {
  1. Use parameter objects for functions likely to evolve, making it easier to add options without breaking changes.
// Bad: Making previously optional parameters required
- required: ["name", "rule"],
+ required: ["name", "rule", "alwaysApply", "description"],

// Good: Keep core parameters required, make new ones optional
+ required: ["name", "rule"],
+ properties: {
+   alwaysApply: { type: "boolean", default: false },
+   description: { type: "string", default: "" },
+ }
  1. When breaking changes are unavoidable, provide function overloads or migration utilities to ease the transition for API consumers.

Remember that every API change affects all dependent code. Taking the time to design evolution-friendly interfaces upfront prevents costly migrations later.


Enforce strict config schemas

Configuration schemas should explicitly define all required fields and validate types at compile time to prevent runtime errors. Use strict typing with clear validation rules, and avoid marking required fields as optional.

Example:

// ❌ Problematic: Required field marked as optional
const configSchema = z.object({
  modelArn: z.string().optional(), // Could cause runtime errors
});

// ✅ Better: Explicit required/optional fields
const configSchema = z.object({
  modelArn: z.string(), // Required field
  profile: z.string().optional(), // Truly optional field
  region: z.string().optional(),
});

// Add runtime validation
function validateConfig(config: Config) {
  const result = configSchema.safeParse(config);
  if (!result.success) {
    throw new ValidationError(result.error.errors);
  }
}

This approach:

  1. Makes required fields explicit in the schema
  2. Catches missing required fields at compile time
  3. Provides clear validation errors at runtime
  4. Maintains consistency between schema and implementation

Mutually exclusive promises

Ensure that promises are either resolved or rejected, but never both. When handling promise resolution in callbacks or event handlers, use proper conditional logic to guarantee mutual exclusion between success and error paths.

For example, this pattern creates inconsistent promise states:

return new Promise((resolve, reject) => {
  child.on("message", (msg) => {
    if (msg.error) {
      reject();
    }
    resolve(); // Problem: This always executes regardless of error state
  });
});

Instead, use an else block to ensure mutual exclusion:

return new Promise((resolve, reject) => {
  child.on("message", (msg) => {
    if (msg.error) {
      reject();
    } else {
      resolve(); // Correct: Only resolves if there is no error
    }
  });
});

This prevents inconsistent promise states where both error and success handlers might execute, leading to unpredictable application behavior and hard-to-debug issues.


Explicit security bypass

When implementing functionality to bypass security controls (like sandboxing), ensure the bypass is complete and explicit rather than just configuring existing security mechanisms to be permissive. Create dedicated code paths for unrestricted operation that truly bypass all security layers.

For example, instead of:

pub fn new_unrestricted_policy() -> Self {
    // This still uses the sandbox with relaxed permissions
    SandboxPolicy {
        allow_disk_read: true,
        allow_disk_write: true,
        allow_network: true,
        auto_approve: true,
    }
}

Implement a truly separate path:

pub fn new_unrestricted_policy() -> Self {
    // Explicitly use NoSandbox implementation
    SandboxPolicy {
        sandbox_type: SandboxType::NoSandbox,
        // other fields as needed
    }
}

This prevents subtle security issues where sandboxing mechanisms might still be partially active despite intending to fully bypass them.


Config precedence and env overrides

When reading configuration from multiple sources (function arguments, environment variables, config files, defaults), implement and preserve a single, explicit precedence order, and ensure user-provided overrides beat environment-derived values.

Apply this consistently:

Example pattern (proxy mounts precedence):

# env_proxies: dict[str, str|None]
proxy_map = {k: None if v is None else Proxy(url=v) for k, v in get_environment_proxies().items()}

proxy_mounts = {
    k: None if p is None else AsyncHTTPTransport(proxy=p, **transport_kwargs)
    for k, p in proxy_map.items()
}

# User mounts override env-derived mounts
mounts = dict(proxy_mounts)
mounts.update(kwargs.get("mounts", {}))
kwargs["mounts"] = mounts

Prefer pythonic simplicity

Use Python’s expressive features to write cleaner, more maintainable code by reducing nesting and improving readability. Follow these practices:

  1. Avoid unnecessary else blocks after raising exceptions or returns: ```python

    Instead of this:

    if not FOUNDRY_AVAILABLE: raise ImportError(“Foundry Agent Dependencies are not installed.”) else: # Do something

Do this:

if not FOUNDRY_AVAILABLE: raise ImportError(“Foundry Agent Dependencies are not installed.”)

Do something


2. **Use walrus operators** for concise assignment in conditional expressions:
```python
# Instead of this:
knowledge_storage = getattr(agent, "knowledge", None)
if knowledge_storage is not None:
    knowledge_storage.reset()

# Do this:
if (knowledge_storage := getattr(agent, "knowledge", None)) is not None:
    knowledge_storage.reset()
  1. Prefer early returns to reduce indentation and improve readability: ```python

    Instead of nested conditionals:

    try: for frame_info in stack: candidate = frame_info.frame.f_locals.get(“self”) if isinstance(candidate, Flow): self.parent_flow = candidate break else: self.parent_flow = None finally: del stack

Prefer early assignments and returns:

try: self.parent_flow = None for frame_info in stack: candidate = frame_info.frame.f_locals.get(“self”) if isinstance(candidate, Flow): self.parent_flow = candidate break return self
finally: del stack


4. **Simplify conditional logic** with default assignments:
```python
# Instead of this:
if not memory_path:
    memory_path = db_storage_path()

# Do this:
memory_path = memory_path or db_storage_path()

These practices help reduce cognitive load when reading code and make it easier to spot logical errors. They also lead to more maintainable code by limiting nesting depth and reducing unnecessary verbosity.


Environment variable configuration

Prefer environment variables over hardcoded configuration values to improve flexibility and avoid forcing configuration choices on users. Always provide sensible defaults and implement proper validation.

Use environment variables for:

Implementation pattern:

# Good: Environment variable with default and validation
search_engine = os.getenv('BROWSERUSE_SEARCH_ENGINE', 'google').lower().strip()
assert search_engine in ['google', 'bing', 'duckduckgo']

# Good: Configurable port instead of hardcoded
port = int(os.getenv('CHROME_REMOTE_DEBUGGING_PORT', '9222'))
endpoint_url = f'http://localhost:{port}'

# Good: Utility function for env var validation
def check_env_variables(keys: list[str], any_or_all=all) -> bool:
    return any_or_all(os.getenv(key, '').strip() for key in keys)

# Bad: Hardcoded configuration
CAMOUFOX = True  # Should be os.getenv('USE_CAMOUFOX', 'false').lower() == 'true'

This approach allows users to customize behavior without code changes while maintaining reasonable defaults for common use cases. Create reusable utility functions for environment variable validation that can be imported across the codebase.


Model-agnostic AI code

When building applications that interact with AI models, avoid hardcoding model-specific behavior and instead design for flexibility across different LLM providers and versions. This approach increases resilience and makes your code more maintainable as the AI ecosystem evolves.

Key practices:

  1. Allow LLM instances to be passed as parameters rather than hardcoding model names
  2. Implement provider-specific handling through abstraction rather than special cases
  3. Validate LLM instances early to prevent runtime errors
  4. Use dependency injection for LLM components to make testing easier

Example:

# Instead of this:
def process_with_ai(prompt, model="gpt-4o"):
    client = OpenAI()
    response = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": prompt}]
    )
    return response.choices[0].message.content

# Do this:
def process_with_ai(prompt, llm=None):
    llm = llm or get_default_llm()
    
    # Validate LLM instance early
    if not hasattr(llm, 'call') or not callable(llm.call):
        raise ValueError("Invalid LLM instance: missing call method")
    
    # Use provider-agnostic interface
    return llm.call([{"role": "user", "content": prompt}])

def get_default_llm():
    # Create default LLM instance with appropriate config
    return BaseLLM(model="default-model")

This approach lets you easily switch models, test with mock LLMs, and adapt to new model APIs without changing your core application logic.


Use structured error logging

Always use the proper logger instance instead of console methods, and format error logs with structured data objects rather than string concatenation. Console logging methods like console.error can lead to log flooding in production and lack proper log level controls. Structured logging with error objects enables better log parsing, monitoring, and debugging.

Avoid:

console.error('Schema validation error: Detected unconverted Zod schema');
logger.error(`Failed to scrape URL ${url}: ${scrapeResponse.error}`);

Use instead:

logger.error('Schema validation error: Detected unconverted Zod schema', {
  type: val._def?.typeName,
  keys: Object.keys(val),
  hasZodProperties: !!(val._def || val.parse || val.safeParse)
});
logger.error(`Failed to scrape URL ${url}`, { error: scrapeResponse.error });

This approach provides consistent logging behavior across environments, enables proper log level filtering, and creates structured data that monitoring tools can easily parse and alert on.


Names reflect semantic purpose

Identifiers (variables, properties, keys, IDs) should accurately reflect their semantic purpose and context. Names should be chosen to clearly communicate the meaning and role of the element within its specific context, not just its technical type or generic purpose.

Examples:

// Incorrect: Name doesn't match context
const hasCustomTemperature = value !== undefined 
// Correct: Name reflects actual context
const hasCustomMaxContext = value !== undefined

// Incorrect: Generic/mismatched test ID
data-testid="open-tabs-limit-slider"
// Correct: ID reflects component purpose
data-testid="markdown-lineheight-slider"

// Incorrect: Inconsistent API property naming
interface Props {
  apiRequestFailedMessage: string;
  apiReqStreamingFailedMessage: string; // Inconsistent abbreviation
}
// Correct: Consistent naming pattern
interface Props {
  apiRequestFailedMessage: string;
  apiRequestStreamingFailedMessage: string;
}

This standard helps maintain code clarity, improves maintainability, and reduces cognitive load by ensuring names accurately represent their purpose within the codebase.


Explicit over implicit

Always explicitly configure important system components rather than relying on implicit defaults or environment variables. Document required configuration combinations and version requirements clearly to prevent subtle errors.

For example:

Configure both required components for automatic memory saving

crew = Crew( agents=[…], tasks=[…], memory=True, long_term_memory=long_term_memory, entity_memory=EntityMemory() )


- For version requirements, specify exact minimum versions (e.g., Python >=3.10) rather than recommendations when functionality depends on it

- When adding configuration flags, use consistent, explicit naming that clearly communicates scope and function (like `-kn` for all knowledge and `-akn` for agent-specific knowledge)

---

## Avoid hardcoded API assumptions

<!-- source: browser-use/browser-use | topic: API | language: Python | updated: 2025-06-09 -->

API interfaces should not contain hardcoded implementation details or assume specific underlying technologies. Instead, make them configurable and implementation-agnostic to support different backends and configurations.

When designing APIs, avoid embedding specific service names, browser types, or implementation details directly in the interface. Use dynamic configuration or parameterization instead.

Example of problematic hardcoded approach:
```python
@self.registry.action(
    'Search the query in Google, the query should be a search query...',
    param_model=SearchGoogleAction,
)

browser = await browser_class.launch(
    headless=self.config.headless,
    channel='chrome',  # Hardcoded despite browser_class potentially being firefox/webkit
)

Better approach with configurable implementation:

@self.registry.action(
    f'Search the query in {self.search_engine.title()}, the query should be a search query...',
    param_model=SearchAction,
)

# Use appropriate channel based on browser type or make it configurable
browser = await browser_class.launch(
    headless=self.config.headless,
    channel=self.get_appropriate_channel(browser_class),
)

This ensures APIs remain flexible and can adapt to different implementations without requiring interface changes.


Context-aware null checking

Choose null checking patterns based on your function’s purpose and intended behavior with empty values. For functions with fallback strategies, consider whether empty strings should trigger alternative methods or be treated as valid results.

Use if (value?.property) when empty strings should be treated as falsy and trigger fallback logic:

// Content extraction with fallbacks
if (article?.textContent) {
  return postProcessText(article.textContent)
}
// Falls through to try other extraction methods

Use if (value?.property != null) when you need to distinguish null/undefined from empty strings:

// When empty string is a valid result
if (article?.textContent != null) {
  return article.textContent // Returns empty string if that's what was parsed
}

Consider the downstream impact: will your function benefit from attempting alternative strategies when the primary method yields empty content, or should empty results be preserved and returned immediately?


Optimize AI interactions

When working with AI models and LLMs, optimize both prompts and input data to improve model performance and reduce token usage. For prompts, be specific about the AI’s role, requirements, and expected output format rather than using vague instructions. For input data, preprocess and clean content to remove unnecessary elements that could confuse the model or waste tokens.

Example of improved prompt specificity:

// Instead of vague prompts:
const prompt = `Translate the following into ${language} and only show me the translated content`

// Use specific, role-based prompts:
const prompt = `You are a professional translator. Translate the following text into ${language}, preserving meaning, tone, and formatting. Only provide the translated result.`

Example of input data cleaning:

// Clean subtitle data before sending to AI
subtitleContent = replaceHtmlEntities(subtitleContent.replace(",", " "))

This approach reduces confusion, improves output quality, and optimizes token usage when interacting with AI models.


Semantic naming patterns

Names should clearly communicate purpose, relationships, and domain context. Choose identifiers that reveal intent and accurately describe what they represent:

  1. Class/component names should reflect relationships - Name components to show their relationship with other entities. For example, prefer TaskGuardrail over GuardrailTask to indicate it’s a guardrail for tasks, not a task type.

  2. Use domain-specific naming - Avoid generic names when domain-specific terms can provide context. For instance, use crewai_events instead of generic event_bus to clearly indicate the domain.

  3. Method names should indicate actions - Name methods with verbs that describe what they do:
    # Good - name clearly indicates action
    def _get_context(self, task, task_outputs):
        # Method retrieves context
       
    # Confusing - doesn't clearly indicate if setting or getting
    def _context(self, task, task_outputs):
        # Purpose unclear from name
    
  4. Parameter names should indicate limitations - When parameters have specific constraints, reflect this in the name:
    # Good - name indicates specific model type support
    def __init__(self, openai_model_name: str):
        self.model = openai_model_name
       
    # Misleading - suggests any model type works
    def __init__(self, model: str):
        self.model = model  # Actually only works with OpenAI
    
  5. Interface naming should follow conventions - Use recognized naming patterns for interfaces and abstract classes (e.g., AgentInterface rather than AgentWrapperParent).

optimize timing intervals

Choose appropriate timing intervals for asynchronous operations to improve performance and responsiveness. For frequent polling of cheap operations, use shorter intervals (200ms instead of 1s) to reduce latency. For potentially blocking file system operations, use atomic patterns like rename-then-delete to avoid blocking the async runtime.

Example of optimized polling:

// Instead of 1-second polling
tokio::time::sleep(Duration::from_secs(1)).await;

// Use shorter intervals for cheap status checks
tokio::time::sleep(Duration::from_millis(200)).await;

Example of non-blocking file operations:

// Instead of direct removal that can block
tokio::fs::remove_dir_all(&path).await;

// Use atomic rename then remove pattern
let temp_path = path.with_extension("to-remove");
tokio::fs::rename(&path, &temp_path).await?;
tokio::fs::remove_dir_all(&temp_path).await;

This approach reduces unnecessary waiting time for responsive operations while preventing blocking operations from degrading overall system performance.


Environment variable access

Use direct process.env access and standardized configuration management instead of custom environment variable wrappers. Avoid redundant abstraction layers when the framework or libraries already handle environment variable inference automatically.

Key principles:

Example:

// ❌ Avoid custom wrappers when direct access works
clientId: authEnv.AUTH_GOOGLE_CLIENT_ID ?? process.env.AUTH_GOOGLE_CLIENT_ID

// ✅ Use direct access for new implementations
clientId: process.env.AUTH_GOOGLE_CLIENT_ID

// ✅ Use @t3-oss/env-nextjs for validation
import { createEnv } from '@t3-oss/env-nextjs';

export const appEnv = createEnv({
  server: {
    ENABLED_CLOUDFLARE: z.boolean().default(false),
    CLOUDFLARE_API_KEY: z.string().optional(),
  }
});

This approach reduces complexity, improves maintainability, and leverages existing framework capabilities for environment variable management.


Document API schemas

Add comprehensive JSDoc comments to all API interfaces, types, and schema definitions. This documentation should:

  1. Include links to official external documentation when available
  2. Describe each property in schema objects to provide context for their use
  3. Be placed at the appropriate abstraction level to support inheritance in class hierarchies
  4. Include example values where helpful

This practice improves developer experience through enhanced IDE tooltips and makes the code more maintainable by new team members.

Example:

/**
 * Web search tool result error content
 * @see https://docs.anthropic.com/en/docs/build-with-claude/tool-use/web-search-tool#errors
 */
export interface AnthropicWebSearchToolResultErrorContent {
  /** Identifies this as a web search tool error response */
  type: 'web_search_tool_result_error';
  
  /** Error code from the API (e.g., 'max_uses_exceeded', 'too_many_requests') */
  error_code: string;
}

// For schemas with multiple properties:
const providerOptionsSchema = z.object({
  /** Language code (ISO-639-1) for transcription, e.g. 'en-US' */
  language: z.string().nullish(),
  
  /** Start position in seconds for partial audio processing */
  audioStartAt: z.number().int().nullish(),
});

Explicit code organization patterns

Maintain clear and explicit code organization patterns by following these guidelines:

  1. Use explicit property visibility in classes:
    • Prefer public properties over getters/setters when no additional logic is needed
    • Use private fields (#) for truly internal state
    • Only use protected when inheritance is a core design requirement
  2. Keep imports and exports explicit:
    • Avoid wildcard exports (export *)
    • Import directly from source files rather than barrel files
    • Control what gets exported from each module

Example:

// ❌ Avoid
export * from './utils';
import { something } from './index';

class MyClass {
  private messages: Message[];
  getMessages() { return this.messages; }
}

// ✅ Better
export { generateId, parseConfig } from './utils';
import { something } from './something';

class MyClass {
  #internalState: string;
  messages: Message[]; // public property when no special handling needed
}

This pattern improves code maintainability, makes dependencies clear, and helps control your public API surface.


preserve null semantics

When null or undefined values represent meaningful absence of data, preserve them rather than converting to default values like empty strings, arrays, or placeholder text. Converting these values can lose semantic meaning and create unnecessary data storage or processing overhead.

For example, prefer null over string literals for unknown enum values:

// Avoid - stores unnecessary text in database
export enum IntegrationEnum {
  UNKNOWN = "unknown"
}

// Prefer - null represents true absence
export enum IntegrationEnum {
  // omit unknown case, handle with null checks
}

Similarly, when making parameters optional, let undefined flow through rather than converting to defaults:

// Avoid - loses the semantic difference between undefined and empty
let jsonData = { urls: urls || [], ...params };

// Prefer - preserves undefined semantics
let jsonData = { urls, ...params };

This approach maintains clearer data contracts and prevents ambiguity between “no data provided” and “empty data provided”.


reduce nesting levels

Minimize nested conditional statements and complex control flow by using early returns, guard clauses, and default value patterns. This improves code readability and maintainability by reducing cognitive load.

Use the or operator for default values instead of conditional checks:

# Instead of:
if modules_to_serialize is not None:
    # process modules_to_serialize
else:
    modules_to_serialize = []

# Use:
modules_to_serialize = modules_to_serialize or []

Restructure conditional logic to reduce nesting:

# Instead of:
result = dict(usage_entry2)
for k, v in usage_entry1.items():
    if isinstance(v, dict):
        if k in result:
            result[k] = self._merge_usage_entries(result[k], v)
        else:
            result[k] = dict(v) if isinstance(v, dict) else v
    else:
        result[k] = result[k] or 0
        result[k] += v if v else 0

# Use:
result = dict(usage_entry2)
for k, v in usage_entry1.items():
    current_v = result.get(k)
    if isinstance(v, dict):
        result[k] = self._merge_usage_entries(current_v, v)
    else:
        result[k] = current_v or 0
        result[k] += v if v else 0

For functions with many parameters, use multi-line formatting:

# Instead of:
def __call__(self, lm: LM, lm_kwargs: dict[str, Any], signature: Type[Signature], demos: list[dict[str, Any]], inputs: dict[str, Any]) -> list[dict[str, Any]]:

# Use:
def __call__(
    self,
    lm: LM,
    lm_kwargs: dict[str, Any],
    signature: Type[Signature],
    demos: list[dict[str, Any]],
    inputs: dict[str, Any]
) -> list[dict[str, Any]]:

validate null undefined values

Always perform explicit null and undefined checks before accessing object properties or using values in operations. Filter out undefined values from arrays and collections to prevent runtime errors and unexpected behavior.

Key practices:

Example:

// Good: Explicit null check prevents runtime errors
if (typeof value === "object" && value !== null) {
  // Safe to access properties
}

// Good: Check property existence and filter undefined values
const toolMessages = tailMessages
  .filter(msg => "tool_call_id" in msg)
  .map(msg => msg.tool_call_id)
  .filter(id => id !== undefined);

// Good: Validate before property access
if (maybeLastAssistantMessageUsage) {
  const allMatch = Object.entries(currentUsage).every(
    ([key, value]) => maybeLastAssistantMessageUsage[key] === value
  );
}

Add missing error handling

Wrap operations that can fail in try/catch blocks to prevent unhandled exceptions from crashing the application or leaving it in an inconsistent state. This is especially important for file operations, API calls, and critical initialization code.

Operations that commonly need error handling include:

Example of adding error handling to extension activation:

export async function activate(context: vscode.ExtensionContext) {
    try {
        // Extension initialization code that might fail
        await initializeExtension(context)
    } catch (error) {
        console.error("Failed to activate extension:", error)
        // Handle gracefully or show user-friendly error
    }
}

Example of adding error handling to file operations:

async function deleteTaskWithId(id: string) {
    try {
        if (id === this.cline?.taskId) {
            await this.clearTask()
        }
        // File deletion operations that can fail
        await fs.unlink(apiConversationHistoryFilePath)
        await fs.unlink(uiMessagesFilePath)
    } catch (error) {
        console.error("Error deleting task files:", error)
        // Handle cleanup or notify user
    }
}

Without proper error handling, exceptions can be lost, operations can fail silently, or the entire application can crash unexpectedly. Always consider what can go wrong and provide appropriate error handling with meaningful error messages.


Choose clear semantic names

Names should clearly and accurately convey their purpose, behavior, and content. Follow these guidelines:

  1. Use positive boolean flags: ```typescript // Bad const IGNORE_NEXT_EDIT = false; if (!IGNORE_NEXT_EDIT) { … }

// Good const IS_NEXT_EDIT_ACTIVE = true; if (IS_NEXT_EDIT_ACTIVE) { … }


2. Method names should precisely reflect their behavior:
- Use verbs that accurately describe the action
- Include plurality when handling multiple items
- Avoid ambiguous terms like "set" when "add" or "update" are more accurate

```typescript
// Bad
setDecoration(editor: Editor, ranges: Range[]) // "set" implies replacement
userId(): string // doesn't indicate it's a check

// Good
addDecorations(editor: Editor, ranges: Range[]) // clearly shows augmenting
isSignedIn(): boolean // clearly shows purpose
  1. Choose descriptive, declarative names for parameters and variables: ```typescript // Bad budget_tokens: number // unclear what the budget represents

// Good tokenBudget: number // clearly indicates purpose


This standard helps maintain code clarity, reduces confusion, and makes intentions immediately clear to other developers.

---

## Consistent terminology usage

<!-- source: browser-use/browser-use | topic: Naming Conventions | language: Python | updated: 2025-05-30 -->

Maintain consistent terminology and naming patterns throughout the codebase to avoid confusion and future conflicts. Use descriptive names that clearly indicate their purpose and remove unnecessary parameters or elements that don't serve a function.

Key principles:
- Keep consistent naming across the entire codebase, even if the underlying implementation might change
- Use semantic names that clearly describe the function or purpose (e.g., `on_step_start`/`on_step_end` instead of `before_step_func`/`after_step_func`)
- Remove unused parameters or fields that don't contribute to functionality
- Consider future extensibility when choosing terminology to avoid naming conflicts

Example from the discussions:
```python
# Good: Consistent terminology maintained across codebase
self.playwright = self.playwright or await self.playwright.chromium.connect_over_cdp(...)

# Avoid: Introducing conflicting terminology
self.driver = self.driver or await self.playwright.chromium.connect_over_cdp(...)

# Good: Descriptive parameter names
async def run(
    self,
    max_steps: int = 100,
    on_step_start: AgentHookFunc | None = None,
    on_step_end: AgentHookFunc | None = None
):

# Good: Remove unused parameters
class ExtractElementHtmlAction(BaseModel):
    index: int
    format: Literal['text', 'markdown', 'html'] = 'html'
    # xpath removed as it wasn't being used

This approach prevents terminology conflicts, improves code readability, and makes the codebase more maintainable by ensuring names accurately reflect their purpose and usage.


Chunked data processing

When processing large arrays or data structures, implement chunked processing to avoid stack size limitations and optimize performance. Break operations into manageable chunks rather than processing everything at once.

Key practices:

  1. Use appropriate chunk sizes (typically 100KB or less) when dealing with large binary data or strings
  2. Choose the right collection operation for your use case:
    • Use reduce() when accumulating or combining values across collections
    • Use map() when transforming elements without combining them
    • Consider recursion for nested structures with appropriate base cases

Example:

// Process large binary data in chunks to avoid stack overflow
async asString(): Promise<string> {
  const data = this.data ?? new Blob([]);
  const dataBuffer = await data.arrayBuffer();
  const dataArray = new Uint8Array(dataBuffer);

  // Need to handle the array in smaller chunks to deal with stack size limits
  let ret = "";
  const chunkSize = 102400;
  for (let i = 0; i < dataArray.length; i += chunkSize) {
    const chunk = dataArray.subarray(i, i + chunkSize);
    ret += String.fromCharCode(...chunk);
  }

  return ret;
}

Implementing chunked processing improves application stability by preventing stack overflows and can improve performance by managing memory more efficiently. This pattern is especially important when handling user-generated content, large API responses, or binary data operations.


validate connection timeouts

Always validate network connection states and implement explicit timeout handling to prevent zombie connections and ensure robust network operations. Connection objects can appear valid while actually being disconnected, and network operations without timeouts can hang indefinitely.

When working with browser contexts or network connections, actively verify the connection state rather than assuming validity:

# Validate browser connection state
if self.browser_context:
    try:
        _ = self.browser_context.pages
        if self.browser_context.browser and not self.browser_context.browser.is_connected():
            self.browser_context = None
    except Exception:
        self.browser_context = None

For network operations, always specify explicit timeouts with reasonable defaults:

# Add timeout parameter to network operations
await page.goto(params.url, timeout=int((params.timeout or 30)*1000))

This prevents hanging operations and provides predictable failure modes when network conditions are poor or connections are unstable.


validate file inputs

All file-related operations must implement comprehensive input validation and sanitization to prevent path traversal attacks, arbitrary file system access, and execution of malicious content. This is especially critical when handling user-provided file paths or when systems interact with AI agents that could be manipulated through prompt injection.

Key validation requirements:

Example implementation:

def validate_file_path(file_path: str, allowed_extensions: list[str]) -> str:
    # Check for dangerous directories
    dangerous_paths = ['/', '~', '~/Desktop', '~/Documents']
    if file_path in dangerous_paths:
        raise ValueError(f"Access to {file_path} is not allowed")
    
    # Extract filename and validate
    filename = Path(file_path).name
    
    # Sanitize filename
    sanitized = re.sub(r'[^a-zA-Z0-9 _-]', '_', filename)
    if len(sanitized) > 64:
        sanitized = sanitized[:64]
    
    # Check extension
    if not any(sanitized.endswith(ext) for ext in allowed_extensions):
        raise ValueError(f"File extension not allowed: {sanitized}")
    
    return sanitized

This prevents AI agents or malicious users from writing to system files, executing scripts, or accessing sensitive directories through path traversal attacks.


Avoid logging sensitive content

Be cautious about what data gets included in log messages to prevent security risks and performance issues. Before logging file contents or user data, consider whether it could contain:

Instead of logging full content, log metadata like file names, sizes, types, or character counts. Use appropriate log levels - consolidate related error information into a single error log rather than splitting across multiple log statements.

Example of what to avoid:

# Bad - logs potentially sensitive/large content
file_content = file_system.read_file(file_name)
logger.info(f'Read file contents: {file_content}')

# Bad - splits error information
logger.info("error during llm invocation")
logger.error(e)

Example of better approach:

# Good - logs metadata only
file_content = file_system.read_file(file_name)
logger.info(f'Read file {file_name} ({len(file_content)} characters)')

# Good - consolidated error logging
logger.error(f"Error during LLM invocation: {e}")

Pin dependency versions

Always pin external dependencies to specific commit hashes rather than mutable references like tags or branch names to prevent supply chain attacks. This applies to GitHub Actions, package dependencies, Docker images, and similar resources - even if they’re from your own repositories.

If a dependency repository is compromised, using mutable references makes it easier for attackers to execute lateral movement into your project. While using tags like @latest or @beta is more convenient, it introduces significant security vulnerabilities.

Example:

# Insecure - using mutable tag references
- name: Checkout repository
  uses: actions/checkout@v4

# Secure - pinning to specific commit hash
- name: Checkout repository
  uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4

Consider implementing automation to update these hashes regularly while maintaining the security benefits of pinning specific versions.


Document performance tool lifecycle

When creating performance optimization tools, especially temporary dev-only utilities, clearly document their purpose, scope, and removal criteria in the README or documentation. This helps teams make informed decisions about maintenance vs. performance benefits over time.

Include these key elements:

Example documentation:

# Translation MCP Server

**Kilocode internal dev tool only:** This is a performance optimization to reduce LLM waiting time during translation tasks. Can be deleted when maintenance burden outweighs time saved.

This approach prevents performance tools from becoming technical debt by establishing upfront expectations about their lifecycle and making it easier for future developers to evaluate whether the optimization is still worthwhile.


Validate untrusted input

Always validate and sanitize user-provided inputs before using them in sensitive contexts like SQL queries, file paths, or URL requests. This prevents SQL injection, path traversal, SSRF, and similar attacks.

For SQL queries, use parameterized queries instead of string concatenation:

// UNSAFE - vulnerable to SQL injection:
const query = `SELECT column_name FROM information_schema.columns WHERE table_name = '${tableName}'`;

// SAFE - using parameterized queries:
const query = `SELECT column_name FROM information_schema.columns WHERE table_name = ?`;
await connection.execute(query, [tableName]);

For file paths, validate against directory traversal attempts:

// Validate that paths don't try to escape the intended directory
if (path.includes('..') || path.startsWith('/') || path.includes('\\')) {
  throw new Error("Invalid path: directory traversal attempt detected");
}

For URL requests, implement validation and consider using allowlists:

function isValidUrl(url: string): boolean {
  try {
    const parsedUrl = new URL(url);
    // Check against allowlist of domains or protocols
    return ['https:'].includes(parsedUrl.protocol) && 
           ALLOWED_DOMAINS.includes(parsedUrl.hostname);
  } catch {
    return false;
  }
}

if (!isValidUrl(userProvidedUrl)) {
  throw new Error("Invalid or disallowed URL");
}

When developing API endpoints or libraries, clearly document in JSDoc comments which parameters must come from trusted sources and cannot accept direct user input.


Standardize model access

When integrating AI models into applications, provide consistent configuration methods that support different access patterns (direct API, chat interfaces, or intermediary services like LiteLLM).

Key practices:

  1. Support environment variables for flexible configuration (e.g., LITELLM_BASE_URL, OPENAI_API_KEY)
  2. Handle both local and remote model access scenarios
  3. Account for behavioral differences between chat and API modes of the same model
  4. Use clear prefixing for different interaction modes

Example:

def create_model(model_name, **kwargs):
    # Support prefix-based mode selection
    COPY_PASTE_PREFIX = "cp:"
    copy_paste_mode = model_name.startswith(COPY_PASTE_PREFIX)
    if copy_paste_mode:
        model_name = model_name.removeprefix(COPY_PASTE_PREFIX)
    
    # Support environment variables for configuration
    base_url = os.environ.get("MODEL_API_BASE_URL")
    api_key = os.environ.get("MODEL_API_KEY")
    
    # Create appropriate client based on configuration
    if base_url:
        client = RemoteModelClient(base_url, api_key, model_name)
    else:
        client = LocalModelClient(model_name)
        
    return client

This standardized approach improves maintainability when supporting multiple AI backends and simplifies switching between different deployment configurations.


TypeScript naming standards

Follow consistent naming conventions in TypeScript to improve code clarity, type safety, and developer experience:

  1. Capitalize types and interfaces: All type and interface names should start with an uppercase letter.
    // Incorrect
    type chainTypeName = "stuff" | "map_reduce";
       
    // Correct
    type ChainTypeName = "stuff" | "map_reduce";
    
  2. Use unknown instead of any: When the type is truly not known, prefer unknown over any for better type safety.
    // Incorrect - too permissive
    function isBuiltinTool(tool: any)
       
    // Correct - safer typing
    function isBuiltinTool(tool: unknown)
    
  3. Prefer type literals over strings for constrained values to improve developer experience and catch errors at compile time.
    // Incorrect
    function createLoader(mode: string)
       
    // Correct
    type SearchMode = "subreddit" | "username";
    function createLoader(mode: SearchMode)
    
  4. Use visibility modifiers instead of naming conventions for private/protected members:
    // Incorrect
    class GraphQLClientTool {
      _endpoint: string;
    }
       
    // Correct
    class GraphQLClientTool {
      private endpoint: string;
    }
    
  5. Standardize parameter naming across similar components (e.g., use model instead of modelName for consistency):
    // Standardized
    interface EmbeddingsParams {
      model: string;  // Not modelName
    }
    
  6. Improve type precision when appropriate to enhance developer experience:
    // Less precise
    loaders: { [extension: string]: (path: string) => Loader }
       
    // More precise
    loaders: { [extension: `.${string}`]: (path: string) => Loader }
    

Eliminate redundant code

Simplify code by eliminating redundancy and unnecessary complexity. This improves readability, reduces potential bugs, and makes the codebase easier to maintain.

Some key practices to follow:

  1. Avoid unnecessary object creation: Don’t create objects that might be discarded immediately. ```typescript // Instead of this: let requestOptions: RequestOptions | undefined = { …(config?.timeout ? { timeout: config.timeout } : {}), …(config?.signal ? { signal: config.signal } : {}), };

if (Object.keys(requestOptions).length === 0) { requestOptions = undefined; }

// Do this:
const requestOptions: RequestOptions | undefined = config?.timeout || config?.signal
? { timeout: config.timeout, signal: config.signal }
undefined; ```
  1. Remove redundant await in returns: In async functions, avoid using await when returning a promise. ```typescript // Instead of this: async function getData() { return await fetchData(); }

// Do this: async function getData() { return fetchData(); }


3. **Use concise array methods**: Many array methods have default parameters you can omit.
```typescript
// Instead of this:
return embeddings.flat(1);

// Do this:
return embeddings.flat();
  1. Don’t declare class properties only used in constructors: If a property is only accessed inside the class constructor, it doesn’t need to be a class property. ```typescript // Instead of this: class MyClass { json = false;

constructor() { if (this.json) { // do something } } }

// Do this: class MyClass { constructor() { const json = false; if (json) { // do something } } }


Eliminating redundancy leads to cleaner, more maintainable code that's easier to review and less prone to errors.

---

## Configuration file consistency

<!-- source: lobehub/lobe-chat | topic: Configurations | language: Yaml | updated: 2025-05-26 -->


Ensure configuration values are consistent and properly coordinated across all related files (docker-compose, .env files, initialization scripts, workflows, etc.). Verify that port mappings, environment variables, and tokens don't conflict between files, and provide fallback configurations for critical settings.

Key practices:
- Cross-reference port assignments between docker-compose and .env files to prevent conflicts
- When adding new environment variables, update all relevant files (.env.example, init scripts, docker-compose)
- Provide fallback tokens/credentials (e.g., use GITHUB_TOKEN as fallback when PAT is not available)
- Test configuration changes locally to catch startup issues early

Example from discussions:
```yaml
# Bad: Port conflict
ports:
  - '8000:8000'  # Conflicts with CASDOOR_PORT=8000 in .env

# Good: Use environment variable consistently
ports:
  - '${CASDOOR_PORT}:${CASDOOR_PORT}'
# Bad: No fallback
target_repo_token: ${{ secrets.PAT_FOR_SYNC }}

# Good: Provide fallback
target_repo_token: ${{ secrets.PAT_FOR_SYNC || secrets.GITHUB_TOKEN }}

Match configuration documentation

Configuration documentation must accurately reflect implementation details and behavior. Ensure that:

  1. Code examples in documentation use the exact same property names and structure as the actual implementation
  2. Configuration option descriptions explain all behavioral implications, including exceptions and special cases

Example - Incorrect:

const client = new MultiServerMCPClient({
  mcpServers: {
    'data-processor': {
      command: 'python',
      args: ['data_server.py']
    }
  }
});

Example - Correct:

const client = new MultiServerMCPClient({
  'data-processor': {
    command: 'python',
    args: ['data_server.py']
  }
});

When documenting configuration flags like useStandardContentBlocks, also include special case behavior (e.g., “audio content always uses standard content blocks regardless of this setting”).


Documentation completeness check

Ensure all documentation is complete, well-formatted, and maximally useful for developers. This includes:

  1. Use proper markdown syntax for headings, lists, code blocks, and other formatting elements to ensure documents render correctly.
# Main Heading
## Subheading
- Bullet point
- Another bullet point

## Code Example
```typescript
const example = "properly formatted";
  1. Include external reference links to relevant resources when mentioning libraries, tools, or APIs so users can easily access additional information.
Install the [Oracle JavaScript client driver](https://node-oracledb.readthedocs.io/en/latest/) to get started:

```npm install oracledb```
  1. Document all parameters completely in API references and configuration tables, even those inherited from parent interfaces or less commonly used options.
| Parameter | Type | Default | Description |
| --------- | ---- | ------- | ----------- |
| `timeout` | number | 60000 | Timeout in milliseconds for the tool call |
| `signal`  | AbortSignal | `undefined` | Optional AbortSignal to cancel the tool call |

Complete documentation improves developer experience, reduces questions, and facilitates faster onboarding.


Functional code examples

Ensure all code examples in documentation are complete, accurate, and ready to run without modification. Since developers frequently copy and paste examples directly into their projects, include all required parameters and follow consistent patterns.

For example, when demonstrating object creation:

# Correct example with all required parameters
research_task = Task(
    description="Research the latest AI developments",
    expected_output="",  # Include mandatory parameters even if empty
    agent=researcher
)

Documentation structure should maintain consistent patterns across sections, explicitly listing required methods and parameters. This helps developers implement interfaces correctly and reduces the time spent debugging issues caused by incomplete examples.


Explicit configuration validation

Avoid using configuration values as implicit feature flags or logic triggers. Instead, validate configuration explicitly and make behavior predictable.

Configuration values should not be used to implicitly detect features or modes of operation, as this leads to false positives/negatives and confusing behavior. When configuration is required, validate it explicitly and fail fast with clear error messages.

Problems to avoid:

Better approach:

# Instead of implicit detection
if self.config.per_instance_cost_limit == 0 and self.config.total_cost_limit == 0:
    # Local model logic

# Use explicit configuration
if self.config.model_type == "local":
    # Local model logic

# Validate required configuration explicitly
if self.args.model_name.startswith("deepseek"):
    api_base_url = keys_config.get("DEEPSEEK_API_BASE_URL")
    if not api_base_url:
        raise ValueError("DEEPSEEK_API_BASE_URL must be specified for DeepSeek models")

Make configuration behavior predictable by validating requirements upfront and using explicit flags rather than inferring behavior from side effects of other configuration values.


Use database-native types

Always leverage database-native data types and appropriate schema design to maximize performance and query capabilities. This includes:

  1. Use database-specific type bindings when available instead of generic formats:
    // Instead of:
    pref: JSON.stringify(this.pref)
       
    // Prefer:
    pref: { val: JSON.stringify(this.pref), type: oracledb.DB_TYPE_JSON }
    
  2. For vector stores or cross-platform storage, use serialization-friendly formats for complex types:
    // Instead of storing Date objects directly
    doc.metadata.date = new Date()
       
    // Store as ISO string for better compatibility
    doc.metadata.date = new Date().toISOString()
    
  3. In relational databases, prefer specific typed columns over generic JSON fields for data that will be frequently filtered or sorted:
    // Better schema design with specific columns for important fields
    await engine.pool.raw(`CREATE TABLE ${schemaName}.${tableName}(
      id UUID PRIMARY KEY,
      content TEXT NOT NULL,
      created_date TIMESTAMP NOT NULL,
      category VARCHAR(50) NOT NULL,
      metadata JSON  // Only for truly variable/unstructured data
    )`);
    

This approach enables more efficient querying, better indexing capabilities, type validation at the database level, and allows you to leverage database-specific optimizations. Creating typed fields instead of dictionary-style complex types provides better type fidelity and enables richer filtering expressions like numeric/date range comparisons.


Ensure semantic naming clarity

Names should clearly communicate their actual behavior and preserve sufficient context for meaningful identification. For functions with conditional behavior, use descriptive suffixes like _if_needed or _maybe to indicate optionality. For paths and identifiers, maintain enough context to ensure usability - avoid over-shortening that removes essential information.

Examples:

This ensures that names serve as clear documentation of intent and maintain practical usability for developers and tools.


validate LLM reliability

Always validate LLM capabilities before deployment and implement robust handling for unreliable responses. LLMs can vary significantly in capability and may return empty, invalid, or hallucinated responses that can break your application.

Implement capability testing with realistic prompts that match your actual usage patterns. Use simple knowledge tests to establish a minimum intelligence bar and filter out low-power models that struggle with basic instructions.

def _test_tool_calling_method(self, method: str) -> bool:
    """Test if a specific tool calling method works with the current LLM."""
    try:
        # Test with realistic prompt matching actual usage
        test_message = HumanMessage(content='What is the capital of France? Respond with valid JSON.')
        
        if method == 'raw':
            response = self.llm.invoke([test_message])
            # Validate both response format and basic intelligence
            if not response or 'Paris' not in response.content:
                return False
        
        return True
    except Exception:
        return False

Always validate LLM outputs against original inputs to detect hallucination, and implement retry logic with fallback actions for empty or invalid responses:

if not model_output.action or all(action.model_dump() == {} for action in model_output.action):
    logger.warning('Model returned empty action. Retrying...')
    retry_messages = input_messages + [clarification_message]
    model_output = await self.get_next_action(retry_messages)
    
    if not model_output.action:
        # Safe fallback action
        action_instance = self.ActionModel(done={
            'success': False,
            'text': 'No next action returned by LLM!',
        })

This approach significantly reduces support load from broken or low-capability models while ensuring your application remains functional even when LLMs behave unpredictably.


avoid unnecessary custom hooks

Before creating custom hooks, evaluate whether existing solutions or simpler patterns can address the need. Custom hooks should provide clear value beyond what’s available through established libraries, built-in React patterns, or direct component logic.

Ask these questions when reviewing custom hook implementations:

  1. Does this hook abstract meaningful logic or just wrap existing functionality?
  2. Are there established libraries (like react-use) that already provide this functionality?
  3. Would direct usage of existing hooks or patterns be clearer?

For example, instead of creating a custom useClickOutside hook, leverage existing solutions:

// Avoid: Custom implementation
export function useClickOutside<T extends HTMLElement = HTMLElement>(
  ref: RefObject<T>,
  callback: () => void
) {
  // Custom click outside logic...
}

// Prefer: Existing library solution
import { useClickAway } from 'react-use';

// Use directly in component
useClickAway(ref, callback);

Custom hooks are valuable for encapsulating complex stateful logic, but avoid creating them when they merely wrap existing functionality without adding meaningful abstraction or reusability.


Handle AI provider inconsistencies

When integrating with AI model providers, implement defensive programming to handle API inconsistencies, bugs, and unexpected return types. AI provider libraries often have implementation bugs or return different types than documented, requiring robust error handling and type checking.

Key practices:

Example from LiteLLM tokenizer bug workaround:

def count_tokens(text: str) -> int:
    enc = tokenizer_json["tokenizer"].encode(text)
    if isinstance(enc, list):
        return len(enc)
    elif hasattr(enc, "ids"):
        return len(enc.ids)
    else:
        raise TypeError(f"Unexpected return type from encode: {type(enc)}")

This approach ensures your AI model integrations remain robust even when underlying provider APIs have bugs or inconsistent behavior.


Prefer nullish coalescing

When handling null or undefined values, use modern JavaScript patterns to write more robust and maintainable code:

  1. Use the nullish coalescing operator (??) instead of logical OR (||) for defaults: ```javascript // Good: Only falls back when value is null or undefined this.endpointUrl = fields.endpointUrl ?? getEnvironmentVariable(“AZUREML_URL”);

// Avoid: Will also replace empty strings, 0, and false this.endpointUrl = fields.endpointUrl || getEnvironmentVariable(“AZUREML_URL”);


2. Conditionally include properties in objects only when they exist:
```javascript
// Good: Only adds the property when content exists
const options = {
  ...otherOptions,
  ...(message.content != null ? { content: formatContent(message.content) } : {})
};

// Avoid: Passing undefined values to APIs
const options = {
  ...otherOptions,
  audio: this.audio // might be undefined
};
  1. Use strict equality (===, !==) for null checks:
    // Good: Clear intent, checks for both null and undefined
    if (documents === null || documents === undefined) {
      // Handle the case
    }
    // Or more concisely:
    if (documents == null) {
      // Handle the case
    }
    
  2. Thoroughly check combinations of conditions when handling nullable values: ```javascript // Good: Raises an error only when both client and credentials are missing if (!config.client && (!endpoint || !key)) { throw new Error(“Missing required configuration”); }

// Avoid: Oversimplified check if (!config.client && !endpoint && !key) { // This will only throw if ALL are missing }


These patterns help prevent subtle bugs and make your code's intent clearer to other developers.

---

## Avoid hard-coded configuration

<!-- source: openai/codex | topic: Configurations | language: Shell | updated: 2025-05-16 -->

Make scripts and applications flexible by avoiding hard-coded configuration values. Instead, allow users to provide configuration through command-line flags, environment variables, or configuration files. When updating scripts to use configurable parameters:

1. Prefer explicit flag-based interfaces over positional arguments
2. Use descriptive names for flags, especially those with security implications (e.g., `--dangerously-allow-network-outbound`)
3. Validate configuration values before use to prevent errors
4. Maintain backward compatibility when possible
5. Include helpful usage documentation

Example:
```bash
#!/usr/bin/env bash
# Parse optional flags with descriptive names
while [ "$#" -gt 0 ]; do
  case "$1" in
    --dangerously-allow-network-outbound)
      ALLOW_OUTBOUND=true
      shift
      ;;
    --work_dir)
      if [ -z "$2" ]; then
        echo "Error: --work_dir flag provided but no directory specified."
        exit 1
      fi
      WORK_DIR="$2"
      shift 2
      ;;
    -h|--help)
      echo "Usage: $(basename "$0") [--dangerously-allow-network-outbound] [--work_dir directory]"
      exit 0
      ;;
    *)
      # Handle other arguments or commands
      break
      ;;
  esac
done

# Validate environment variables before use
if [ -z "$ALLOWED_DOMAINS" ]; then
  echo "Error: ALLOWED_DOMAINS is empty."
  exit 1
fi

Explicit environment declarations

Always explicitly declare environment variables in configuration files, even when they have default values. Use consistent naming conventions with appropriate prefixes for related variables, and clearly document when each variable is required versus optional.

This practice prevents configuration confusion and makes deployment requirements transparent. For example, instead of relying on implicit defaults, explicitly set values like NEXT_PUBLIC_ENABLE_NEXT_AUTH=0 in environment files. Use consistent prefixes such as AUTH_ for authentication-related variables, and provide clear documentation about when variables are needed (e.g., “necessary for self-hosting with Docker” vs “optional for most users”).

# Good: Explicit declaration with clear naming
NEXT_PUBLIC_ENABLE_NEXT_AUTH=0
AUTH_GITHUB_CLIENT_ID=your_client_id
AUTH_GITHUB_CLIENT_SECRET=your_secret

# Bad: Missing explicit declaration, inconsistent naming
# NEXT_PUBLIC_ENABLE_NEXT_AUTH (relies on default)
GITHUB_CLIENT_ID=your_client_id  # Missing AUTH_ prefix

Document each variable’s purpose and requirements in configuration guides, using callouts or tables to indicate when specific variables are mandatory for different deployment scenarios.


implement algorithms correctly

Ensure algorithmic implementations use correct patterns, handle edge cases gracefully, and avoid silent failures. This includes using proper mathematical functions, correct object access methods, and robust error handling for each operation.

Key principles:

  1. Use correct mathematical functions: Choose appropriate functions like np.log2() instead of np.log() when the algorithm specifically requires base-2 logarithms
  2. Handle edge cases per-item: Implement try/catch logic for individual items rather than wrapping entire operations to prevent silent corruption
  3. Use proper access patterns: For enums, use Status(value) for value-based lookup instead of Status[value] which expects names
  4. Check for required attributes: Verify object attributes exist before accessing them, especially for dynamic types

Example of robust per-item processing:

def _copy_tools(self, tools):
    copied_tools = []
    for tool in tools:
        try:
            copied_tools.append(copy.deepcopy(tool))
        except Exception as e:
            logger.warning(f"Could not deep copy tool {tool}, using shallow copy: {e}")
            copied_tools.append(copy.copy(tool))
    return copied_tools

Example of correct enum handling:

# Correct: restore enum from value
parsed_value = Status(value)  # where value is "in_progress"

# Incorrect: lookup by name when you have value
parsed_value = Status[value]  # throws KeyError

This approach prevents algorithmic errors that can lead to silent failures, incorrect results, or runtime exceptions in production code.


Use structured logging consistently

Always use the established logging framework instead of console.log or ad-hoc logging approaches. This ensures consistent log formatting, proper log levels, and better log management across the application.

When logging errors, include contextual information like error traces, messages, and auxiliary data to make logs more informative for debugging. For components that need logging capabilities, inherit or inject the logger from the main application rather than creating separate logging mechanisms.

Example of what to avoid:

console.log(options.messages);
console.log(tree);

Example of proper structured logging:

this.logger({
  category: "debug",
  message: "Processing options messages",
  auxiliary: { messageCount: options.messages.length }
});

this.stagehandLogger.error(
  "The browser context is undefined. This means the CDP connection to the browser failed"
);

This approach provides better log filtering, formatting, and integration with log management systems while maintaining consistency across the codebase.


avoid silent failures

Always provide clear feedback when operations fail, even when continuing with fallbacks or alternative approaches. Silent failures make debugging extremely difficult and can lead to unexpected behavior in production systems.

Key practices:

  1. Optional dependencies: Wrap imports in try-except blocks but defer the error until actual usage, not at module level
  2. Operation failures: Log warnings or raise informative exceptions instead of silently continuing
  3. Fallback scenarios: When falling back to alternative approaches, log the reason for the fallback
  4. Parsing errors: Provide specific error messages rather than generic exception handling

Example of proper optional dependency handling:

# Good - defer error until usage
try:
    import optional_library
except ImportError:
    optional_library = None

def use_optional_feature():
    if optional_library is None:
        raise ImportError("optional_library is required for this feature. Install with: pip install optional_library")
    return optional_library.do_something()

# Bad - fails at import time
import optional_library  # This breaks if not installed

Example of proper fallback with feedback:

# Good - inform about fallback
try:
    result = primary_operation()
except SpecificError as e:
    logger.warning(f"Primary operation failed: {e}. Falling back to alternative.")
    result = fallback_operation()

# Bad - silent fallback
try:
    result = primary_operation()
except:
    result = fallback_operation()  # No indication why fallback was used

This approach ensures that failures are visible to developers and operators, making systems more maintainable and debuggable.


Pin external action dependencies

Use full commit hashes instead of version tags when referencing third-party GitHub Actions in workflows to prevent unexpected behavior changes if the action is modified at its source. This ensures reproducible builds and improves security by protecting against supply chain attacks.

For GitHub’s own first-party actions, using semantic versioning tags (like @v4) is acceptable since they are widely used and well-maintained, making it easier to identify canonical versions.

Example:

steps:
  # Third-party actions: Use full commit hash
  - name: Annotate locations with typos
    uses: codespell-project/codespell-problem-matcher@a8ce06949d771ee07807e8ce2c9b873f906a9fc2 # v1
  - name: Codespell
    uses: codespell-project/actions-codespell@94e0a8e0b7e2a42a1e1223cc80b4c150a38a0e1e # v2
    
  # GitHub first-party actions: Semantic versioning is acceptable
  - name: Checkout
    uses: actions/checkout@v4

This practice helps ensure that your CI/CD pipelines remain stable and secure over time, and allows for explicit updating of dependencies when desired rather than automatically adopting potentially breaking changes.


Secure CI/CD pipelines

Implement strict security controls in continuous integration and deployment workflows:

  1. Pin external GitHub Actions to immutable commit hashes rather than mutable tags: ```yaml

    Instead of this (vulnerable to supply chain attacks):

    • uses: codespell-project/codespell-problem-matcher@v1

    Use this (pinned to specific commit):

    • uses: codespell-project/codespell-problem-matcher@e8fc5c5c5e6c5c5c5c5c5c5c5c5c5c5c5c5c5c5c ```
  2. Isolate workflows requiring elevated permissions into separate files for clearer security boundaries:
    # Separate high-privilege workflows (e.g., update-nix-hash.yml) from regular CI workflows
    permissions:
      contents: write  # Clearly visible elevated permission
    
  3. Apply the principle of least privilege by:
    • Only granting write permissions where strictly necessary
    • Using conditional execution to limit when privileged jobs run (e.g., if: github.event_name == 'push' && github.ref == 'refs/heads/main')
  4. Thoroughly review scripts running with elevated permissions to protect against:
    • Secret leakage
    • Unintended commits or changes
    • Input injection vulnerabilities

Implementing these practices prevents supply chain attacks and reduces the risk of compromised workflows affecting your repository.


Pin testing dependency versions

Always specify explicit versions for testing frameworks and tools to ensure reproducible test environments across different deployment contexts. Avoid installing testing dependencies with implicit “latest” versions, which can lead to inconsistent test behavior and difficult-to-debug failures.

Use environment variables or extract versions from dependency manifests rather than hard-coding versions directly in installation commands:

# Option 1: Using environment variables
RUN pip install playwright==$PLAYWRIGHT_VERSION

# Option 2: Extract from dependency manifest
RUN PLAYWRIGHT_VERSION=$(grep -oP 'playwright>=\K[0-9.]+' pyproject.toml) \
    && pip install playwright==$PLAYWRIGHT_VERSION

This practice is especially critical in containerized environments where test dependencies need to remain consistent across development, CI/CD, and production testing scenarios. Version pinning prevents unexpected test failures caused by breaking changes in testing framework updates and ensures that test results are reproducible across different environments and time periods.


isolate mock configurations

When using Vitest mocking, avoid multiple vi.mock calls for the same module within a single test file, as mock calls are hoisted and can interfere with each other. Instead, organize tests requiring different mock configurations into separate test files or test suites with proper setup/teardown.

The issue arises because vi.mock calls are hoisted to the top of the file, making it impossible to have different mock implementations for different test scenarios in the same file. This can cause tests to break unexpectedly when mock configurations conflict.

Problematic approach:

// This won't work as expected - both mocks target the same module
vi.mock("../../../context/ExtensionStateContext", () => ({
  useExtensionState: vi.fn(() => ({ apiProvider: "openai" }))
}))

vi.mock("../../../context/ExtensionStateContext", () => ({
  useExtensionState: vi.fn(() => ({ apiProvider: "nebius" }))
}))

Better approach:

This ensures test isolation and prevents one test’s mock configuration from breaking others.


Test before documenting

Always thoroughly test API features and endpoints before documenting them, especially when integrating with third-party services. Documentation should accurately reflect the actual behavior of the API, including:

For error documentation, focus on specific causes rather than general descriptions:

// DON'T: Use vague descriptions
// "APICallError occurs when there's an issue during an API call"

// DO: Be specific about error causes
// "APICallError occurs when a provider API returns an error response,
// typically due to invalid message structure. Always check the provider's
// error message for specific resolution steps."

For third-party integrations, test thoroughly and document any limitations:

// Example: Adding appropriate warnings for feature limitations
if (isGoogleProvider && options.includeThoughts) {
  console.warn('includeThoughts is not fully supported in all Google Generative AI models.');
}

For code examples, ensure they are practical and executable:

// DON'T: Use abstract placeholders without explanation
const { transcript } = await generateTranscript({
  model: openai.transcription('whisper-1'),
  audio: audioData, // What is audioData?
});

// DO: Provide complete, executable examples
import fs from 'fs/promises';

const audioData = await fs.readFile('./sample-audio.mp3');
const { transcript } = await generateTranscript({
  model: openai.transcription('whisper-1'),
  audio: audioData,
});

This standard ensures that developers can rely on your documentation to accurately understand how to use your API properly, reducing confusion and support issues.


optimize Docker layers

Avoid unnecessary duplication and bloat in Docker layers by trusting base images to provide standard tools and using appropriate installation methods. Instead of upgrading pip when the base image already provides it, trust the image’s version to prevent duplicate copies across layers. When installing application code, use editable installs to avoid creating duplicate copies of the codebase in different layers.

Example of problematic approach:

RUN pip install --upgrade pip \
    && pip install .

Preferred approach:

# Trust base image pip version, use editable install
RUN pip install -e .

This reduces image size, build time, and layer complexity while maintaining the same functionality. Apply this principle to other tools and dependencies - only install what’s not already provided by the base image.


Fail securely by default

When designing systems that handle sensitive operations, always default to the most secure behavior rather than prioritizing convenience. This practice applies to error handling, execution environments, and security-critical fallbacks.

Key principles to follow:

  1. Sanitize error responses: Never expose internal exception details or stack traces in API responses that could reveal implementation details to potential attackers.

  2. Require explicit opt-in for reduced security: Don’t silently fall back to less secure modes of operation; require explicit configuration through environment variables or parameters.

  3. Log security-relevant decisions: Ensure security-related fallbacks are clearly logged for monitoring and debugging.

Example of insecure error handling:

except Exception as e:
    return JSONResponse(
        content=JSONRPCResponse(
            id=request_id,
            error=InternalError(data=str(e)),  # Exposes potentially sensitive details
        ),
        status_code=500,
    )

Secure implementation:

except Exception as e:
    # Log complete details for internal use
    self.logger.exception(f"Error handling {method} request")
    # Return sanitized response to external users
    return JSONResponse(
        content=JSONRPCResponse(
            id=request_id,
            error=InternalError(data="An internal server error occurred"),
        ),
        status_code=500,
    )

Example of insecure fallback:

unsafe_mode = not self.check_docker_available()
# Silently proceeds with unsafe execution

Secure implementation:

if not self.check_docker_available():
    if os.getenv("CREWAI_GUARDRAIL_EXECUTION_MODE") == "allow_unsafe":
        self.logger.warning("Docker unavailable. Falling back to unsafe execution mode.")
        self.unsafe_mode = True
    else:
        raise SecurityError("Cannot execute code safely. Docker unavailable and unsafe execution not explicitly enabled.")

Consistent AI interfaces

Maintain consistent naming patterns and parameter structures across AI provider implementations. This makes the SDK more intuitive and reduces developer friction when switching between different AI models or providers.

Key practices:

Example:

// Preferred approach
const { response } = await embed({
  providerOptions: {
    // Provider-specific options here
  }
});

// Instead of
const { rawResponse } = await embed({
  // Mixing provider-specific options at the top level
});

When adding examples for AI providers, always verify that model identifiers are valid for the specific provider (e.g., using ‘scribe_v1’ for ElevenLabs transcription models rather than invalid identifiers).


Workspace version configuration

Standardize version management across multi-crate Rust projects by using workspace versioning. This reduces duplication and ensures consistency across all crates in your project.

Implementation:

  1. Define the version once in the workspace Cargo.toml:
    [workspace]
    version = "0.1.0"
    
  2. Reference this version in each crate’s Cargo.toml:
    [package]
    name = "your-crate-name"
    version = { workspace = true }
    

This approach centralizes version management, making it easier to release coordinated updates across all crates while maintaining a consistent configuration structure.


prefer authentication tokens

When configuring authentication in CI/CD workflows, prefer using tokens over passwords for enhanced security. Tokens can be scoped with specific permissions, rotated more easily, and provide better audit trails compared to passwords. This is particularly important for service-to-service authentication where credentials are stored as secrets.

For Docker Hub authentication in GitHub Actions, use a personal access token instead of your account password:

- name: Log in to Docker Hub
  uses: docker/login-action@v3
  with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_TOKEN }}  # Use token instead of password

Even when official documentation shows password usage, prioritize token-based authentication as it follows security best practices and reduces the risk of credential compromise.


optimize CI performance

Structure CI workflows to minimize execution time and resource usage through strategic job organization, caching, and elimination of redundant operations.

Key optimization strategies:

Example of optimized job structure:

jobs:
  # Fast parallel checks (each ~20sec)
  syntax-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6
      - run: uv run ruff check --no-fix --select PLE
  
  format-check:
    runs-on: ubuntu-latest  
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6
      - run: uv run ruff format
      - run: uv run pre-commit run --all-files
      
  type-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6  
      - run: uv run pyright

  # Build once, test across matrix
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6
      - run: uv build
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/
          
  test-import:
    needs: build
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ["3.11", "3.12", "3.13"]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/
      - run: python -c "import browser_use; print('Success!')"

This approach reduces total CI time from sequential execution to parallel execution, with all checks completing in under 30 seconds instead of several minutes.


Layer documentation by complexity

Structure documentation to be approachable for beginners while remaining comprehensive for all users. Keep main pages focused on common use cases with simplified examples, and move advanced configurations to separate, linked sections. When documenting features, start with basic usage before detailing exceptions or edge cases.

For example, instead of including complex configuration options in introductory documentation:

{
  "embeddingsProvider": {
    "provider": "ollama",
    "embeddingPrefixes": [
      // complex configuration...
    ]
  }
}

Present a simpler initial example:

{
  "embeddingsProvider": {
    "provider": "ollama",
    "model": "nomic-embed-text"
  }
}

With a clear link to advanced configuration options for users who need them. This progressive disclosure approach ensures new users aren’t overwhelmed while giving experienced users access to the depth they need.


Make test descriptions specific

Test scenarios and steps should use specific, descriptive language that clearly communicates what is being tested and what behavior is expected. Avoid vague or ambiguous terms that leave room for interpretation.

When writing test scenarios, use descriptive names that specify the exact conditions and expected outcomes rather than generic phrases. For test steps, explicitly define all inputs and conditions rather than using undefined references.

Examples of improvements:

This ensures that anyone reading the tests can understand exactly what scenario is being tested without having to make assumptions about undefined or vague references.


Strategic telemetry implementation

Implement telemetry collection strategically to ensure system reliability and meaningful data capture. Place telemetry calls where relevant context is available, use non-blocking patterns for time-sensitive operations, and avoid unnecessary abstraction.

Key principles:

  1. Non-blocking in critical paths: Use fire-and-forget patterns or periodic collection for operations with strict time limits
  2. Context-aware placement: Capture metrics where you have access to the relevant data and user actions
  3. Avoid over-engineering: Don’t create unnecessary abstractions for single-use telemetry calls
  4. Be intentional: Focus on metrics that provide actionable insights about feature usage and error rates

Example implementation:

// Good: Periodic collection with non-blocking pattern
const thirtyMinutes = 30 * 60 * 1000
telemetryIntervalId = setInterval(() => {
    // Fire-and-forget, log potential errors but don't block
    void telemetryService.sendCollectedEvents().catch((error) => {
        Logger.error("Error sending periodic telemetry:", error)
    })
}, thirtyMinutes)

// Good: Capture at the point where context is available
const options = parsePartialArrayString(optionsRaw || "[]")
this.lastOptionsCount = options.length

// Good: Direct usage instead of unnecessary abstraction
telemetryService.captureTaskRestarted(this.taskId, apiConfiguration.apiProvider)

avoid interactive authentication automation

When building scripts or applications that require user authentication, avoid automating interactive authentication processes that could cause system instability or security issues. Instead, check authentication status programmatically and delegate the actual authentication to the user.

Interactive authentication commands (like login flows) can cause console freezing, unpredictable behavior, or security vulnerabilities when executed programmatically. The safer approach is to verify authentication status and provide clear instructions for users to authenticate themselves.

Example implementation:

const checkGitHubAuth = async () => {
	try {
		execSync("gh auth status", { stdio: "ignore" })
		return true
	} catch (err) {
		console.log("\nGitHub authentication required.")
		console.log("\nPlease run the following command in your terminal to authenticate:")
		console.log("\n  gh auth login\n")
		return false
	}
}

This approach maintains security boundaries, prevents system issues, and ensures users maintain control over their authentication credentials while still enabling automated workflows to function properly.


Consistent provider options

When designing APIs that support multiple providers or service integrations, implement consistent patterns for handling provider-specific options. This includes proper validation, separation of request vs. non-request options, and clear type definitions.

Key practices:

  1. Use schema validation for provider options before sending requests
  2. Extract non-request options that shouldn’t be sent to external APIs
  3. Maintain consistent naming patterns across providers
  4. Provide comprehensive type definitions with JSDoc comments
// Good practice: Extract non-request options before API calls
const { pollIntervalMillis, maxPollAttempts, ...providerRequestOptions } = 
  providerOptions.luma ?? {};
  
// Good practice: Use standardized validation
const openaiOptions = parseProviderOptions({
  provider: 'openai',
  providerOptions,
  schema: openaiProviderOptionsSchema,
});

// Good practice: Well-documented provider option types
export type GladiaTranscriptionInitiateAPITypes = {
  /** URL to a Gladia file or to an external audio or video file */
  audio_url: string;
  /** [Alpha] Context to feed the transcription model with for better accuracy */
  context_prompt?: string;
  // Additional well-documented parameters...
};

This approach ensures type safety, prevents sending unnecessary options to external APIs, and makes your code more maintainable as you add support for new providers or update existing integrations.


API parameter consolidation

When designing API functions with multiple parameters, consolidate optional or related parameters into a single options object to improve extensibility and maintainability. This pattern prevents function signatures from becoming unwieldy and allows for easier future parameter additions without breaking changes.

Key principles:

Example of good parameter consolidation:

// Before: Multiple separate parameters
export const QwenAIStream = (
  stream: Stream<OpenAI.ChatCompletionChunk>,
  callbacks?: ChatStreamCallbacks,
  inputStartAt?: number,
)

// After: Consolidated into options object
export const QwenAIStream = (
  stream: Stream<OpenAI.ChatCompletionChunk>,
  options?: {
    callbacks?: ChatStreamCallbacks;
    inputStartAt?: number;
  }
)

Example of using utility functions:

// Before: Manual URL construction
const avatarUrl = fileEnv.S3_PUBLIC_DOMAIN + '/' + filePath;

// After: Using utility function
const avatarUrl = await ctx.fileService.getFullFileUrl(filePath);

// Before: Manual URL joining
endpointUrl: instance.baseURL + '/' + payload.model

// After: Using urlJoin utility
endpointUrl: urlJoin(instance.baseURL, payload.model)

This approach makes APIs more maintainable, reduces the likelihood of bugs from manual implementations, and provides a clear upgrade path for future enhancements.


Leverage style tools

Maintain consistent code style by using and respecting the project’s established formatting tools and patterns. Run linters and formatters (pnpm run format, pnpm run lint) before committing code. Organize logical expressions for clarity and consistency, and prefer language constructs that work well with static analysis tools.

For example, maintain symmetry in related conditional blocks:

// GOOD: Organize conditions symmetrically and logically
if (
  (key["meta"] || key["ctrl"] || key["alt"]) &&
  (key["backspace"] || input === "\x7f") &&
  !key["shift"]
) {
  this.deleteWordLeft();
}

// AVOID: Asymmetrical or nested conditions that are harder to parse
if (
  (key["meta"] || key["ctrl"] || key["alt"]) &&
  (key["backspace"] || input === "\x7f" || (key["delete"] && !key["shift"]))
) {
  this.deleteWordLeft();
}

Use language constructs that leverage static analysis, like switch statements for exhaustive checking of enum values, even when it might seem easier to convert to if/else statements. This ensures that when new enum variants are added, existing code will be flagged for updates.


Structure errors with intent

Implement error handling with clear intent and proper propagation. Follow these principles:

  1. Use structured try/catch blocks with specific error types
  2. Propagate errors explicitly - avoid silent failures
  3. Include actionable error messages
  4. Consider creating custom exceptions for domain-specific errors

Example of proper error handling structure:

try:
    if self.max_execution_time is not None:
        if not isinstance(self.max_execution_time, int) or self.max_execution_time <= 0:
            raise ValueError("Max Execution time must be a positive integer greater than zero")
        result = self._execute_with_timeout(task_prompt, task, self.max_execution_time)
    else:
        result = self._execute_without_timeout(task_prompt, task)
except TimeoutError as e:
    error = f"Task '{task.description}' execution timed out after {self.max_execution_time} seconds. Consider increasing max_execution_time or optimizing the task."
    crewai_event_bus.emit(
        self,
        event=AgentExecutionErrorEvent(
            agent=self,
            task=task,
            error=error
        )
    )
    raise TimeoutError(error)

This pattern ensures:


Clear AI component interfaces

When designing AI components and tools, use domain-specific terminology and provide clear interface documentation to enhance usability and integration. This includes:

  1. Use precise, domain-specific naming that clearly indicates the component’s purpose and functionality in the AI ecosystem. For example, prefer LLMGuardrail over generic terms like Validator when the component specifically handles language model outputs.

  2. Document how AI agents and LLMs will interact with your tools, including expected inputs, outputs, and parameter definitions. This helps other developers understand how the AI will interpret and use the tool.

  3. Provide complete usage examples that demonstrate real-world integration patterns.

Example:

# Good practice with clear naming and documentation
from crewai import Task
from crewai.llm import LLM

task = Task(
    description="Generate JSON data",
    expected_output="Valid JSON object",
    guardrail=LLMGuardrail(  # Specific name indicates it works with LLMs
        instructions="Ensure the response is a valid JSON object",
        examples=[{"valid": {"key": "value"}}]
    )
)

# Example showing tool integration with clear documentation of parameters
from crewai_tools import AISearchTool  # Name indicates AI-specific functionality

# Document how the AI will use this tool
search_tool = AISearchTool(
    name="Web Search",  # Clear name for AI to reference
    description="Search the web for up-to-date information on a given topic",
    input_schema={"query": "The search term or question to look up online"}
)

agent = Agent(
    role="Research Analyst",
    goal="Provide up-to-date market analysis",
    tools=[search_tool]
)

Clear interfaces improve maintainability, make your code more intuitive for other developers, and help language models better understand how to interact with your components.


organize code properly

Maintain clear code organization by placing code in appropriate files, directories, and modules. Respect module boundaries and create logical directory structures that reflect the code’s purpose and domain.

Key principles:

Example of proper organization:

// Before: accessibility functions mixed in handlers
// lib/handlers/observeHandler.ts
type AccessibilityNode = { ... }
function formatSimplifiedTree() { ... }

// After: dedicated accessibility module  
// lib/a11y/utils.ts
type AccessibilityNode = { ... }
function formatSimplifiedTree() { ... }

This approach improves code discoverability, reduces coupling between modules, and makes the codebase easier to navigate and maintain.


Validate pattern matching

When implementing algorithms that involve pattern matching or data parsing, ensure robustness across all edge cases and clearly document the algorithm’s behavior. This is particularly important for:

  1. Prefix matching and partial results - When matching strings against a set of possible values (like enums), consider how to handle ambiguous partial matches:
// Instead of returning any partial match:
const possibleEnumValues = enumValues.filter(enumValue =>
  enumValue.startsWith(result)
);

// Consider uniqueness in your algorithm:
if (possibleEnumValues.length > 1) {
  // Handle ambiguous case - either return only the partial result
  // or require a complete match
  return { partial: result };
} else if (possibleEnumValues.length === 1) {
  // Return the full value when there's only one possible match
  return { complete: possibleEnumValues[0] };
}
  1. Binary format detection - When parsing binary data formats, account for metadata headers and format variations:
// Check for format-specific headers before pattern matching
const stripMetadata = (data: Uint8Array) => {
  // Detect specific header patterns (like ID3 for MP3)
  if (data[0] === 0x49 && data[1] === 0x44 && data[2] === 0x33) {
    // Calculate header size and return data without header
    const headerSize = calculateHeaderSize(data);
    return data.slice(headerSize);
  }
  return data; // No metadata found
};

// Then perform format detection on clean data
const detectedFormat = detectFormat(stripMetadata(rawData));
  1. Iteration correctness - When processing collections as part of your algorithm, verify that you’re iterating over the correct data structure:
// Incorrect: iterating over empty/wrong object
for (const key in emptyObject) { /* ... */ }

// Correct: iterate over the object containing actual data
for (const key in dataObject) {
  if (dataObject[key] !== undefined) {
    processedData[key] = dataObject[key];
  }
}

Always test pattern matching algorithms with comprehensive test cases covering edge cases like empty inputs, partial matches, and format variations.


optimize workflow maintainability

Design CI/CD workflows for long-term maintainability by using consolidated commands and extracting reusable components. Instead of listing individual build steps that may change over time, prefer consolidated npm scripts like npm run pretest that encapsulate the full build process. This approach reduces the need to update workflows when underlying build requirements change. For complex inline logic, extract functionality into custom GitHub Actions rather than embedding lengthy scripts directly in workflow files.

Example of maintainable approach:

# Preferred: Uses consolidated command
- name: Build Tests and Extension  
  run: npm run pretest

# Instead of: Individual commands that require updates
- name: Check Types
  run: npm run check-types
- name: Lint
  run: npm run lint  
- name: Build Extension
  run: npm run compile

For reusable logic, create custom actions instead of inline scripts to improve readability and enable reuse across workflows.


Consistent AI naming

Use specific and consistent naming conventions when referencing AI services, models, and their parameters throughout your codebase. Always include the full provider name (e.g., “AzureOpenAI” instead of just “Azure”) to clearly distinguish between different AI services and avoid ambiguity.

For variables, parameters, and properties related to AI services:

Example:

// Incorrect - ambiguous naming
const azureParams = `{
  azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
  azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"]
}`;

// Correct - specific and consistent naming
const azureOpenAIParams = `{
  azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
  azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
  openai_api_version=os.environ["AZURE_OPENAI_API_VERSION"]
}`;

// Component property should also use the specific name
@property {boolean} [hideAzureOpenAI] - Whether or not to hide Microsoft Azure OpenAI chat model.

This practice improves code readability, reduces confusion when working with multiple AI services, and makes maintenance easier, especially as you integrate additional AI providers in the future.


Platform-appropriate environment variables

Always use the correct syntax for accessing environment variables based on the target platform. In JavaScript/Node.js environments, use process.env.VARIABLE_NAME instead of syntaxes from other languages (e.g., Python’s os.environ).

Example:

// Incorrect - Using Python syntax in JavaScript
const config = {
  azure_endpoint: os.environ["AZURE_OPENAI_ENDPOINT"],
  azure_deployment: os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
  openai_api_version: os.environ["AZURE_OPENAI_API_VERSION"]
};

// Correct - Using JavaScript syntax
const config = {
  azure_endpoint: process.env.AZURE_OPENAI_ENDPOINT,
  azure_deployment: process.env.AZURE_OPENAI_DEPLOYMENT_NAME,
  openai_api_version: process.env.AZURE_OPENAI_API_VERSION
};

For platform-specific configurations, consider using appropriate file formats (like .mdx for Node-specific code) or implement automatic import methods that work across environments to improve compatibility.


organize tests by category

Structure test suites into clear, logical categories and run them as separate CI jobs for better parallelization, maintainability, and failure identification. This approach makes it easier to understand test failures, enables targeted testing, and improves CI performance through parallel execution.

Organize tests by functional area or technology stack, such as:

Example CI matrix configuration:

strategy:
  matrix:
    test:
      - browser/patchright
      - browser/user_binary
      - browser/remote_cdp
      - models/openai
      - models/google
      - models/anthropic
      # TODO: keep adding more in the future
      # - models/azure
      # - models/deepseek
      # - functionality/click
      # - functionality/tabs

This structure allows teams to easily add new test categories, run specific test subsets, and quickly identify which area of the codebase has issues when tests fail.


Verify state before execution

When scheduling asynchronous operations in concurrent environments, always verify the system state hasn’t changed before executing critical operations to prevent race conditions. This is especially important in interactive applications where user actions (like cancellations) might occur between the time an operation is scheduled and when it executes.

To implement this pattern:

Example:

// Instead of this:
setTimeout(() => {
  this.onItem(item);
  staged[idx] = undefined;
}, delay);

// Do this:
setTimeout(() => {
  // Double-check cancellation state right before executing
  if (
    thisGeneration === this.generation &&
    !this.canceled &&
    !this.hardAbort.signal.aborted
  ) {
    this.onItem(item);
    staged[idx] = undefined;
  }
}, delay);

This pattern helps maintain consistency between internal state and UI, prevents “ghost” operations from occurring after cancellation, and makes your concurrent code more robust against race conditions.


Configurable model selection

Avoid hard-coding model names and provider-specific configurations throughout the codebase. Instead, implement flexible model selection patterns that support runtime configuration and consistent naming conventions across different AI providers.

Key practices:

Example of problematic pattern:

// Bad: Hard-coded model name
const response = await client.chat.completions.create({
  model: "gpt-4o", // Hard-coded
  messages: [...],
});

// Bad: Repetitive model specification
await stagehand.act({ action: "start game", model_name: "gpt-4o" });
await stagehand.extract({ instruction: "get price", model_name: "gpt-4o" });

Example of improved pattern:

// Good: Configurable with defaults
class Stagehand {
  constructor(private defaultModel: string = "gpt-4o") {}
  
  async act(options: { action: string; modelName?: string }) {
    const model = options.modelName || this.defaultModel;
    // Use configured model
  }
}

// Good: Consistent provider naming
const modelToProviderMap: { [key in AvailableModel]: ModelProvider } = {
  "cerebras-llama-3.3-70b": "cerebras",
  "openai-gpt-4o": "openai",
};

This approach improves maintainability, reduces duplication, and makes model selection more flexible for different deployment scenarios.


Preserve API backward compatibility

When modifying existing APIs, maintain backward compatibility by implementing changes in a non-breaking way. Use method overloading, optional parameters, or deprecation notices rather than direct breaking changes.

Example of proper API evolution:

// Instead of changing existing interface:
interface DeleteParams {
  ids: string[];
}

// Add overloaded method signatures:
class Store {
  // Original method
  async delete(ids: string[]): Promise<void>;
  // New overload with expanded functionality
  async delete(params: DeleteParams): Promise<void>;
  // Implementation handling both cases
  async delete(idsOrParams: string[] | DeleteParams): Promise<void> {
    if (Array.isArray(idsOrParams)) {
      // Handle legacy case
      return this.deleteByIds(idsOrParams);
    }
    // Handle new case
    return this.deleteWithParams(idsOrParams);
  }
}

// For deprecations, add clear notices:
/** @deprecated Use newMethod() instead. Will be removed in next major version. */

This approach allows gradual migration to new patterns while maintaining existing integrations. When deprecating functionality, provide clear migration paths and timeline in documentation.


Prefer specific identifiers

Always use specific, descriptive names for identifiers rather than generic terms. Names should clearly indicate their purpose and context, making code more readable and self-documenting. This applies to variables, parameters, types, and files.

Examples:

This practice reduces cognitive load for other developers, improves maintainability, and helps prevent confusion or misuse of code elements. The additional verbosity is well worth the clarity it provides.


Propagate errors appropriately

Allow errors to bubble up to their appropriate handling layers rather than catching them prematurely. Catching errors at incorrect levels can prevent proper error handling, recovery mechanisms, and specialized handlers (like rate limiting logic) from functioning as intended.

When designing error handling, consider:

  1. Only catch errors at the level where you can meaningfully handle them
  2. Let specialized error handling logic (like retry mechanisms) exist in a single place
  3. Use appropriate error type checking when you do need to handle specific errors
// Poor practice - catching errors too early without proper handling
try {
  await performOperation();
} catch (error) {
  console.error('Operation failed:', error);
  // No meaningful recovery or proper error propagation
}

// Better practice - let errors propagate to appropriate handlers
// In component code:
await performOperation(); // No try/catch here

// In higher-level error handling layer:
try {
  await executeComponentCode();
} catch (error) {
  if (error instanceof RateLimitError) {
    return await retryWithBackoff();
  } else if (error instanceof NetworkError) {
    // Specialized handling for network issues
  } else {
    // Log and propagate further if needed
    logger.error('Unhandled error:', error);
    throw error;
  }
}

This approach creates a cleaner separation of concerns, centralizes error handling logic, and ensures errors are handled at the most appropriate level.


Handle async operations safely

Always wrap asynchronous operations in try-catch blocks to prevent unhandled promise rejections and provide graceful error recovery. This is especially important for browser APIs that may fail due to user permissions, network issues, or browser compatibility.

When an async operation fails, log the error appropriately and implement fallback behavior or user-friendly error messages. Avoid letting async operations fail silently, as this can lead to confusing user experiences.

Example of proper async error handling:

const handleCopyCode = async () => {
  try {
    await navigator.clipboard.writeText(code)
  } catch (err) {
    console.error('Copy failed', err)
    // Optional: Show user-friendly error message
  }
}

For operations that may fail but have acceptable fallback behavior, handle errors gracefully by returning default values and informing users when appropriate, such as showing “Chrome not detected” messages when browser detection fails.


Balance organization with constraints

When making code organization decisions, consider the broader impact beyond just eliminating duplication or following patterns. Sometimes a slightly less “clean” solution is preferable when it preserves type safety, maintains clear class responsibilities, or avoids exposing unnecessary implementation details.

Key considerations:

Example: Instead of extracting common code that would lose TypeScript type information:

// Prefer this (preserves type safety)
if (this.#protocol === "sse") {
  this.#transport = new McpSSETransport(() => this.getWebSocket());
  await this.server.connect(this.#transport);
} else if (this.#protocol === "streamable-http") {
  this.#transport = new McpStreamableHttpTransport(/*...*/);
  await this.server.connect(this.#transport);
}

// Over this (loses type information, requires assertions)
this.#transport = this.#protocol === "sse" 
  ? new McpSSETransport(/*...*/) 
  : new McpStreamableHttpTransport(/*...*/);
await this.server.connect(this.#transport!); // Type assertion needed

The goal is maintainable code that serves developers well, not just adherence to abstract principles.


validate connection protocols

Always validate network connection types, required parameters, and protocol-specific headers before processing requests. This prevents runtime errors and ensures proper connection handling across different network protocols.

For WebSocket connections, verify the Upgrade header and required parameters:

// Validate WebSocket upgrade request
if (request.headers.get("Upgrade") !== "websocket") {
  return new Response("Expected WebSocket Upgrade request", {
    status: 400,
  });
}

// Validate required parameters
const url = new URL(request.url);
const sessionId = url.searchParams.get("sessionId");
if (!sessionId) {
  return new Response("Missing sessionId", { status: 400 });
}

Use URL paths to distinguish between different protocols and route accordingly:

const path = url.pathname;
switch (path) {
  case "/sse": {
    // Handle SSE protocol
    break;
  }
  case "/websocket": {
    // Handle WebSocket protocol
    break;
  }
}

Consider implementing connection limits and state management to prevent issues with multiple concurrent connections when your system expects only one active connection per session.


Consistent configuration declarations

Ensure configuration specifications (such as version requirements, environment settings, and tool declarations) are consistent and not duplicated across project files. Redundant or contradictory configuration declarations create maintenance issues and confusion.

For example, instead of declaring the same tool in multiple places:

# agents.yaml
tools:
  - SerperDevTool  # Don't declare here if also declared in crew.py
# crew.py
# Declare tools in a single location
tools = [SerperDevTool()]

Similarly, ensure version specifications in documentation accurately reflect actual compatibility:

# README.md
Ensure you have Python >=3.10 <3.12 installed on your system.

When the project actually supports Python 3.12, this should be correctly documented as:

# README.md
Ensure you have Python >=3.10 <=3.12 installed on your system.

Restrict command whitelist

When configuring command whitelists for auto-approval, include only commands with limited capabilities that cannot be exploited for malicious purposes. Powerful tools like text editors (e.g., vim) should be avoided as they provide broad system access and functionality that could introduce security vulnerabilities if auto-approved.

Instead, prefer commands with specific, limited functionality such as nl (number lines). Evaluate each command for its potential security impact before adding it to the whitelist.

Example:

# Recommended
commandWhitelist:
  - "nl"
  - "cat"
  - "grep"

# Not recommended
commandWhitelist:
  - "vim"  # Avoid - provides too much functionality and system access
  - "bash" # Avoid - allows arbitrary command execution

Always ask: “What’s the worst that could happen if this command is automatically approved and executed?” If the answer involves potential system compromise or data exposure, don’t whitelist it.


Document configuration decisions

Configuration files should be self-explanatory and maintainable by including explicit version constraints and explanatory comments for non-obvious choices. This prevents future confusion and ensures reproducible environments.

For dependencies, always specify version constraints rather than leaving them open-ended:

dependencies = [
    "anyio>=4.9.0",  # Not just "anyio"
]

For configuration choices that might seem unusual, add comments explaining the reasoning:

[tool.ruff.lint]
select = ["ASYNC", "E", "F", "I", "PLE"]
ignore = ["ASYNC109", "E101", "E402", "E501", "F841", "E731"]  # TODO: determine if adding timeouts to all the unbounded async functions is needed / worth-it so we can un-ignore ASYNC109

This practice helps future maintainers understand the rationale behind configuration decisions and makes it easier to revisit choices when requirements change.


AI provider consistency

Ensure consistent patterns and configurations across all AI model providers to maintain code maintainability and scalability. This includes providing proper default configurations for all providers and minimizing provider-specific conditional logic that can become unwieldy as more AI models are integrated.

Key practices:

Example of inconsistent approach to avoid:

// Avoid provider-specific logic scattered throughout
const maxTokens = apiConfiguration?.apiProvider === "gemini" 
    ? geminiModels[geminiDefaultModelId].maxTokens
    : anthropicModels["claude-3-7-sonnet-20250219"].maxTokens

// Instead, use a unified approach
case "sambanova":
    return getProviderData(sambanovaModels, sambanovaDefaultModelId) // Always provide default

This approach reduces technical debt and makes the codebase more maintainable as the number of supported AI providers grows.


validate algorithmic correctness

Always verify algorithms work correctly across edge cases and boundary conditions through concrete examples and mathematical validation. Pay special attention to preventing infinite recursion and ensuring mathematical formulas produce expected results.

Key practices:

Example from message truncation logic:

// Incorrect: Can result in zero when it shouldn't
messagesToRemove = Math.floor((messages.length - startOfRest) / 8) * 3 * 2
// With messages.length=5, startOfRest=1: floor(4/8) * 3 * 2 = 0 * 6 = 0

// Correct: Properly calculates 3/4 of remaining pairs  
messagesToRemove = Math.floor(((messages.length - startOfRest) * 3) / 4 / 2) * 2
// With messages.length=5, startOfRest=1: floor((4*3)/4/2) * 2 = floor(1.5) * 2 = 2

For recursive operations, implement safeguards:

// Prevent infinite recursion with cycle detection
const visitedPaths = new Set<string>()
if (visitedPaths.has(resolvedPath)) {
    continue // Skip already processed paths
}
visitedPaths.add(resolvedPath)

Safe attribute access

Always use defensive programming patterns when accessing object attributes, especially when dealing with optional or potentially None values. Use hasattr() checks before accessing attributes, prefer public accessor methods over private attributes, and add null checks when accessing nested properties.

Key patterns to follow:

  1. Use hasattr() to check attribute existence before access
  2. Prefer public accessor methods over direct private attribute access
  3. Add null checks when accessing returned objects from methods
  4. Understand the actual object structure before accessing nested properties

Example of unsafe vs safe access:

# Unsafe - direct private attribute access
if hasattr(page.context, '_browser_context_config'):
    if hasattr(page.context._browser_context_config, 'anti_fingerprint'):
        self.anti_fingerprint = page.context._browser_context_config.anti_fingerprint

# Safe - public accessor with null checks
if hasattr(page, 'context') and hasattr(page.context, 'get_config'):
    config = page.context.get_config()
    if config is not None and hasattr(config, 'anti_fingerprint'):
        self.anti_fingerprint = config.anti_fingerprint

This approach prevents AttributeError exceptions, respects encapsulation, reduces coupling, and makes code more robust against null references and missing attributes.


Proper package.json structure

Maintain clean and properly structured package.json files by following these principles:

  1. Categorize dependencies correctly - place development tools and testing libraries in devDependencies, not in regular dependencies. This ensures smaller production builds and clearer dependency management.

  2. Avoid creating custom npm scripts that merely duplicate functionality already available through standard CLI commands.

Example of proper dependency categorization:

 {
   "dependencies": {
     "react": "^18.2.0",
     "openai": "^4.89.0",
-    "js-yaml": "^4.1.0",
   },
   "devDependencies": {
+    "js-yaml": "^4.1.0",
     "typescript": "^5.0.0",
     "jest": "^29.0.0"
   },
   "scripts": {
     "build": "tsc",
-    "husky:add": "husky add"
   }
 }

This approach keeps configuration files clean, minimizes production build size, and leverages standard tools as intended.


validate untrusted inputs

Always validate and sanitize untrusted inputs to prevent injection attacks and security vulnerabilities. This includes path inputs that could lead to directory traversal attacks and content that may contain malicious HTML entities.

For path validation, avoid resolving symbolic links directly as this can enable directory traversal attacks. Instead, use safe path manipulation methods that don’t follow symlinks.

For content validation, implement reusable functions to check for dangerous patterns rather than repeating validation logic:

function areUnallowedHtmlEntities(content) {
   const entityNamesToBeBypassed = ['gt','lt','quot','amp','apos']
   const unallowedEntityNamesRegExp = entityNamesToBeBypassed.map(entityName => `(${entityName})`).join('|')
   const reg = new RegExp(`&${unallowedEntityNamesRegExp};`,'g')
   return content.match(reg)?.length > 0
}

// Usage
if(areUnallowedHtmlEntities(content)) {
   // Handle unsafe content
}

This approach prevents XSS vulnerabilities while maintaining clean, reusable code. Always assume inputs are malicious and validate accordingly.


Prevent command injection

Always use child_process.spawn() with array arguments instead of exec() with string concatenation when executing system commands. This prevents command injection vulnerabilities that can occur when untrusted input is incorporated into command strings.

Problematic code:

const safePreview = preview.replace(/"/g, '\\"');
const title = "Codex CLI";
exec(`osascript -e "display notification \\"${safePreview}\\" with title \\"${title}\\""`, { cwd });

Secure code:

const title = "Codex CLI";
spawn('osascript', [
  '-e',
  `display notification "${preview}" with title "${title}"`
], { cwd });

By passing arguments as separate array elements, the operating system receives them without interpreting special characters as command syntax, ensuring untrusted input cannot escape its intended context.


Test behavior not calls

Tests should validate actual system behavior rather than just verifying method calls. When writing tests, focus on asserting the expected outcomes and side effects rather than simply checking if methods were invoked.

Bad example:

def test_task_execution():
    with patch.object(Agent, "_execute", return_value="ok") as execute:
        result = task.execute()
        assert result.raw == "ok"
        execute.assert_called_once()  # Only validates the call

Good example:

@tool("test_tool", result_as_answer=True)
def delayed_tool():
    sleep(5)  # Actual behavior
    return "ok"

def test_task_execution():
    agent = Agent(tools=[delayed_tool])
    task = Task(description="test", agent=agent)
    
    result = task.execute()
    assert result.raw == "ok"
    # Test validates actual timing behavior
    assert task.execution_time >= 5

Key points:


Manage database connections

Always properly manage database connections to prevent resource leaks and improve application stability. Implement these key practices:

  1. Release connections back to the pool after use with a try/finally block
  2. Implement graceful shutdown for database pools
  3. Use connection pooling instead of creating new connections for each request
  4. Set appropriate connection pool configuration (size, timeout)

Example:

// Connection pool setup with proper configuration
const dbPool = mysql.createPool({
  ...dbConfig,
  connectionLimit: 10,
  queueLimit: 0,
  connectTimeout: 10000,
});

// Function using a connection with proper release
async function queryDatabase() {
  const connection = await dbPool.getConnection();
  try {
    const [results] = await connection.execute('SELECT id, name FROM users WHERE status = ?', ['active']);
    return results;
  } catch (error) {
    console.error('Database query failed:', error);
    throw error;
  } finally {
    // Always release the connection back to the pool
    connection.release();
  }
}

// Graceful shutdown handler
process.on('SIGTERM', async () => {
  console.log('Closing database connections...');
  if (dbPool) {
    await dbPool.end();
    console.log('Database pool closed');
  }
  process.exit(0);
});

Default None not empty

Always use None as the default value for optional parameters and class attributes instead of empty collections ([], {}, "") or other mutable defaults. This prevents sharing mutable state between instances and makes null checks more explicit.

Example:

# ❌ Bad - Using mutable defaults
class ToolAdapter:
    original_tools: List[BaseTool] = []  # Shared between instances
    def __init__(self, items: List[str] = []):  # Mutable default
        self.items = items

# ✅ Good - Using None as default
class ToolAdapter:
    def __init__(self):
        self.original_tools: List[BaseTool] = []  # Instance-specific
    
    def process(self, items: Optional[List[str]] = None):
        items = items or []  # Convert None to empty list
        # Process items...

This approach:

  1. Prevents shared state bugs from mutable defaults
  2. Makes optional parameters explicit
  3. Forces conscious initialization of collections
  4. Enables clear null checking patterns

CSS utility usage

Use CSS utility functions and avoid complex inline calculations for better maintainability and readability. Prefer cx() from useStyles for combining CSS classes instead of template literals, and use css from antd-style for simple styles without design tokens.

Recommended patterns:

// ✅ Good: Use cx() for combining classes
const { styles, cx } = useStyles();
<div className={cx(styles.promptBox, styles.animatedContainer)} />

// ❌ Avoid: Template literal concatenation
<div className={`${styles.promptBox} ${styles.animatedContainer}`} />

// ✅ Good: Simple CSS without tokens
import { css, cx } from 'antd-style';
const extraTitle = css`
  font-weight: 300;
  white-space: nowrap;
`;
<div className={cx(extraTitle)} style={{ fontSize: extraSize }} />

// ❌ Avoid: Complex CSS calculations that are fragile
style={{ maxHeight: `calc(75vh - 56px - 13px - ${gap}px)` }}

Avoid overly complex CSS calculations that depend on magic numbers, as they become fragile when layouts change. Consider using CSS inheritance properties or more robust layout solutions instead.


Model initialization formatting

Maintain consistent formatting when initializing AI models and agents. Use proper spacing around assignment operators and consistent indentation for constructor parameters to improve code readability and follow Python style conventions.

Key formatting rules:

Example of proper formatting:

# Good: proper spacing and indentation
llm = ChatOpenAI(base_url='https://api.novita.ai/v3/openai', model='deepseek/deepseek-v3-0324', api_key=SecretStr(api_key))

agent = Agent(
    task="Your task here",
    llm=llm,
    planner_llm=planner_llm,
    extend_planner_system_message=extend_planner_system_message
)

This ensures AI model initialization code is clean, readable, and follows established Python formatting standards.


preserve exception context

When handling exceptions, always preserve the original error context to aid in debugging and error diagnosis. This involves two key practices: (1) Include the exception class name when converting exceptions to strings, and (2) Use exception chaining when re-raising exceptions.

For error message formatting, avoid bare str(e) or f'{e}' as these only show the error message without the exception type. Instead, use f'{type(e).__name__}: {e}' to include both the exception class and message.

When re-raising exceptions or wrapping them in custom exceptions, always preserve the original traceback using from e to maintain the full error context for debugging.

Example of proper exception context preservation:

try:
    response: dict[str, Any] = await structured_llm.ainvoke(input_messages)
    parsed: AgentOutput | None = response['parsed']
except Exception as e:
    logger.error(f'Failed to invoke model: {type(e).__name__}: {e}')
    raise LLMException(401, 'LLM API call failed') from e

# For error reporting in return values:
except Exception as e:
    return {
        'task_id': task_folder.name, 
        'judgement': None, 
        'success': False, 
        'error': f'{type(e).__name__}: {e}', 
        'score': 0.0
    }

This practice significantly improves error diagnosis by providing complete context about what went wrong and where the error originated, making debugging much more efficient.


Remove commented code immediately

Commented-out code should be removed immediately rather than committed to the codebase. Keeping commented code creates confusion, adds unnecessary noise, and makes the codebase harder to maintain. If code is no longer needed, delete it - version control systems will preserve the history if it needs to be referenced later.

Example of what to avoid:

export function useDocumentTitle() {
  // const settingsStore = useSettingsStore();
  // const { releaseChannel } = settingsStore.settings;
  // const suffix = !releaseChannel || releaseChannel === 'stable' 
  //   ? 'n8n' 
  //   : `n8n[${releaseChannel.toUpperCase()}]`;
}

Instead, either:

  1. Delete the code entirely if it’s no longer needed
  2. Complete the implementation if the code is still required
  3. Create a TODO comment with a clear explanation if the code represents future work

This keeps the codebase clean, current, and easier to understand for all developers.


Versioning for migrations

Use appropriate version bumps to signal migration requirements and maintain clear upgrade paths. Flag breaking changes with major version bumps to help with release notes and upgrade guides. External contributors should use patch bumps only, while minor and major version changes are reserved for the core team.

Example:

# For breaking changes (core team only)
pnpm changeset
# Select 'major' for the bump type when removing APIs or making breaking changes

# For external contributors
pnpm changeset
# Select 'patch' for all contribution changes

This versioning strategy ensures users have clear signals about migration requirements and proper documentation is maintained for version transitions.


Optional dependency management

Avoid including optional or provider-specific dependencies in the main dependency list. Dependencies should only be required if they are essential for core functionality that all users need.

Make dependencies optional when they are:

Use the optional = true flag and organize them into appropriate extras groups:

[tool.poetry.dependencies]
# Core dependencies only
python = ">=3.9,<3.12"
pydantic = "^2.0"

# Optional dependencies
groq = { version = "^0.4.2", optional = true }
mistralai = { version = "^0.1.3", optional = true }

[tool.poetry.extras]
groq = ["groq"]
mistral = ["mistralai"]

This approach prevents forcing unnecessary installations on users who don’t need specific providers or features, while still making them available for those who do.


Maintain API naming consistency

When working with AI model interfaces and result objects, ensure consistent property naming across related components. The AI ecosystem involves multiple providers and model types, making naming consistency crucial for maintainable code.

For example, use the same property name consistently when accessing similar data from model results:

// INCORRECT
console.log('Responses:', result.responses);

// CORRECT
console.log('Response:', result.response);

This consistency should extend across different AI capabilities (text generation, transcription, embedding, etc.) to create a cohesive developer experience. Inconsistent naming patterns lead to:

  1. Developer confusion when switching between model types
  2. Harder code maintenance as the application grows
  3. Bugs from incorrectly accessing properties with similar purposes but different names

When designing AI interfaces or extending existing ones, audit the naming patterns of related components and align new additions with established conventions. This is particularly important when working with response objects from different AI providers that may use varying terminology for similar concepts.


Verify properties before logging

When logging object properties, always verify that the property names exactly match the actual structure of the object being logged. Incorrect property names (like ‘responses’ instead of ‘response’) or non-existent properties will result in undefined values in logs, reducing their usefulness for debugging and troubleshooting.

Example of problematic code:

console.log('Responses:', result.responses);       // Incorrect property name
console.log('Provider Metadata:', result.providerMetadata);  // Non-existent property

Corrected code:

console.log('Response:', result.response);         // Correct property name
// Don't log properties that don't exist in the object

Consider using optional chaining (?.) for nested properties or TypeScript to help catch these issues at compile time. For important logging in production code, consider adding runtime property existence checks before logging.


Place configurations appropriately

Configuration options should be organized based on their nature and scope of use. Place model-specific configurations in constructor parameters or config objects rather than in general settings objects that might be shared across models. Additionally, standardized settings should be consistent across providers and not duplicated in provider-specific options.

This organization improves code maintainability and prevents confusion about where settings should be defined or accessed.

// GOOD: Model-specific config in constructor parameters
constructor(
  modelId: OpenAICompatibleChatModelId,
  settings: OpenAICompatibleChatSettings,
  config: OpenAICompatibleChatConfig & {
    defaultObjectGenerationMode?: 'json' | 'tool' | undefined;
  }
) { ... }

// BAD: Model-specific config in settings
export interface OpenAICompatibleChatSettings {
  user?: string;
  defaultObjectGenerationMode?: 'json' | 'tool' | undefined; // Should be in config instead
}

// GOOD: Standardized settings not duplicated in provider options
// For settings like 'voice' that are standardized across providers
speech.generate("Hello world", {
  voice: "alloy",  // Top-level standardized setting
});

// BAD: Duplicating standardized settings in provider options
speech.generate("Hello world", {
  providerOptions: {
    openai: {
      voice: "alloy",  // Duplicated standardized setting
    }
  }
});

For common settings that apply across different providers (like ‘voice’ for speech models or ‘language’ for transcription), define them as top-level options rather than duplicating them in each provider’s specific options.


AI capability documentation

When documenting AI systems, models, or assistants, ensure technical terminology is precise and capabilities are clearly scoped. Use consistent language to describe what the AI can and cannot do, avoiding vague or overstated claims. For AI agents or assistants, explicitly detail their tools, permissions, and limitations.

For example, instead of vague descriptions like “AI helper that can code,” use specific language:

# Clear AI Capability Documentation
Powered by Claude 3.7 Sonnet's agentic coding capabilities, this AI assistant can:
- Create and edit files with linter/compiler error monitoring
- Execute terminal commands (with user authorization)  
- Browse projects and analyze code structure via AST parsing
- Use headless browser for web development tasks

Limitations: Requires human approval for each file change and terminal command.

This approach helps users understand exactly what to expect from AI tools and prevents misaligned expectations. When localizing AI documentation, maintain technical accuracy while adapting language for cultural context. Consistent terminology across all documentation languages ensures users have the same understanding regardless of their preferred language.


Handle errors gracefully

Always implement appropriate error handling to prevent crashes while providing clear feedback to users. Consider these principles:

  1. Decide on error propagation strategy: Determine whether errors should be handled locally or propagated to a higher-level handler based on severity and recoverability.

  2. Catch specific exceptions: Target exact exception types rather than using broad catches.

  3. Use consistent error reporting: Utilize standardized error reporting mechanisms instead of print statements.

  4. Consider platform-specific issues: Anticipate and handle platform-dependent error scenarios.

Example of proper error handling with clear propagation strategy:

def register_models(model_def_fnames):
    for model_def_fname in model_def_fnames:
        if not os.path.exists(model_def_fname):
            continue
        try:
            with open(model_def_fname, "r") as model_def_file:
                model_def = json.load(model_def_file)
        except json.JSONDecodeError as e:
            # Propagate critical configuration errors to main for centralized handling
            raise ConfigurationError(f"Invalid model definition in {model_def_fname}: {e}")
        except IOError as e:
            # Log but continue if a file can't be read
            io.tool_error(f"Could not read model definition: {e}")

When handling cleanup operations, catch specific exceptions that might occur:

try:
    # Cleanup operation
    shutil.rmtree(self.tempdir)
except (OSError, PermissionError):
    pass  # Ignore cleanup errors (especially on Windows)

For functions that might fail, clearly document return behavior and ensure consistent error state handling:

# Return values on error should be documented and consistent
try:
    self.repo.git.commit(cmd)
    return commit_hash, commit_message
except GitError as err:
    self.io.tool_error(f"Unable to commit: {err}")
    # Explicitly return None to make the error path obvious
    return None

Optimize CI type checking

Configure separate TypeScript type-checking strategies for CI environments and local development. CI pipelines should run complete type checks that validate the entire codebase, while local development can use faster configurations to improve developer productivity.

Example implementation:

// package.json
{
  "scripts": {
    "type-check": "tsc --build",                       // Faster checks for local development
    "type-check:full": "tsc --build tsconfig.with-examples.json", // Comprehensive checks for CI
    "clean": "rimraf dist"                             // Add cleanup before builds
  }
}

In your CI pipeline configuration, always use the more thorough type checking:

# CI configuration
steps:
  - name: Type Check
    run: npm run type-check:full

This approach ensures your CI pipeline catches all type errors while developers can work efficiently with faster feedback loops during local development. When changing build configurations, document the implications for the team and update CI pipelines accordingly.


Restrict external dependencies

Dependencies from packages outside your organization’s trusted domain pose security risks and should be avoided in pull requests. When package-lock.json files include external dependencies, they introduce potential vulnerabilities that bypass internal security controls.

Only include dependencies from your organization’s approved domains (e.g., internal packages, trusted vendors like AWS in this case). If external dependencies are necessary, they should be reviewed and added through internal security processes rather than directly in pull requests.

When submitting PRs:

This approach ensures all external dependencies undergo proper security vetting before being introduced to the codebase.


Sanitize Model Output

When handling untrusted model/text output that will be serialized into JSON (or rendered in a UI), normalize it before output generation—specifically strip or escape tag-like content (e.g., “”) so it cannot corrupt JSON or break downstream parsing.

Apply this by adding a single sanitization/normalization step right before JSON serialization (or right before writing responses to clients):

function sanitizeTagsByLine(text) {
  return text
    .split(/\r?\n/)
    .map(line => line
      // remove thinking tags that can break JSON/UI parsing
      .replace(/<\s*think\s*>[\s\S]*?<\s*\/\s*think\s*>/gi, "")
      // optionally remove any stray <think> tags
      .replace(/<\s*think\s*>/gi, "")
      .replace(/<\s*\/\s*think\s*>/gi, "")
    )
    .join("\n");
}

const raw = modelOutputText; // untrusted
const safe = sanitizeTagsByLine(raw);
const json = JSON.stringify({ content: safe });

Also add a quick sanity check (e.g., ensure the produced payload is valid JSON and the UI receives expected fields) so tag-related issues are caught early.


Sanitize untrusted tags

Treat any tag/markup coming from user input, LLM output, or external commands as untrusted. Validate and sanitize it at the earliest boundary before embedding into JSON or rendering in the UI—e.g., strip/escape disallowed tags so they can’t break parsers or visuals.

Example (shell boundary sanitization):

# sanitize_tags.sh
# Remove/neutralize disallowed tags before downstream UI/JSON handling
sanitize_tags() {
  # Example: drop <thinking>...</thinking>
  sed -E 's#<\/?thinking[^>]*>##g'
}

INPUT="$1"
SAFE_INPUT="$(printf '%s' "$INPUT" | sanitize_tags)"
# Use $SAFE_INPUT for any JSON generation or UI rendering

Apply this by: (1) defining allowed vs. disallowed tags, (2) sanitizing/escaping before JSON construction and before UI templating/rendering, and (3) adding automated tests for payloads that previously broke visuals/JSON (e.g., special tags).


Provide contextual error messages

Error messages should include specific context about what went wrong and provide actionable guidance for resolution. Avoid generic error messages that leave developers guessing about the root cause or solution.

When throwing errors:

  1. Include the original error details when wrapping exceptions to preserve debugging information
  2. Provide specific context about the current state or operation that failed
  3. Offer clear, actionable steps the developer can take to resolve the issue

Example of improved error messaging:

// Poor: Generic error message
throw new Error("act() is not implemented on the base page object");

// Better: Contextual error with actionable guidance
throw new Error(
  "act() is not implemented on the base page object. Ensure you are calling init() on the Stagehand object before calling methods on the page object."
);

// Best: Include original error details when wrapping
constructor(error?: unknown) {
  if (error instanceof Error || error instanceof StagehandError) {
    super(
      `\nHey! We're sorry you ran into an error. \nIf you need help, please open a Github issue or reach out to us on Slack: https://stagehand.dev/slack\n\nFull error:\n${error.message}`
    );
  }
}

This approach reduces debugging time and improves the developer experience by making failures self-explanatory.


Async error callbacks

When handling asynchronous operations, especially those that might continue running in the background after the main consumer has moved on, provide error callback options to ensure errors are properly reported and handled. This pattern prevents silent failures in background tasks and enables proper logging, monitoring, and recovery.

For example, when consuming streams:

// Without error handling - errors might be silently lost
result.consumeStream(); // no await

// With error handling - errors are properly reported
result.consumeStream(error => {
  console.log('Error during background stream consumption: ', error);
  // Optional: report to monitoring system
});

This approach is particularly important for background operations like stream consumption where the operation continues even when the client response is aborted (e.g., when a browser tab is closed). By implementing error callbacks, you ensure that errors are visible and actionable rather than silently failing.


Thread-safe message dispatching

When implementing communication between multiple threads, ensure that messages are correctly routed to their intended recipients. Avoid designs where all worker threads consume from a single shared queue when messages are intended for specific threads, as this creates race conditions where messages can be processed by the wrong thread.

Instead, consider one of these approaches:

  1. Use separate queues for each recipient thread
  2. Implement a central dispatcher that routes messages to the correct recipient
  3. Use an event-based pattern with callbacks or futures

Example of problematic code:

def _server_loop(self, server: McpServer, loop: asyncio.AbstractEventLoop) -> None:
    while True:
        # All threads compete for the same messages
        msg: CallArguments = self.message_queue.get()
        
        # If message not for this server, discard it
        if msg.server_name != server.name:
            self.message_queue.task_done()
            continue
            
        # Process the message...

Better implementation:

class McpManager:
    def __init__(self):
        # One queue per server for proper message routing
        self.server_queues = {}  # server_name -> queue
        self.result_queue = queue.Queue()
        
    def add_server(self, server_name):
        self.server_queues[server_name] = queue.Queue()
        
    def _call(self, io, server_name, function, args={}):
        # Route message to specific server queue
        if server_name in self.server_queues:
            self.server_queues[server_name].put(CallArguments(server_name, function, args))
            result = self.result_queue.get()
            return result.response
        return None
        
    def _server_loop(self, server: McpServer, loop: asyncio.AbstractEventLoop) -> None:
        # Each server only processes its own messages
        server_queue = self.server_queues[server.name]
        while True:
            msg = server_queue.get()
            # Process message...

This pattern prevents race conditions and ensures messages are always processed by their intended recipients.


Configuration merging precedence

When merging configuration objects, always preserve existing values and follow clear precedence rules to avoid unintentionally overriding settings. Use spread operators carefully and ensure the merge logic is implemented at the appropriate layer (preferably in action/store layer rather than component level).

Key principles:

  1. Preserve existing values: When conditionally adding properties, avoid using empty objects {} that can override existing configurations
  2. Clear precedence order: Establish and document which configuration source takes priority (e.g., user settings > default settings > provider settings)
  3. Merge at the right layer: Implement merging logic in store actions rather than components for consistency across the application

Examples:

Problematic merging - overwrites existing footerAction:

appearance={{
  ...appearance,
  elements: {
    ...appearance.elements,
    footerAction: !enableClerkSignUp ? { display: 'none' } : {}, // Empty object overwrites existing
  }
}}

Proper conditional merging:

appearance={{
  ...appearance,
  elements: {
    ...appearance.elements,
    ...((!enableClerkSignUp) && { footerAction: { display: 'none' } }),
  }
}}

Component-level merging:

onChange={(value) => {
  updatePluginSettings(id, { [item.name]: value }); // Overwrites other settings
}}

Store-level merging:

// In store action
updatePluginSettings: (id, updates) => {
  set((state) => ({
    pluginSettings: {
      ...state.pluginSettings,
      [id]: { ...state.pluginSettings[id], ...updates }
    }
  }));
}

This approach ensures configuration integrity and prevents accidental loss of user preferences or system settings.


Clean typing and DRY

Adopt a “type-correct, DRY, and clean” coding style.

Rules: 1) Make type hints compile and be precise

2) Remove unused assignments and dead code

3) Avoid redundant abstractions/config branches

Example (typing + unused-code cleanup):

from typing import Dict, List, Union

def parse_intent(text: str) -> Dict[str, Union[str, List[str]]]:
    intention: Dict[str, Union[str, List[str]]] = {}  # typed and initialized
    # ... parse JSON, fill intention ...
    return intention

Example (DRY via config flag):

def explore(..., graph_store):
    similarity_search_enabled = graph_store.get_config().similarity_search_enabled
    if similarity_search_enabled:
        # do embedding/search logic
        pass
    # else: fall through

Enforce these checks in review and via tooling (lint/type checker) so style remains consistent and code stays maintainable.


comprehensive test coverage

Ensure tests are comprehensive and explicit to prevent regressions and gaps in coverage. Tests should cover all scenarios including edge cases, error conditions, and boundary conditions. Avoid vague assertions that could pass even when the implementation is incorrect.

Key practices:

Example of explicit vs vague testing:

# Vague - could pass even if no parameters are missing
assert len(missing_params) < max_allowed

# Explicit - tests exact expected behavior  
assert len(missing_params) == 2
assert "required_field" in missing_params
assert "another_field" in missing_params

When adding new features or modifying behavior, always ask: “What scenarios could break this?” and “What edge cases am I not testing?” This prevents regressions and ensures robust, reliable code.


Simplify algorithmic implementations

Favor clear, simple algorithmic implementations over complex custom logic. When faced with algorithmic choices, prefer built-in functions, direct approaches, and well-structured decomposition into stages.

Key principles:

  1. Use built-in functions: Replace custom implementations with standard library functions when available
  2. Choose direct approaches: Opt for straightforward logic over complex conditional chains
  3. Decompose complex operations: Break multi-step algorithms into clearly named stages
  4. Use lookup tables: Replace long conditional chains with dictionary-based approaches

Example of good decomposition (from discussion 5):

# Stage 1: Gather all results
all_results = chain.from_iterable(await asyncio.gather(*tasks))

# Stage 2: Remove duplicates  
unique_results = list(set(all_results))

# Stage 3: Get top results
top_results = sorted(unique_results, key=lambda r: r.distance)[:max_terms]

Example of lookup table approach (from discussion 7):

tests = {
    "equal_to": lambda a, b: a == b,
    "not_equal_to": lambda a, b: a != b,
    "regex": lambda a, b: re.match(str(a), str(b)),
}

for test, value in conditions.items():
    if not tests[test](value, candidate.get(field)):
        return False

This approach improves code maintainability, reduces bugs, and makes algorithmic intent clearer to other developers.


Typed API client abstractions

When designing API clients, encapsulate responses in typed objects rather than passing raw JSON throughout your codebase. This improves maintainability, enables better error handling, and provides type safety.

For HTTP API clients, use session objects to handle common configurations like authentication headers and base URLs. This approach reduces code duplication and creates a cleaner interface.

Example:

# Instead of this:
def _make_request(self, method: str, endpoint: str, **kwargs) -> requests.Response:
    url = f"{self.base_url}/{endpoint}"
    return requests.request(method, url, headers=self.headers, **kwargs)

# Do this:
class CrewAPI:
    def __init__(self, api_key: str) -> None:
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        })
        self.base_url = "https://api.example.com/v2"
        
    def deploy_by_name(self, project_name: str) -> DeployResponse:
        """Deploy a project by name and return a typed response."""
        url = f"{self.base_url}/deploy/{project_name}"
        response = self.session.post(url)
        
        if not response.ok:
            raise APIError(response.json())
            
        return DeployResponse.from_json(response.json())
        
class DeployResponse:
    """Typed representation of a deployment response."""
    uuid: str
    status: str
    timestamp: datetime
    
    @classmethod
    def from_json(cls, data: dict) -> 'DeployResponse':
        # Convert raw JSON to typed object
        return cls(**data)

This pattern ensures that API-specific concerns stay in the client implementation while providing a clean, type-safe interface for consumers.


Use cross-platform build commands

Replace native shell commands in package.json scripts with cross-platform alternatives to ensure build consistency across different operating systems. Native commands like rm -rf fail on Windows, breaking CI/CD pipelines that run on mixed environments.

Use tools like shx or rimraf instead of native shell commands:

{
  "scripts": {
    //  Not cross-platform compatible
    "clean": "rm -rf build",
    "build": "rm -rf dist && rslib build && chmod +x dist/*.js",
    
    //  Cross-platform compatible
    "clean": "shx rm -rf build", 
    "build": "shx rm -rf dist && rslib build && shx chmod +x dist/*.js"
  }
}

This ensures your build scripts work reliably in CI/CD environments regardless of the underlying operating system, preventing deployment failures due to platform-specific command incompatibilities.


Respect browser behavior

Always consider and respect browser native behaviors when implementing web application features. Avoid conflicts with built-in browser shortcuts and choose appropriate client vs server-side approaches based on the execution environment.

Key considerations:

Example from hotkey implementation:

// Avoid: Using 'mod' which maps to 'cmd' on Mac, conflicting with browser tabs
useHotkeys(list.slice(0, 9).map((e, i) => `mod+${i + 1}`), handler);

// Prefer: Use 'ctrl' explicitly to avoid browser shortcut conflicts
useHotkeys(list.slice(0, 9).map((e, i) => `ctrl+${i + 1}`), handler);

Example from navigation:

// Avoid: Server redirect that fails in production
return redirect(urlJoin('/settings', searchParams.tab));

// Prefer: Client-side redirect for better compatibility
// Use client-side navigation instead

This ensures better user experience by respecting established browser conventions and avoiding runtime errors in production environments.


Fail fast principle

When writing security-sensitive shell scripts, use strict error handling to fail immediately on errors rather than attempting fallbacks or continuing silently. Always include set -euo pipefail to exit on errors, treat unbound variables as errors, and propagate pipeline failures. This prevents partial application of security configurations that could leave systems in a vulnerable state.

#!/bin/bash
# Always use strict error handling in security scripts
set -euo pipefail  # Exit on error, undefined vars, and pipeline failures
IFS=$'\n\t'        # Stricter word splitting

# Critical security operations
iptables -F
ipset create allowed-domains hash:net

# External dependencies should fail explicitly rather than silently continuing
gh_ranges=$(curl -s https://api.github.com/meta)
if [ -z "$gh_ranges" ]; then
    echo "ERROR: Failed to fetch GitHub IP ranges"
    exit 1
fi

By failing fast on errors, you ensure that security configurations are either completely applied or not applied at all, avoiding inconsistent states that could create security vulnerabilities. For security-critical code, avoid fallback mechanisms like the try_cmd pattern that might silently continue after failures.


validate SVG security context

SVG files can execute code when loaded, making them a potential security vulnerability. Before using SVGs, evaluate the deployment context and security requirements. Different environments have different restrictions - for example, VS Code marketplace prohibits user-provided SVGs due to security concerns, while webview-hosted SVGs may be acceptable. When SVGs pose security risks, consider safer alternatives like base64-encoded images or icon pack fonts. Be especially cautious with user-provided SVG content that could be modified to contain malicious code.

Example of context-aware SVG handling:

// Risky: User-provided SVG for marketplace
const userSvg = getUserProvidedSvg(); // Could contain malicious code

// Safer alternatives:
const base64Image = convertToBase64(imageFile);
const iconFont = registerIconPackFont();
const controlledSvg = getStaticSvgFromAssets(); // Known safe content

enhance poor error messages

When external APIs or dependencies provide cryptic or unhelpful error messages, wrap them with user-friendly, actionable guidance. This is especially important when the external service returns terse responses that don’t help users understand what went wrong or how to fix it.

Transform generic errors into specific, step-by-step instructions that guide users toward resolution. Include relevant links, configuration steps, or troubleshooting information.

Example:

// Instead of letting cryptic API errors bubble up
if (!this.options.fireworksApiKey) {
    yield {
        type: "text",
        text: "ERROR: Fireworks API key is required but was not provided.\n\n" +
              "Please set your API key in the extension settings:\n" +
              "1. Open the KiloCode settings panel\n" +
              "2. Select 'Fireworks' as your provider\n" +
              "3. Enter your API key\n\n" +
              "You can get your API key from: https://fireworks.ai/account/api-keys",
    }
    return
}

This approach is justified when external services provide inadequate error context (like Fireworks returning just {"error":"unauthorized"} instead of OpenAI’s detailed error messages). The enhanced messages should be implemented at the API boundary to avoid duplicating error handling logic throughout the codebase.


Least privilege networking

Restrict network access to only what’s necessary for your application to function, using explicit allowlisting rather than trying to block malicious traffic. Network traffic should be denied by default and only specifically required destinations should be allowed.

When implementing network restrictions:

  1. Start with a default deny policy for all traffic
  2. Explicitly allowlist only necessary domains and IP ranges
  3. Use fallback mechanisms for critical security controls
  4. Verify your restrictions work as expected

For example, when configuring container firewalls:

# Create default deny policy
iptables -P OUTPUT DROP

# Create allowlist for domains
ipset create allowed-domains hash:net

# Add only necessary domains
for domain in "api.required-service.com" "cdn.dependencies.org"; do
    ips=$(dig +short A "$domain")
    for ip in $ips; do
        ipset add allowed-domains "$ip"
    done
done

# Allow only traffic to allowlisted destinations
iptables -A OUTPUT -m set --match-set allowed-domains dst -j ACCEPT

# Test the configuration works as expected
if curl --connect-timeout 5 https://blocked-domain.com >/dev/null 2>&1; then
    echo "ERROR: Firewall verification failed"
fi

Remember that network restrictions should be combined with other security controls (defense in depth). As shown in the discussion about S3 access, network allowlisting can be paired with credential restrictions to provide multiple layers of security.


Document configuration assumptions

When documenting configuration settings, environment setup, or system requirements, explicitly state assumptions about the target environment and provide accurate default values. Avoid making implicit assumptions that may not apply to all users or deployment scenarios.

For configuration settings, ensure documented default values match the actual implementation:

- `cline.editor.skipDiffAnimation`: Disable the animated diff view when Cline makes changes to files. This can significantly speed up file modifications, especially when working with remote repositories. Default: `false`

For environment-specific instructions, acknowledge the target system and note alternatives:

**Linux-specific Setup (Debian/Ubuntu)**
If you're developing on Debian-based Linux distributions, you'll need to install additional system libraries:
```bash
sudo apt update
sudo apt install -y libatk1.0-0 libatk-bridge2.0-0 ...

Note: For RHEL, Arch, or Alpine systems, equivalent packages will have different names and installation methods.


This practice prevents confusion, reduces support burden, and ensures users can adapt instructions to their specific environments.

---

## synchronize configuration environments

<!-- source: stanfordnlp/dspy | topic: Configurations | language: Yaml | updated: 2025-03-03 -->

Ensure configuration values remain consistent between local development and CI/CD environments, and document the rationale behind environment-specific settings. Version mismatches and undocumented configuration behavior can lead to unexpected failures and developer confusion.

When updating configuration values like dependency versions, tool versions, or environment variables, verify they match across all environments. Add explanatory comments for configurations that have non-obvious behavior or requirements.

Example:
```yaml
env:
  # Keep in sync with poetry.lock - developers use 1.7.1 locally
  POETRY_VERSION: "1.7.1"

- name: Create test environment
  # Virtual env activation changes sys.path, excluding working dir
  # Installation is required for imports to work properly
  run: python -m venv test_env

Regularly audit configuration files to catch drift between local development tools and CI/CD pipeline settings.


Provide contextual guidance

Documentation should provide clear contextual information that helps users understand when they need to take specific actions versus when configurations are automatically handled. Include deployment-specific details and maintain consistent cross-referencing syntax throughout.

When documenting configuration options, specify the conditions under which manual setup is required:

| Environment Variable | Type | Description |
| -------------------- | ---- | ----------- |
| `NEXT_PUBLIC_ENABLE_NEXT_AUTH` | Required | Used to enable NextAuth service. Set to `1` to enable; changing this setting requires recompiling the application. Users deploying with the `lobehub/lobe-chat-database` image have this configuration added by default. |

For cross-references, use consistent linking syntax that matches the existing documentation structure:

This configuration is done in the environment for each [model providers](/docs/self-hosting/environment-variables/model-provider).

This approach reduces user confusion by clearly indicating when manual intervention is needed and ensures documentation maintains professional consistency.


Avoid privileged installations

Always recommend user-level package installations rather than using administrative/root privileges. Installing packages with elevated permissions can compromise system security and stability. Documentation and scripts should explicitly guide users toward safer installation practices.

Example:

# Installation

## User-level installation (recommended)
```sh
mkdir -p ~/.local/share/npm-packages
npm config set prefix ~/.local/share/npm-packages
export PATH=~/.local/share/npm-packages/bin:$PATH
npm install -g my-package

We recommend installing this package as a regular user, not as an administrative user like root. Installing as a regular user helps maintain your system’s security and stability.


---

## Environment-specific configuration handling

<!-- source: lobehub/lobe-chat | topic: Configurations | language: Shell | updated: 2025-02-26 -->

When writing configuration scripts, ensure they handle environment-specific differences properly by using predefined path variables and adapting commands for different operating systems. Use consistent variable naming for paths that may vary between environments, and implement OS detection when commands have different syntax across platforms.

For path management, always use predefined variables when referencing configuration files:
```bash
SUB_DIR="docker-compose/local"
FILES=(
    "$SUB_DIR/docker-compose.yml"
    "$SUB_DIR/init_data.json"
    "$SUB_DIR/searxng-settings.yml"
)

For cross-platform compatibility, detect the operating system and adapt commands accordingly:

if [[ "$OSTYPE" == "darwin"* ]]; then
    # macOS
    SED_COMMAND="sed -i ''"
else
    SED_COMMAND="sed -i"
fi

This approach ensures configuration scripts work reliably across different environments while maintaining consistency in path handling and command execution.


Next.js auth configuration

Follow auth.js standardized environment variable naming conventions and use explicit function declarations for OAuth providers. Use the AUTH_[PROVIDER_ID]_ID format for environment variables as auth.js automatically reads these. Avoid deprecated naming patterns that will be removed in future versions. Explicitly declare scope and profile handling functions rather than relying on defaults.

Example:

// Use standardized environment variables (auto-read by auth.js)
// AUTH_FEISHU_ID=your_app_id
// AUTH_FEISHU_SECRET=your_secret

function Feishu(): OAuthConfig<FeishuProfileResponse> {
  return {
    authorization: {
      params: {
        scope: '', // Explicitly declare scope
      },
      url: 'https://accounts.feishu.cn/open-apis/authen/v1/authorize',
    },
    // Explicitly declare profile function
    profile(profileResponse) {
      const profile = profileResponse.data;
      return {
        id: profile.union_id,
        image: profile.avatar_url,
        name: profile.name,
        providerAccountId: profile.union_id,
      };
    },
    // ... other config
  };
}

For client-side auth components, prefer dynamic imports to optimize bundle size:

const { signOut } = await import("next-auth/react");

API parameter design

Design API methods with structured object parameters instead of ordered parameters or loose typing. Use proper TypeScript types rather than any, and consider parameter patterns that enhance safety and flexibility.

Key principles:

Example transformation:

// Before: Ordered parameters with loose typing
page.goto = async (url: string, options?: any) => { ... }

// After: Proper typing and structured approach
page.goto = async (url: string, options?: GotoOptions) => { ... }

// Before: Multiple ordered parameters
resolveLLMClient(llmClient, modelName, requestId)

// After: Object parameter with proper typing
resolveLLMClient({ 
  llmProvider, 
  modelName, 
  requestId 
}: { 
  llmClient?: LLMClient, 
  modelName?: AvailableModel, 
  requestId?: string 
})

This approach improves API discoverability, reduces parameter ordering mistakes, and makes future extensions easier without breaking existing code.


Compatible null annotations

When annotating optional or nullable types in Python, ensure compatibility across all supported Python versions. For codebases supporting Python 3.9:

  1. Add from __future__ import annotations at the top of files using the union type syntax:
    from __future__ import annotations
       
    class ExInfo:
        name: str
        retry: bool
        description: str | None
    
  2. Alternatively, use typing.Optional[X] instead of X | None syntax:
    import typing
       
    class CoderPrompts:
        repo_content_prefix: typing.Optional[str] = """Here are summaries..."""
    

This ensures proper null handling with type annotations while maintaining backward compatibility with Python 3.9, preventing runtime errors like TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'.


Dependency lock file management

Always commit dependency lock files (poetry.lock, package-lock.json, etc.) to version control and maintain their consistency across development environments. Lock files ensure reproducible builds and prevent environment mismatches that can cause unexpected changes or build failures.

Before updating lock files, ensure your local environment matches the project’s requirements by running the appropriate install command first. For Poetry projects, run poetry install before poetry lock to avoid introducing unrelated changes from environment mismatches.

Example workflow for Poetry:

# First, sync your environment with the existing lock file
poetry install

# Then update dependencies if needed
poetry lock

# Commit both pyproject.toml and poetry.lock
git add pyproject.toml poetry.lock

Never add lock files to .gitignore as they are essential for maintaining consistent dependency versions across all development and deployment environments.


consistent naming patterns

Maintain consistent naming conventions within related groups of identifiers. When naming related variables, functions, or constants, use the same naming pattern and style to improve code readability and maintainability.

Apply consistent patterns for:

Example from discussions:

// Good: Consistent environment variable naming
FEISHU_APP_ID: process.env.FEISHU_APP_ID,
FEISHU_APP_SECRET: process.env.FEISHU_APP_SECRET,

// Good: Consistent database field naming  
emailVerifiedAt: timestamptz('email_verified_at'),
clerkCreatedAt: timestamptz('clerk_created_at'),

// Good: Specific, descriptive function names
initAgentRuntimeWithUserPayload() // Clear object and action

// Good: Context-appropriate naming
// Config files use snake_case
embedding_model: DEFAULT_FILE_EMBEDDING_MODEL_ITEM,
// Code variables use camelCase  
embeddingModel: config.embedding_model,

This consistency reduces cognitive load when reading code and makes the codebase more predictable for developers.


preserve error context

Always maintain complete error information when logging or re-throwing errors to enable effective debugging and monitoring. This includes using structured logging instead of console methods, chaining original errors when throwing new ones, and ensuring underlying errors are not masked by generic error handling.

When logging errors, use structured logging with the error object:

// Instead of
console.error(`There was an error searching for content: ${error.message}`);

// Use
logger.error(`There was an error searching for content`, { error });

When re-throwing errors, preserve the original error context:

// Instead of
throw new Error("Failed to convert rawHtml to UTF-8");

// Use  
throw new Error("Failed to convert rawHtml to UTF-8", { cause: error });

Avoid silently continuing on failures that should be propagated - throw errors to capture the correct context rather than masking underlying issues with generic error messages or type errors.


validate environment variables early

Environment variables should be validated at startup or module initialization rather than at runtime usage. Use non-null assertion operators or explicit validation checks to fail fast when required configuration is missing, preventing delayed runtime errors and making configuration issues immediately apparent during development and deployment.

Instead of logging errors and continuing execution:

const url = process.env.SEARXNG_ENDPOINT as string;
if (!url) {
  console.error(`SEARXNG_ENDPOINT environment variable is not set`);
}
// Code continues and may fail later...

Use non-null assertion for required variables:

const url = process.env.SEARXNG_ENDPOINT!;

Or implement explicit validation at module initialization:

if (!process.env.SEARXNG_ENDPOINT) {
  throw new Error('SEARXNG_ENDPOINT environment variable is required');
}

This approach ensures configuration problems are caught early in the application lifecycle rather than causing mysterious runtime failures.


API endpoint simplicity

Design API endpoints with concise, direct naming that clearly communicates their purpose without unnecessary verbosity. Avoid redundant prefixes or overly descriptive names that make endpoints harder to remember and use. Choose built-in language features over custom implementations when possible to improve reliability and maintainability.

For endpoint naming, prefer the core functionality over implementation details:

// Avoid verbose prefixes
v1Router.post("/generate-llmstxt", ...)  // ❌ Too verbose

// Prefer direct, clear naming  
v1Router.post("/llmstxt", ...)          // ✅ Concise and clear

For implementation, leverage built-in APIs over custom logic:

// Avoid custom regex for URL handling
const isCompleteUrl = new RegExp('^(?:[a-z+]+:)?//', 'i');
if (!isCompleteUrl.test(link)){
  link = this.baseUrl + link;
}

// Use built-in URL constructor
const url = new URL(link.trim(), this.baseUrl);  // ✅ Simpler and more reliable

This approach improves developer experience by making APIs more intuitive to use and implementations easier to understand and maintain.


Leverage TypeScript null safety

Use TypeScript’s type system proactively to prevent null and undefined issues at compile time rather than handling them reactively at runtime. This includes using exhaustive pattern matching, explicit type annotations, and avoiding type casting that can hide null safety problems.

Key practices:

Example of good null safety:

// Instead of type casting that hides null issues
return cachedResponse as T;

// Use explicit typing
const cachedResponse: AnthropicTransformedResponse | undefined = this.cache.get(...);
if (cachedResponse) {
  return cachedResponse;
}

This approach catches potential null/undefined issues during development rather than discovering them at runtime.


preserve exception context

When handling exceptions, preserve the original exception context and provide clear, actionable error information. Avoid creating new exceptions that lose important details from the original error, and replace generic error handling (like assertions) with specific, user-friendly messages.

Key practices:

Example of what NOT to do:

# Loses original exception context
except RateLimitError as e:
    raise RateLimitError(RATE_LIMIT_ERROR_MESSAGE, response=e.response, body=e.body)

# Generic assertion without clear message
assert condition or action

Example of better approach:

# Preserve context with logging
except RateLimitError as e:
    logger.error(RATE_LIMIT_ERROR_MESSAGE)
    raise  # Re-raise original exception

# Clear error message
if not (condition or action):
    raise ValueError("At least one of --condition or --action is required")
    set_exit_status(1)

This ensures that debugging information is preserved while still providing clear feedback to users about what went wrong and how to fix it.


AI dependency classification

When adding AI/ML libraries to a project, carefully consider whether they belong in dependencies or devDependencies. Libraries used for examples, experimentation, or development tooling should be classified as devDependencies to avoid bloating production bundles. Maintain consistency by avoiding install scripts in package.json for dev-only AI libraries.

Example:

// Correct - AI libraries for examples/development
"devDependencies": {
  "@langchain/core": "^0.3.40",
  "@langchain/openai": "^0.4.4"
}

// Avoid install scripts for dev dependencies
"scripts": {
  "example": "npm run build-dom-scripts && tsx examples/example.ts"
  // Not: "langchain": "npm install @langchain/core @langchain/openai && ..."
}

This ensures production deployments only include necessary AI dependencies while keeping development and example code properly isolated.


Document configuration decisions

When making configuration changes, especially those involving version specifications or constraints, include explanatory comments with links to relevant issues, PRs, or documentation. This provides context for future maintainers and makes the reasoning behind configuration decisions transparent and traceable.

For dependency versions, document why specific version constraints were chosen:

dependencies:
  - together>=1.1.0  # Use >= for compatibility, see issue #236

For CI/CD matrices, explain version selection rationale:

strategy:
  matrix:
    python-version: ["3.11", "3.12"]  # Dropped 3.10 support, see PR #123

This practice helps team members understand the historical context of configuration decisions and prevents unnecessary changes or confusion during future updates.


Prevent uv Overwrites

When CI workflows mix multiple uv steps (e.g., install built wheels, then run tests/lint), make dependency installation deterministic and prevent later steps from overwriting earlier artifact installs.

Apply these rules:

Example pattern (wheel install + tests without overwriting):

# Install built wheel artifacts
uv pip install dist/*.whl

# Prevent later uv operations (including under uv run) from syncing/overwriting
export UV_NO_SYNC=true

# Run tests (may internally call uv run)
make tests  # should behave like: uv run --group test pytest ...

For group-scoped test deps, prefer:

uv sync --only-group test
# then run tests
uv run pytest

This avoids the common CI failure mode where a built wheel install is replaced by the local project (or where earlier dependency changes vanish after a later uv run).


prefer lazy computation

Avoid precomputing expensive operations when they may not be needed, especially for large datasets. Instead, compute values on-demand when they are actually required. This prevents unnecessary work and improves performance for scenarios where only a subset of computed values will be used.

When designing algorithms, resist the temptation to use oversimplified heuristics or “quick fixes” that may create edge cases. Take time to implement proper solutions rather than relying on magic numbers or hacky workarounds.

Example of the problem:

// Bad: Precomputing XPaths for all nodes
for (const node of nodes) {
  if (node.backendDOMNodeId !== undefined) {
    const xpath = await getXPathByResolvedObjectId(cdpClient, objectId);
    node.xpath = xpath; // May never be used
  }
}

// Good: Compute XPaths only when needed
async function getXPathForNode(node: AXNode): Promise<string> {
  if (!node.xpath && node.backendDOMNodeId) {
    node.xpath = await getXPathByResolvedObjectId(cdpClient, node.backendDOMNodeId);
  }
  return node.xpath;
}

This approach scales better with large datasets and avoids wasted computation cycles on unused data.


Avoid hardcoded configurations

Always parameterize values that might vary across different environments or users instead of hardcoding them in your code. This applies to API endpoints, regions, dimensions, credentials, and other configuration values.

When providing fallbacks to environment variables, use nullish coalescing (??) to only override missing values rather than replacing all values if any are missing:

// ❌ Don't do this
if (!id || !secret || !uri) {
  id = getEnvironmentVariable("OUTLOOK_CLIENT_ID");
  secret = getEnvironmentVariable("OUTLOOK_CLIENT_SECRET");
  uri = getEnvironmentVariable("OUTLOOK_REDIRECT_URI");
}

// ✅ Do this instead
id = id ?? getEnvironmentVariable("OUTLOOK_CLIENT_ID");
secret = secret ?? getEnvironmentVariable("OUTLOOK_CLIENT_SECRET");
uri = uri ?? getEnvironmentVariable("OUTLOOK_REDIRECT_URI");

For service defaults, prefer leaving values unset when possible and let the backend/service set the defaults. This prevents issues when service providers change their best practices:

// ❌ Don't hardcode dimensions, regions, endpoints, etc.
vectorSearchDimensions: 1536, // Hardcoded to ada-002's size

// ✅ Make these configurable via parameters
vectorSearchDimensions: config.dimensions || embeddings.dimensions,

When integrating with SDKs, only pass overridden values and avoid setting unnecessary defaults:

// ❌ Don't do this
const app = new FirecrawlApp({ apiKey: this.apiKey, apiUrl: "https://api.firecrawl.dev" });

// ✅ Do this instead
const params = { apiKey: this.apiKey };
if (this.apiUrl !== undefined) {
  params.apiUrl = this.apiUrl;
}
const app = new FirecrawlApp(params);

Robust LLM Integration

When integrating LLMs/embeddings into production code, treat the model as unreliable: enforce a stable IO contract (especially JSON), validate and safely recover from format mismatches, and route model calls through the project’s unified abstractions with configurable parameters.

Apply this checklist: 1) Make LLM outputs contract-safe

Example (defensive JSON parsing):

import json, re
from typing import Optional, Dict

def parse_llm_json(text: str) -> Dict:
    # 1) Prefer ```json ... ```
    code_block = re.search(r"```json\s*(.*?)\s*```", text, re.S|re.I)
    candidate = code_block.group(1) if code_block else None

    # 2) Fallback: first JSON object
    if not candidate:
        obj = re.search(r"\{.*?\}", text, re.S)
        candidate = obj.group(0) if obj else ""

    if not candidate:
        return {}

    try:
        data = json.loads(candidate)
    except json.JSONDecodeError:
        return {}

    # 3) Validate minimum contract
    if not isinstance(data, dict):
        return {}
    return data

2) Never call provider SDKs directly in core business logic

3) Keep embeddings/models configurable and extensible

4) Keep message/history handling consistent

5) Add fallback behavior for empty/failed vector sub-results

This standard prevents production breakage from minor LLM formatting drift, improves portability across LLM providers, and makes embedding/model changes safe and configuration-driven.


Catch Expected Exceptions

When handling failures, avoid broad try/except that hides root causes. Catch only the exceptions you expect, log a warning (with enough context to debug), and preserve the original error/stack trace. For unsupported/unimplemented functionality or dependency/version mismatches, fail explicitly with clear, actionable error messages.

Practical rules:

Example pattern:

import json
import logging
logger = logging.getLogger(__name__)

async def try_text2gql(text, intent_interpreter, text2cypher, graph_adapter):
    try:
        intention = await intent_interpreter.translate(text)
        interaction = await text2cypher.translate(json.dumps(intention))
        query = interaction.get("query", "")
        if "LIMIT" not in query:
            query += " LIMIT 10"
        return graph_adapter.query(query=query)
    except (KeyError, ValueError) as e:  # expected failures only
        logger.warning("text2gql failed; falling back. text=%r err=%s", text, e)
        return None

This keeps behavior predictable, makes production issues diagnosable, and ensures that truly unexpected bugs are not masked.


Null-Safe Data Access

Write code so nullable/missing data can’t cause runtime errors.

Apply these rules: 1) Declare nullability in types

2) Use safe dict/JSON access

3) Guard empty sequences before indexing

4) Use is not None instead of truthiness for config inclusion

Example:

from typing import Optional

def parse_intent(payload: dict) -> Optional[str]:
    # key may be missing -> use get
    return payload.get("rewrited_question")

def handle_response(r):
    # choices may be missing/empty -> guard before indexing
    choices = r.get("choices") if isinstance(r, dict) else getattr(r, "choices", None)
    if not choices:
        return None
    first = choices[0]
    return getattr(first.delta, "content", None)

def build_config(cfg_obj):
    config_dict = {}
    for key in cfg_obj.model_dump().keys():
        value = getattr(cfg_obj, key)
        if value is not None:  # not: if value:
            config_dict[key] = value
    return config_dict

Outcome: fewer KeyError, IndexError, and silent config-misbehavior, while making null/empty cases explicit and testable.


Throw meaningful errors

Always throw specific, actionable errors instead of returning unexpected values or simply logging issues. Error messages should be clear, concise, and contain the exact reason for failure without redundancy.

Consider these practices:

  1. When a function can’t perform its task, throw an error rather than returning a default value: ```typescript // Bad _combineLLMOutput(): Record<string, any> | undefined { return []; // Returns unexpected empty array }

// Good _combineLLMOutput(): Record<string, any> | undefined { throw new Error(“AzureMLChatOnlineEndpoint._combineLLMOutput called, but is not implemented.”); }


2. Avoid redundant error prefixes that will be repeated in logs:
```typescript
// Bad - creates redundant messages
if (!response.ok) {
  throw new Error(`Error authenticating with Reddit: ${response.statusText}`);
}

// Good - concise and clear
if (!response.ok) {
  throw new Error(response.statusText);
}
  1. Propagate errors instead of just logging them to allow proper handling up the call stack: ```typescript // Bad - swallows the error try { await this.collection.deleteMany({}); } catch (error) { console.log(“Error clearing sessions:”, error); }

// Good - allows callers to handle the error try { await this.collection.deleteMany({}); } catch (error) { console.error(“Error clearing sessions:”, error); throw error; // Re-throw or throw a more specific error }


4. Preserve error structures expected by error handling mechanisms:
```typescript
// Bad - overwrites properties needed for retry logic
(error as any).details = { /* ... */ };

// Good - maintains expected structure
(error as any).response = res;

Well-designed error handling improves debugging efficiency and creates a more robust application.


preserve thread-local state

When launching threads in DSPy, ensure that child threads inherit the parent thread’s local overrides to maintain consistent behavior across concurrent executions. DSPy uses thread-local settings that must be properly propagated to avoid subtle runtime issues.

Critical Implementation Pattern:

from dspy.dsp.utils.settings import thread_local_overrides

def _wrap_function(self, function):
    def wrapped(item):
        # Capture parent thread's overrides
        original_overrides = thread_local_overrides.overrides
        # Create isolated copy for this thread
        thread_local_overrides.overrides = thread_local_overrides.overrides.copy()
        try:
            return function(item)
        finally:
            # Restore original state
            thread_local_overrides.overrides = original_overrides
    return wrapped

# When launching threads, pass parent overrides:
parent_overrides = thread_local_overrides.overrides.copy()
executor.submit(cancellable_function, parent_overrides, item)

Why This Matters:

When to Apply:

This pattern ensures that DSPy’s internal state management works correctly across all concurrent operations, preventing hard-to-debug issues that only manifest under specific threading conditions.


Comprehensive AI documentation

When documenting AI integrations, provide comprehensive examples that showcase all common initialization and usage patterns. Documentation should include:

  1. All initialization methods (direct constructor, .fromDocuments, etc.)
  2. Links to related components and services
  3. Complete usage examples with different options
  4. Adherence to standardized documentation templates

For example, when documenting a vector store integration:

// Show direct initialization
const vectorStore = new AIVectorStore(new SomeEmbeddings());

// Also show initialization from documents
const documents = [new Document({ pageContent: "text" })];
const vectorStoreFromDocs = await AIVectorStore.fromDocuments(
  documents,
  new SomeEmbeddings()
);

// Demonstrate common operations
const results = await vectorStore.similaritySearch("query", 5);

This practice ensures developers can quickly understand and implement AI integrations without needing to search through multiple documentation pages or source code.


Dependency version management

Use semantic versioning ranges for dependencies instead of “latest” or overly broad ranges. Avoid “latest” as it can cause caching issues during updates. Maintain minimum required version semantics to ensure compatibility - if your code requires features from version 4.4, specify “^4.4” rather than “^4” to prevent runtime errors when using tools like pnpm with resolution-mode set to lowest. When upgrading dependencies, prefer semantic ranges (e.g., “^0.34.2”) over exact version pinning unless there are specific compatibility concerns.

Example:

{
  "dependencies": {
    //  Avoid - caching issues
    "lucide-react": "latest",
    //  Avoid - loses minimum version semantics  
    "zustand": "^4",
    //  Good - preserves minimum required version
    "zustand": "^4.4",
    //  Good - semantic range for upgrades
    "lucide-react": "^0.469.0"
  }
}

abstract environment variables

Avoid directly referencing environment variables throughout your codebase. Instead, abstract them into named constants with sensible defaults at module boundaries. This improves readability, makes configuration explicit, and prevents scattered environment variable access.

Create constants that handle the environment variable logic once:

// Good: Abstract with defaults
const DEFAULT_EVAL_MODELS = process.env.EVAL_MODELS 
  ? process.env.EVAL_MODELS.split(",") 
  : ["gpt-4o", "claude-3-5-sonnet-latest"];

const EXPERIMENTAL_EVAL_MODELS = process.env.EXPERIMENTAL_EVAL_MODELS
  ? process.env.EXPERIMENTAL_EVAL_MODELS.split(",")
  : [];

// Then reference the constants
const models = useExperimental ? EXPERIMENTAL_EVAL_MODELS : DEFAULT_EVAL_MODELS;

// Bad: Direct references scattered throughout
const models = process.env.EVAL_MODELS?.split(",") || ["gpt-4o", "claude-3-5-sonnet-latest"];

Remember that process.env.VARIABLE defaults to undefined when not present - avoid adding unnecessary || undefined or required assertions (!) unless the variable is truly mandatory. Use descriptive constant names that clearly indicate their purpose and scope.


Configure workflow triggers

Ensure GitHub Actions workflows are triggered appropriately by configuring branch patterns and path filters to balance CI efficiency with comprehensive coverage. Workflows should run on all relevant branches (not just main) while using path filters to avoid unnecessary executions.

Configure triggers to run on pushes to any branch when you need broad coverage:

on:
  push:
    branches: ["*"]  # or specific patterns like "dev/*"

Use path filters to limit runs to relevant file changes:

on:
  push:
    branches: ["*"]
    paths:
      - "lib/**"
      - "evals/**"

Avoid overly restrictive triggers that only run on main branch, as this prevents catching issues early in the development cycle. Consider that some changes (like types) may be caught by other build processes (tsc, eslint) and don’t always need separate CI runs.


Performance Guardrails

When implementing knowledge-graph storage/search, proactively prevent expensive work and payload bloat by following these rules:

1) Minimize returned payloads (especially vectors)

2) Make one-time setup idempotent

3) Batch compute for similarity search

4) Bound expensive retrieval early

5) Avoid repeated iteration during persistence

Example (index-create guard pattern):

class Adapter:
    def __init__(self):
        self._chunk_vector_index_created = False
        self._entity_vector_index_created = False

    def upsert_chunks(self, chunks):
        # ... upsert data ...
        if not self._chunk_vector_index_created:
            self._create_chunk_vector_index()
            self._chunk_vector_index_created = True

    def upsert_entities(self, entities):
        # ... upsert data ...
        if not self._entity_vector_index_created:
            self._create_entity_vector_index()
            self._entity_vector_index_created = True

Consistent naming conventions

Maintain consistent and explicit naming conventions across your codebase that reflect:

  1. Component dependencies: Class/function names should explicitly indicate their external dependencies and integrations to improve clarity and avoid confusion.
    // INCORRECT: Doesn't indicate dependency on Unstructured API
    class DropboxLoader { ... }
       
    // CORRECT: Explicitly indicates dependency
    class DropboxUnstructuredLoader { ... }
    
  2. Current parameter naming: Use the current preferred parameter names rather than deprecated ones, and be consistent across all instances.
    // INCORRECT: Using deprecated parameter name
    const model = new ChatOpenAI({
      modelName: "gpt-azure",
    });
       
    // CORRECT: Using current parameter name
    const model = new ChatOpenAI({
      model: "gpt-azure",
    });
    
  3. Standard formatting patterns: Follow standard naming patterns for environment variables and configuration parameters, with proper word separation.
    // INCORRECT: Concatenated words without separation
    process.env.GOOGLE_DRIVE_CREDENTIALSPATH
       
    // CORRECT: Words properly separated with underscores
    process.env.GOOGLE_DRIVE_CREDENTIALS_PATH
    

This consistent approach to naming makes your code more maintainable, reduces confusion for other developers, and provides better clarity about component dependencies and behavior.


Avoid async race conditions

Ensure proper async/await handling and consider concurrent execution patterns to prevent race conditions and improve performance. When working with asynchronous operations, always use await for promises and avoid mixing promise chains with async/await syntax. Additionally, identify opportunities to run independent operations concurrently rather than sequentially.

Common issues to watch for:

Example of problematic code:

private static loadWebSocket() {
  try {
    return require('isows').WebSocket;
  } catch {
    try {
      return import('isows').then(m => m.WebSocket); // Missing await, can cause race condition
    } catch {
      // fallback
    }
  }
}

Better approach:

private static async loadWebSocket() {
  try {
    return require('isows').WebSocket;
  } catch {
    try {
      const module = await import('isows'); // Proper await handling
      return module.WebSocket;
    } catch {
      // fallback
    }
  }
}

For independent operations, prefer concurrent execution:

// Instead of sequential
const sitemapLinks1 = await this.tryFetchSitemapLinks(url, "/sitemap.xml");
const sitemapLinks2 = await this.tryFetchSitemapLinks(url, "/sitemap_index.xml");

// Use concurrent execution
const [sitemapLinks1, sitemapLinks2] = await Promise.all([
  this.tryFetchSitemapLinks(url, "/sitemap.xml"),
  this.tryFetchSitemapLinks(url, "/sitemap_index.xml")
]);

preserve raw network data

Always preserve raw network response data early in the processing pipeline before applying any transformations or parsing. Once network data is processed or encoded, critical information may be permanently lost and cannot be recovered later.

This is particularly important for:

Example of the problem:

// BAD: Encoding conversion after string processing
function encodeRawHTML(document: Document): Document {
  // At this point, UTF-8 misencoding is "too destructive" 
  // to recover original Shift_JIS content
  const decoder = new TextDecoder(charset);
  document.rawHtml = decoder.decode(stringData); // Information already lost
}

// BAD: Using processed HTML for link extraction
linksOnPage = extractLinks(html, urlToScrap); // May miss links from raw content

Move encoding and parsing operations to earlier parts of the stack where you still have access to the raw network buffers. This prevents permanent data loss and ensures all network content is available for processing.


AI provider naming standards

Maintain consistent and proper naming conventions for AI model providers throughout code, documentation, and comments. Use official capitalization (e.g., “OpenAI” not “openai”) and provide clear documentation about which AI services are required versus optional.

When documenting AI model requirements:

Example:

// Good: Proper capitalization and clear requirements
// Stagehand requires OpenAI as a model provider
const stagehand = new Stagehand({
  env: "LOCAL",
});

// Documentation should state:
// "NOTE: Stagehand client will default to OpenAI if these are not specified"

This ensures professional presentation, reduces confusion about service requirements, and maintains consistency across the codebase when referencing external AI providers.


Semantic Naming Rules

Use names that accurately reflect meaning, scope (internal vs external), and responsibility—and keep them consistent with existing/base APIs.

Apply these rules: 1) Internal fields vs user-visible concepts: If a property is implicit/internal, name it consistently with an underscore prefix and ensure all relevant types expose it.

2) Match the data type/role to the identifier: Don’t call vectors “keywords” or “text” if the value is embeddings.

3) Responsibility-revealing function names: The function name must describe what it actually does.

4) Avoid duplicate/conflicting base names: Don’t introduce new variants of fields already defined by base classes.

5) Avoid ambiguous configuration parameter names: Prefer names that won’t be mistaken for other common concepts.

6) Use pythonic module/file naming: Ensure filenames follow standard Python conventions (lowercase with underscores, no camel-case file names).

If you’re unsure, ask: “Can another developer infer the value’s meaning and the function’s side effects from the name alone?” If not, rename it.


Configurable Search Parameters

All retrieval/exploration code (graph + vector/ANN) must be implemented as a staged algorithm with explicit, configurable search hyperparameters, and with correct graph element semantics.

Apply these rules: 1) Make ANN/graph search hyperparameters explicit

2) Limit at the right stage (two-step retrieval)

3) Ensure graph element types are unambiguous

Example pattern (staged retrieval + explicit params):

def search_with_two_stage_explore(graph_store, keywords, *, top_k, ef_search, one_hop_limit):
    # Stage 1: constrained exploration (local units)
    subgraph = graph_store.explore(
        subs=keywords,
        limit=one_hop_limit,
        search_method="entity_search",
        # explicit ANN/graph knobs
        top_k=top_k,
        hnsw_ef_search=ef_search,
    )

    # Stage 2: deterministic expansion (structure completion)
    chunks = [v.name for v in subgraph.vertices()]
    full_structure = graph_store.explore(
        subs=chunks,
        limit=one_hop_limit,
        search_method="path_completion",
    )
    return full_structure

If implementing graph element classification used by traversal, ensure edge/vertex semantics are explicit:

class GraphElemType(Enum):
    # ...
    def is_vertex(self):
        return self in {GraphElemType.DOCUMENT, GraphElemType.CHUNK, GraphElemType.ENTITY}
    def is_edge(self):
        return self in {GraphElemType.INCLUDE, GraphElemType.NEXT, ...}  # enumerate

Outcome: predictable performance, controllable quality/relevance, and correct traversal behavior for algorithms/search over graphs and vector indexes.


Dependency classification standards

Properly classify dependencies in package.json according to their usage pattern and project guidelines. This ensures correct build behavior, optimizes package size, and prevents dependency conflicts.

Example of correct dependency classification:

// package.json
{
  "dependencies": {
    // Only runtime requirements
  },
  "peerDependencies": {
    "@libsql/client": "^0.14.0" // Optional integration
  },
  "devDependencies": {
    "@libsql/client": "^0.14.0", // Also needed for testing
    "@cloudflare/workers-types": "^4.20240502.0" // Types only
  }
}

For third-party integrations, follow the project’s integration guidelines to determine the appropriate dependency type. Avoid adding dependencies when equivalent functionality exists natively.


Constructor over setter

Prefer passing configuration through constructor parameters rather than setting properties after instantiation. This makes APIs more predictable, enables immutability, and clearly communicates required dependencies at creation time. Additionally, use consistent method naming conventions like .invoke() for primary API methods.

Instead of this:

const loader = new GoogleDriveLoader();
loader.recursive = true;
loader.folderId = "YourGoogleDriveFolderId";

Do this:

const loader = new GoogleDriveLoader({
  recursive: true,
  folderId: "YourGoogleDriveFolderId"
});

Similarly, when adding methods to an API class, prefer descriptive action names like invoke() over generic terms like call(). This creates a more intuitive API that follows established patterns across the ecosystem.


Simplify code organization

Maintain clean code organization by eliminating unnecessary abstractions and preventing codebase fragmentation. This applies both at the component level and module level:

  1. Avoid creating wrapper components that don’t add functionality
    // Don't do this:
    function InstallationInfo({ children }) {
      return <Npm2Yarn>{children}</Npm2Yarn>;
    }
       
    // Do this instead:
    <Npm2Yarn>{content}</Npm2Yarn>
    
  2. Consolidate related functionality into logical groups rather than creating new isolated entry points:
    // Don't do this:
    "utils/is_openai_tool": "utils/is_openai_tool",
       
    // Do this instead:
    // Add to existing related module like "language_models/base"
    

This approach reduces code complexity, improves maintainability, and makes the codebase easier to navigate and understand.


Pin Docker base versions

Always specify exact version numbers for Docker base images instead of using floating tags like lts or latest. Floating tags can introduce unexpected breaking changes when they automatically update to newer versions, potentially causing build failures or runtime issues in production environments.

Use specific version tags that provide stability and predictable builds:

# Good - pinned to specific version
FROM node:20-slim AS base

# Avoid - floating tag that can change unexpectedly  
FROM node:lts-slim AS base

While pinning versions, establish a regular review process to evaluate and upgrade to newer LTS versions when appropriate, ensuring your applications benefit from security updates and performance improvements without surprise breakages.


Cache key serialization

When implementing caching for functions that accept complex objects (dictionaries with mixed types, Pydantic models, callables), ensure proper cache key generation by filtering out non-serializable objects and converting complex types to serializable formats.

Key requirements:

  1. Filter out callables: Exclude callable objects from cache key generation as they cannot be reliably serialized or hashed
  2. Convert Pydantic models: Transform Pydantic BaseModel instances to dictionaries using .dict() or .schema() methods
  3. Use consistent serialization: Apply deterministic JSON serialization with sorted keys for reliable cache key generation

Example implementation:

def cache_key(request: Dict[str, Any]) -> str:
    # Transform Pydantic models and exclude unhashable objects
    params = {
        k: (v.dict() if isinstance(v, pydantic.BaseModel) else v) 
        for k, v in request.items() 
        if not callable(v)
    }
    return sha256(ujson.dumps(params, sort_keys=True).encode()).hexdigest()

This approach prevents serialization errors like “TypeError: is not JSON serializable" and ensures cache keys remain consistent across different execution contexts. The pattern is essential for caching LLM requests, embedding calls, and other functions that accept complex parameter objects.


Add comprehensive test coverage

When introducing new functionality, always include corresponding test coverage that extends existing test infrastructure and validates the feature across multiple scenarios. This ensures robustness and maintains code quality standards.

Key practices:

Example approach:

# When adding streaming functionality, extend existing test server
# tests/test_utils/server/litellm_server.py - add streaming endpoint

# Create integration test in appropriate location
# tests/streaming.py
def test_streaming_endpoint():
    # Use existing test infrastructure like litellm_test_server
    # Test the complete flow: configure -> run program -> validate stream
    stream = streaming_dspy_program(question=question.text)
    # Validate streaming response format and content

This approach ensures that new features are thoroughly validated and integrate seamlessly with existing systems, reducing the likelihood of regressions and improving overall system reliability.


Keep build scripts portable

Build scripts should remain environment-agnostic and free from personal customizations or assumptions about end-user needs. Avoid including local-specific commands (like clipboard operations) and let consumers make their own decisions about optimizations like minification.

Personal commands like && cat ./lib/dom/bundle.js | pbcopy should be removed as they’re platform-specific and will fail in CI environments or on different operating systems. Similarly, avoid aggressive optimizations like minification in library builds - distributed code should remain readable and debuggable, allowing end users to apply their own build optimizations if needed.

Example of problematic build script:

"bundle-dom-scripts": "esbuild ./lib/dom/index.ts --bundle --outfile=./lib/dom/bundle.js --platform=browser --target=es2015 --minify && cat ./lib/dom/bundle.js | pbcopy"

Better approach:

"bundle-dom-scripts": "esbuild ./lib/dom/index.ts --bundle --outfile=./lib/dom/bundle.js --platform=browser --target=es2015"

This ensures builds work consistently across all environments and maintains code readability for debugging purposes.


Consider SSR impact

When using Next.js dynamic imports, carefully evaluate whether to disable server-side rendering (SSR) based on the component’s purpose and impact on user experience.

Keep SSR enabled (default) when:

Disable SSR (ssr: false) when:

Example:

// ❌ Avoid for layout-affecting components
const CloudBanner = dynamic(() => import('@/features/AlertBanner/CloudBanner'), { ssr: false });

// ✅ Good for error handling
export default dynamic(() => import('@/components/Error'), { ssr: false });

// ✅ Consider for modals
const ModalContent = dynamic(() => import('./ModalContent'), { ssr: false });

The key is preventing layout shifts while ensuring functionality works correctly across SSR and client-side rendering.


AI signature consistency

Ensure AI model signatures maintain consistency between field types and descriptions, and avoid redundant prompting techniques when the desired behavior is already captured in the signature definition.

When defining AI model signatures, field descriptions should accurately reflect the actual data type. For example, if a field accepts List[dspy.Image], the description should indicate “A list of images” rather than “An image”.

Additionally, avoid using redundant prompting techniques like ChainOfThought when the signature already includes fields that capture the desired reasoning or explanation output.

Example of good practice:

class ColorSignature(dspy.Signature):
    """Output the color of the designated image."""
    images: List[dspy.Image] = dspy.InputField(desc="A list of images")
    explanation = dspy.OutputField(desc="Reasoning for color detection")
    color = dspy.OutputField(desc="Detected color")

# Use simple Predict instead of ChainOfThought since explanation field exists
class ColorModule(dspy.Module):
    def __init__(self):
        self.prog = dspy.Predict(ColorSignature)  # Not dspy.ChainOfThought

This approach reduces confusion, eliminates redundancy, and ensures that AI model interfaces are clear and maintainable.


AI dependency management

When integrating AI models and language processing libraries, follow these dependency management best practices:

  1. Use specific model integration packages instead of general-purpose AI SDKs. For example: ```javascript // AVOID direct dependencies like this: // “dependencies”: { // “openai”: “^4.72.0” // }

// RECOMMENDED: Use model-specific packages // Install with: npm install @langchain/openai // “dependencies”: { // “@langchain/openai”: “^x.x.x” // }


2. Don't include AI service libraries as hard dependencies. Follow project contribution guidelines for integrations by making them optional or peer dependencies.

3. When updating AI SDK versions, clearly flag these changes for maintainers to review, as they may impact compatibility or introduce new features that require additional testing.

This approach ensures better maintainability, clearer dependency trees, and more explicit relationships between your project and the AI services it leverages.

---

## Control caching through instantiation

<!-- source: browserbase/stagehand | topic: Caching | language: TypeScript | updated: 2024-11-20 -->

When implementing optional caching functionality, control cache behavior through conditional instantiation at higher abstraction levels rather than adding conditional logic within cache implementations themselves. This approach maintains cleaner separation of concerns and avoids scattered conditional checks throughout cache methods.

Instead of adding enableCaching flags and conditional logic within cache classes:

```typescript
// Avoid this pattern
export class BaseCache<T extends CacheEntry> {
  protected enableCaching: boolean;
  
  protected ensureCacheDirectory(): void {
    if (this.enableCaching && !fs.existsSync(this.cacheDir)) {
      fs.mkdirSync(this.cacheDir, { recursive: true });
    }
  }
}

Prefer conditional instantiation at the consumer level:

// Prefer this pattern
class LLMProvider {
  private cache?: BaseCache<LLMCacheEntry>;
  
  constructor(enableCaching: boolean) {
    this.cache = enableCaching ? new BaseCache() : undefined;
  }
  
  private async makeCall() {
    if (this.cache) {
      // Use cache operations
    }
  }
}

This pattern keeps cache implementations focused on their core responsibility while allowing higher-level components to control when caching is active.


Use standardized logging pattern

Always use the standardized logging pattern with module-level loggers instead of print statements or direct logging calls. This ensures consistent logging behavior, proper log level control, and better debugging capabilities across the codebase.

The standard pattern is:

import logging

logger = logging.getLogger(__name__)
logger.info("Your message here")
logger.warning("Warning message")
logger.debug("Debug info", exc_info=True)  # Include exception info when relevant

Replace print statements with appropriate log levels:

In modules where the dspy logger isn’t available (like dsp folder), follow the same pattern by creating a module-level logger. This maintains consistency and allows proper log level configuration across the entire application.


React hooks best practices

Always call React hooks at the top level of components and custom hooks to comply with the Rules of Hooks. Handle conditional logic inside hook bodies rather than conditionally calling hooks. When optimizing performance, choose the appropriate hook: use useMemo for computed values and useCallback for function references.

Example of proper hook usage:

function useGlobalShortcut() {
  // Call hooks at the top level to comply with the rules of hooks
  const chatStore = useChatStore();
  const navigate = useNavigate();
  const config = useAppConfig();

  useEffect(() => {
    // Early return if not in environment. This way, the hooks are called unconditionally,
    // but the code inside useEffect only runs conditionally
    if (!window.__TAURI__) {
      return;
    }
    
    // Hook logic here...
  }, [chatStore, navigate, config]); // Include all dependencies
}

For optimization, prefer useMemo for computed values over useCallback when the result is not a function reference.


Dynamic API behavior detection

APIs should determine behavior based on runtime request characteristics rather than static configuration flags. This enables multiple API providers and models to coexist and ensures proper handling of provider-specific requirements.

Instead of using static configuration flags, inspect the actual request to determine the appropriate behavior:

// ❌ Avoid: Static configuration-based decisions
if (serverConfig.isAzure) {
  // Azure-specific logic
}

// ✅ Prefer: Runtime request-based decisions  
if (req.nextUrl.pathname.includes("azure/deployments")) {
  // Azure-specific logic detected from request path
}

// ❌ Avoid: Model name-based assumptions
if (!chatPath.includes("gemini-pro")) {
  // Logic based on model name
}

// ✅ Prefer: Functionality-based detection
if (shouldUseStreamMode(request)) {
  // Logic based on actual streaming requirement
}

This approach allows for more flexible API routing, enables multiple providers to work simultaneously, and makes the system more maintainable by reducing coupling between configuration and runtime behavior. Always inspect request paths, parameters, and headers to make informed decisions about API behavior rather than relying on global flags.


Intention-Revealing Naming

Write names that clearly communicate meaning, scope/intent, and project terminology—especially on public APIs/CLI and when calling helpers.

Apply:

Example:

api_type, api_version = cls._get_api_type_and_version(api_type, api_version)
url = cls._get_url("edits", None, api_type=api_type, api_version=api_version)

def _check_polling_response(...):
    ...  # internal by convention

Simplify conditional logic

Break down complex conditional expressions and control flow into simpler, more readable forms. Use early returns and guard clauses to reduce nesting and avoid unnecessary computations. Avoid chaining multiple conditions with   or && operators when the logic can be made clearer through restructuring.

Examples of improvements:

This approach makes code easier to understand, debug, and maintain by reducing cognitive load and making the control flow more explicit.


organize import groups

Imports should be organized into distinct groups with proper spacing for better readability. Group all third-party library imports together in one contiguous block, followed by a blank line, then group all local/relative imports in another block. This separation makes it immediately clear which dependencies are external versus internal to the project.

Example of proper import organization:

// Third-party imports (grouped together)
import { describe, expect, it, Mock, vi } from 'vitest';
import { cleanup, fireEvent, render } from '@testing-library/react';
import '@testing-library/jest-dom/vitest';

// Blank line separator

// Local imports (grouped together)
import AgentsList from './agents-list';
import { NEW_SESSION_ID } from '../chat-header/chat-header';

This organization pattern helps developers quickly understand the external dependencies versus internal module relationships, making the code more “polite” to readers and easier to maintain.


Handle optional dependencies gracefully

When integrating with external AI libraries, models, or services, handle optional dependencies gracefully to avoid affecting users who don’t need those features. Use local imports within class constructors or methods rather than module-level imports, and provide clear error messages when dependencies are missing.

This pattern is essential in AI libraries that integrate with multiple providers (OpenAI, Anthropic, HuggingFace, etc.) where users typically only need a subset of integrations.

Example implementation:

class MistralLM(LM):
    def __init__(self, model: str, **kwargs):
        try:
            import mistralai
        except ImportError as err:
            raise ImportError(
                "The 'mistralai' package is required to use MistralLM. "
                "Install it with 'pip install mistralai'."
            ) from err
        
        super().__init__(model)
        self.client = mistralai.Mistral(api_key=kwargs.get('api_key'))

# Instead of module-level imports that affect everyone:
# import mistralai  # This would cause errors for all users

Benefits:

Apply this pattern consistently across all optional integrations including embedding models, retrieval systems, tracking libraries, and model providers.


Follow documentation standards

Ensure all documentation follows established templates and includes required sections. When referencing components, add links to their documentation pages. Documentation for each component type (like LLMs or vector stores) should follow its specific template format and include standard sections such as “Overview” with links to conceptual guides and reference tables.

When a component is mentioned in documentation text, include a hyperlink to its own documentation:

// Good example with proper cross-referencing
/**
 * The Semantic Cache feature leverages [AzureCosmosDBNoSQLVectorStore](/docs/integrations/vectorstores/azure_cosmosdb_nosql) 
 * which stores vector embeddings of cached prompts for similarity-based searches.
 * 
 * @see For more details, refer to the [Vector Store conceptual guide](/docs/concepts/vector_stores)
 */

Complete documentation should exist for all public APIs and referenced components. If documentation for a referenced component is missing (like JsonOutputFunctionsParser), create it before finalizing the referencing documentation.


Use Adapter Upsert

When writing to a database/graph store, make the storage adapter the source of truth for schema details and persist data idempotently.

Apply these rules:

Example (graph store):

# Bad: callers forcing storage element typing
# graph.upsert_vertex(Vertex(name, description=summary, vertex_type='entity'))

# Good: callers provide only domain data; adapter assigns types
graph.upsert_vertex(Vertex(name, description=summary))

# And when building relations from chunks/documents, route through adapter upsert helpers
graph_adapter.upsert_document_include_chunk(chunk=chunk, doc_vid=doc_vid)
graph_adapter.upsert_chunk_next_chunk(prev_chunk=prev, next_chunk=chunk)

Example (DB config principle):


Documentation Deduping

When updating technical docs, avoid duplicating environment-specific setup or repeated troubleshooting steps. Prefer linking to the canonical upstream documentation for shell/env configuration, and keep only minimal project-specific commands (e.g., where you truly provide “permanent activation” instructions). Also consolidate identical “fix-it” guidance into a single canonical section, using cross-links instead of repeating the same snippet.

Example (keep only required project-specific commands, link the rest):

# Minimal project-specific permanent activation
register-python-argcomplete openai >> ~/.bashrc
register-python-argcomplete openai >> ~/.zshrc

# For other shells or temporary activation, link to upstream docs
# (replace duplicated instruction blocks with the appropriate argcomplete docs link)

Example (deduplicate troubleshooting text):


Measure performance concerns

Before assuming performance issues exist, measure actual execution time and resource usage. When performance problems are confirmed, eliminate unnecessary operations like redundant initializations, blocking operations, or wasteful resource usage.

Use performance measurement tools to validate concerns:

function escapeBrackets(text: string) {
  let begin_time = performance.now();
  const pattern = /(```[\s\S]*?```|`.*?`)|\\\[([\s\S]*?[^\\])\\\]|\\\((.*?)\\\)/g;
  let res = text.replace(pattern, (match, codeBlock, squareBracket, roundBracket) => {
    // ... processing logic
  });
  let endTime = performance.now();
  console.log(`escapeBrackets, string length=${text.length}, time consumed=${endTime - begin_time} ms`);
  return res;
}

Common wasteful operations to eliminate:

Modern JavaScript engines often optimize common patterns like regex compilation, but measurement reveals the actual impact rather than assumptions.


Isolate test environments

Tests should be isolated from the production environment to prevent side effects and ensure reproducibility. This principle has two main applications:

  1. Use proper temporary files: Instead of writing test files to the current directory where they might overwrite real files, use the tempfile module to create isolated test files.

  2. Establish correct directory context: Ensure tests run in the appropriate directory context to prevent location-dependent failures.

Example:

# Good: Use temporary files instead of hardcoded paths
import tempfile
message_file_path = tempfile.mktemp()
main(["--message-file", message_file_path], input=DummyInput(), output=DummyOutput())

# Good: Explicitly set the directory context for tests
with change_dir(testdir):
    # Test code runs in the correct context
    # ...

Following these practices prevents tests from accidentally modifying real files and ensures they’ll run consistently regardless of the current working directory.


Consistent styling approach

Maintain consistency in styling approaches within components and across the codebase. Avoid mixing className and inline styles in the same component - choose one approach and stick with it throughout the component. When working with reusable UI library components, keep them generic by using className for styling rather than adding component-specific inline styles that could pollute the library’s interface.

For example, instead of mixing approaches:

// Avoid mixing styles
<div style={{ position: "relative" }}>
  <pre
    ref={ref}
    style={{
      maxHeight: collapsed ? "400px" : "none",
      overflow: "hidden",
    }}
  >
    <span className="copy-code-button">

Use a consistent approach with className:

// Consistent className usage
<div className="code-container">
  <pre
    ref={ref}
    className={`code-block ${collapsed ? 'collapsed' : 'expanded'}`}
  >
    <span className="copy-code-button">

This improves maintainability, keeps styling logic centralized in CSS files, and maintains clean separation between UI library components and application-specific styling.


Package manager consistency

Maintain consistent package manager usage throughout the project lifecycle. When a project uses yarn (indicated by yarn.lock), avoid committing npm’s package-lock.json file, as having both lock files can cause dependency resolution conflicts and inconsistent builds across different environments.

Key practices:

Example violation:

# Project structure showing both lock files (problematic)
├── package.json
├── yarn.lock          # Using yarn
└── package-lock.json  # Should not exist when using yarn

This practice ensures reproducible builds and prevents confusion about which package manager and dependency versions should be used in different environments.


Use semantically accurate names

Variable, method, and type names should precisely reflect their actual content, purpose, or scope. Names that misrepresent what they contain or do create confusion and make code harder to understand and maintain.

Ensure that:

Example of problematic naming:

// Misleading - suggests full locale but may be partial
import { LocaleType } from "./index";

// Confusing - Norwegian locale named as English
const en: LocaleType = {
  // Norwegian translations...
};

Example of semantically accurate naming:

// Clear - indicates partial implementation
import { PartialLocaleType } from "./index";

// Accurate - matches the actual locale
const no: LocaleType = {
  // Norwegian translations...
};

// Explicit default parameter
export function getHeaders(ignoreHeaders: boolean = false) {
  // ...
}

This practice makes code self-documenting and reduces cognitive load when reading and maintaining the codebase.


Notebook dependency install

When authoring AI/LLM tutorials in Jupyter notebooks, ensure dependency installation is done with correct notebook syntax and that nearby explanatory text is unambiguous.

Example:

# In a notebook cell (ipynb), use the magic:
%pip install langchain_community

# And keep narrative wording clear when describing state:
# "...wraps the model and adds to this message history..."

Use explicit types

在组件/页面代码中保持表达清晰、类型明确,避免冗余与 any

这些规则能提升可读性、减少潜在类型错误,并使代码更易维护。


Configuration design clarity

Design configuration with clear semantics and appropriate scope. Avoid global constants for values that can be handled locally, and ensure configuration parameters have logical, non-contradictory meanings.

Avoid unnecessary global configuration constants:

# Instead of:
DEFAULT_PORT = 8000
DEFAULT_INDEX = True  # Global constants

# Consider handling defaults in-context:
def setup_server(port=8000, enable_indexing=False):
    # Handle defaults locally where they're used

Design clear configuration interfaces:

# Avoid contradictory parameters:
# Bad: Indexer(perform_indexing=True, force_disable_indexing=True)

# Better: Handle configuration logic at application level:
if params.index and not params.force_disable:
    indexer = Indexer(index_json_file=path)
    # Use indexer
else:
    # Skip indexing entirely

Configuration should be intuitive - parameters shouldn’t require mental gymnastics to understand their combined effect. Keep configuration logic at the appropriate architectural level rather than pushing contradictory options down to individual components.


Externalize configuration values

Always externalize configuration values rather than hardcoding them directly in the code. This improves maintainability, enables easier configuration changes, and ensures consistency across the codebase.

Key practices:

  1. Replace hardcoded strings with values retrieved from a centralized configuration system
  2. Ensure the correct configuration keys are used for specific components
  3. Use standardized utility functions that honor user configuration settings

Example:

# Instead of this:
main_system = """Act as an expert software developer."""

# Do this:
from . import prompt_manager
yaml_prompt_entry = prompt_manager.get_prompt_value('ComponentName', 'main_system')

# And when reading files, respect user configuration:
# Instead of:
with open(file_path, 'r', encoding='utf-8') as file:
    content = file.read()
    
# Use utilities that honor user settings:
content = io.read_text(file_path)  # Respects --encoding setting

This approach makes the codebase more flexible, easier to maintain, and respectful of user-defined settings.


Prevent security vulnerabilities

Proactively identify and prevent common security vulnerabilities in code, particularly around sensitive data handling and input validation. Avoid logging sensitive information like API keys, tokens, or passwords that could be exposed in log files. Implement robust input validation using proper parsing methods rather than simple string operations that can be bypassed.

For sensitive data logging:

// ❌ Avoid - exposes sensitive data
console.log("[Auth] use system api key", systemApiKey);

// ✅ Better - log without sensitive details  
console.log("[Auth] use system api key");

For input validation:

// ❌ Avoid - can be bypassed with crafted URLs
if (!endpoint || !endpoint.endsWith("upstash.io")) {

// ✅ Better - use proper URL parsing
try {
  if (!(new URL(endpoint).hostname.endsWith('.upstash.io'))) {
    throw new Error('Invalid endpoint');
  }
} catch (e) {
  throw new Error('Invalid URL format');
}

Always consider how an attacker might exploit weak validation or gain access to sensitive information through logs, error messages, or other data exposure points.


Implement stable sorting

When implementing sorting algorithms for collections, ensure stable and predictable ordering to avoid inconsistencies from operations like Object.values(). Use multi-level sorting criteria and consider sequence-based approaches for complex ordering requirements.

Key principles:

  1. Avoid unstable ordering: Don’t rely on Object.values() or similar operations that may produce inconsistent results across different executions
  2. Implement multi-level sorting: First sort by primary criteria (e.g., custom vs default), then by secondary criteria (e.g., alphabetical order)
  3. Use sequence numbers for stability: When complex ordering is needed, assign explicit sequence numbers to ensure consistent results

Example implementation:

const sortModelTable = (
  models: ReturnType<typeof collectModels>,
  rule: "custom-first" | "default-first",
) =>
  models.sort((a, b) => {
    // Primary sort: custom vs default
    let aIsCustom = a.provider?.providerType === "custom";
    let bIsCustom = b.provider?.providerType === "custom";
    
    if (aIsCustom !== bIsCustom) {
      return aIsCustom === (rule === "custom-first") ? -1 : 1;
    }
    
    // Secondary sort: by provider type, then model name
    if (a.provider && b.provider) {
      const providerTypeComparison = a.provider.providerType.localeCompare(b.provider.providerType);
      if (providerTypeComparison !== 0) {
        return providerTypeComparison;
      }
      return a.name.localeCompare(b.name);
    }
    
    return a.name.localeCompare(b.name);
  });

For even more stability, use explicit sequence numbers:

// Assign sequence numbers for predictable ordering
let customSeq = -1000; // Custom models get negative numbers (higher priority)
let defaultSeq = 1000;  // Default models get positive numbers

const modelWithSorted = {
  ...model,
  sorted: isCustom ? customSeq++ : defaultSeq++
};

This approach ensures consistent ordering regardless of the underlying data structure’s iteration order and provides clear, maintainable sorting logic.


Configuration backward compatibility

When modifying configuration schemas or adding new configuration options, always ensure backward compatibility with existing deployments. Long-running systems with many user deployments require smooth migration paths from old configurations to new ones.

Key practices:

  1. Validate both old and new formats: Check for the presence of new format indicators before applying new logic
  2. Provide fallback handling: When new configuration format is not detected, gracefully handle the old format
  3. Avoid breaking existing configs: Don’t assume all users will immediately update their configuration files

Example from model configuration handling:

// Check for new format first
if (defaultModel.includes('@')) {
  // New format: model@provider
  if (defaultModel in modelTable) {
    modelTable[defaultModel].isDefault = true;
  }
} else {
  // Old format: just model name - find first matching model
  for (const key in modelTable) {
    if (key.split('@').shift() === defaultModel) {
      modelTable[key].isDefault = true;
      break;
    }
  }
}

This approach ensures that users with existing configurations can continue using the system without forced updates, while new users benefit from improved configuration options.


Use semantic naming

Choose names that reflect purpose and meaning rather than visual appearance, position, or implementation details. This improves code clarity, supports internationalization, and makes the codebase more maintainable.

Avoid positional or appearance-based names like right, left, top that break in different contexts (RTL languages, responsive layouts). Instead, use semantic names that describe the role or function.

Example:

// ❌ Avoid positional naming
const useStyles = createStyles(({ css }) => ({
  right: css`
    display: flex;
  `,
}));

// ✅ Use semantic naming
const useStyles = createStyles(({ css }) => ({
  assistant: css`
    display: flex;
  `,
  user: css`
    display: flex;
  `,
}));

// ❌ Avoid generic labels
<Button title="润色中">Stop</Button>

// ✅ Use descriptive, context-aware labels  
<Button title="语音输入">Stop</Button>

This approach ensures your code works across different languages, layouts, and contexts while making the intent clear to other developers.


Update documentation configuration

When adding new files or components to the project, ensure that documentation configuration is updated accordingly. This includes adding new files to TypeDoc options in tsconfig.json to maintain complete API documentation coverage. Additionally, clearly mark deprecated components and direct developers to use the recommended alternatives instead of extending deprecated functionality.

Example:

// When adding a new file like document_loaders/fs/md.ts
// Remember to update the TypeDoc configuration in tsconfig.json:

"typedocOptions": {
  "entryPoints": [
    // existing entries
    "document_loaders/fs/md.ts"
  ]
}

// For deprecated components, add clear documentation:
/**
 * @deprecated This entrypoint is deprecated. 
 * Please use the community integration instead.
 */

This practice ensures comprehensive documentation coverage and provides clear guidance for developers, preventing them from extending deprecated features and helping them locate the proper integration points for new functionality.


Contextual error handling

Implement error handling that is both architecturally localized and contextually specific to provide better user experience and system resilience. Use localized error boundaries to prevent cascading failures while ensuring error messages are specific to the actual problem and provide actionable guidance.

For architectural design, prefer localized error boundaries over relying solely on global error handlers. This allows different sections of the application to fail independently without affecting other areas, as demonstrated in the discussion: “外面是全页面的,里面加的话可以做到分区出现” (sectional error display) and “其他地方就不会挂掉” (other areas won’t crash).

For error messaging, replace generic error messages with specific, actionable ones. Instead of broad messages like “请求服务出错” (service request error), use specific messages like “未找到该本地模型,请通过 Ollama 下载后重试” (model not found, please download via Ollama and retry). This helps users understand exactly what went wrong and what they can do to resolve it.

Example implementation:

// Localized error boundary for specific feature
<ErrorBoundary fallback={<InvalidOllamaModel />}>
  <ConversationComponent />
</ErrorBoundary>

// Specific error component with actionable message
function InvalidOllamaModel() {
  return (
    <div>
      <p>未找到该本地模型,请通过 Ollama 下载后重试</p>
      <button>下载模型</button>
    </div>
  );
}

Account for model variations

When implementing features that interact with AI models, consider the behavioral differences between various models and adjust parameters accordingly. Different AI models have distinct characteristics such as output speed, token generation patterns, and response formats that can significantly impact user experience.

For example, streaming chat interfaces need different auto-scroll thresholds for different models:

// Consider model output characteristics
const getScrollThreshold = (modelType: string) => {
  // Fast models (GPT-3.5, Sonnet, Groq) output in bursts
  if (modelType.includes('gpt-3.5') || modelType.includes('sonnet')) {
    return 80; // Higher threshold for burst output
  }
  // Slower models (Gemini) output character by character  
  return 50; // Lower threshold for steady output
};

<Virtuoso
  atBottomThreshold={getScrollThreshold(currentModel)}
  // ... other props
/>

This approach prevents common issues like auto-scroll failing when fast models output multiple lines simultaneously, or performance problems when not optimizing for model-specific behaviors. Always test with different model types to ensure consistent user experience across various AI providers.


API version management

When integrating with external APIs, explicitly handle version differences and use parameterized configurations instead of hardcoded values. Different API versions often require different request methods, endpoints, or parameters, so version-specific logic should be clearly defined to prevent incorrect API calls.

Key practices:

Example of explicit version handling:

# Good: Explicit version handling
if self.api_model in ["claude-instant", "claude-2", "claude-2.1"]:
    # Use completions.create() for older models
    response = client.completions.create(...)
else:
    # Use messages.create() for Claude-3 family
    response = client.messages.create(...)

Example of parameterized configuration:

# Good: Parameterized with fallback
api_version = cfg.get("OPENAI_API_VERSION", "2024-02-01")
self.client = AzureOpenAI(
    api_key=cfg["AZURE_OPENAI_API_KEY"], 
    azure_endpoint=cfg["AZURE_OPENAI_ENDPOINT"], 
    api_version=api_version
)

# Avoid: Hardcoded version
self.client = AzureOpenAI(..., api_version="2024-02-01")

This approach prevents API compatibility issues, makes version updates easier to manage, and ensures the correct API interface is used for each version.


Separate multiple imports

When importing multiple items from the same module, use separate import statements instead of combining them on a single line. This improves code readability and makes it easier to track individual imports during code reviews and refactoring.

Instead of:

from refact_webgui.webgui.selfhost_model_resolve import completion_resolve_model, resolve_model_context_size, resolve_tokenizer_name_for_model

Use:

from refact_webgui.webgui.selfhost_model_resolve import completion_resolve_model
from refact_webgui.webgui.selfhost_model_resolve import resolve_model_context_size  
from refact_webgui.webgui.selfhost_model_resolve import resolve_tokenizer_name_for_model

This approach makes each import explicit, reduces line length, and makes it easier to add, remove, or modify individual imports without affecting others.


avoid problematic identifier names

Choose identifier names that avoid system compatibility issues and follow proper naming conventions. Avoid reserved words, system-problematic names, and invalid characters that can cause issues across different platforms or violate language standards.

Key guidelines:

Example from the codebase:

# Problematic - 'aux' is reserved on Windows
from self_hosting_machinery.finetune.scripts.aux.finetune_filter_status_tracker import FinetuneFilterStatusTracker

# Better - use full descriptive name
from self_hosting_machinery.finetune.scripts.auxiliary.finetune_filter_status_tracker import FinetuneFilterStatusTracker

# Problematic - spaces in identifier validation
if not re.match("^[a-zA-Z0-9_ -]*$", v):

# Better - exclude spaces from allowed characters
if not re.match("^[a-zA-Z0-9_-]*$", v):

This prevents deployment issues, ensures cross-platform compatibility, and maintains consistent identifier standards across the codebase.


model-appropriate configuration

Ensure AI models use configuration settings that match their specific architecture and requirements. Different model families (e.g., BigCode vs LLaMA) require different tokenizer configurations, memory management settings, and parameter mappings. Avoid using generic or copy-pasted configurations across different model types.

Key areas to verify:

Example of proper model-specific configuration:

# Wrong - using BigCode tokenizer config for LLaMA model
"tokenizer": {
    "eot_idx": 0,  # BigCode specific
}

# Right - check model family and use appropriate config
if model_family == "llama":
    tokenizer_config = load_llama_tokenizer_config()
elif model_family == "bigcode":
    tokenizer_config = load_bigcode_tokenizer_config()

# Enable checkpointing for large models
"force_enable_checkpointing": model_size > threshold

Always validate that configuration parameters match the target model’s architecture to prevent runtime errors and ensure optimal performance.


API authorization validation

All API endpoints must implement proper authorization checks before processing requests, especially when authentication mechanisms like tokens are available. When adding new API routes, verify that appropriate authorization validation is in place to prevent unauthorized access to sensitive functionality.

Example implementation pattern:

async def _rh_stats(self, account: str = "user"):
    # Add authorization check before processing
    if not self._validate_admin_token():
        raise HTTPException(status_code=401, detail="Unauthorized")
    
    if not self._stats_service.is_ready:
        # ... rest of endpoint logic

Reference existing authorization patterns in your codebase (such as CompletionsRouter) to ensure consistency in how authorization is implemented across different endpoints. This prevents security vulnerabilities where sensitive data or operations could be accessed without proper authentication.


Follow API design conventions

Ensure API endpoints adhere to established design conventions including proper HTTP methods, authorization requirements, and clean route organization. Use GET for data retrieval operations and include appropriate authorization headers for protected endpoints. Avoid creating unnecessary routers when prefixes can be incorporated directly into route definitions.

For HTTP methods and security:

# Instead of POST for data retrieval
self.add_api_route('/rh-stats', self._rh_stats, methods=["POST"])

# Use GET with authorization
self.add_api_route('/rh-stats', self._rh_stats, methods=["GET"])  # + authorization header

For route organization:

# Instead of creating separate routers with prefixes
CAPSRouter(prefix="/v1", ...)

# Incorporate prefix directly into route
self.add_api_route("/v1/completions", self._completions, methods=["POST"])

This approach maintains RESTful principles, improves security posture, and simplifies codebase organization by reducing unnecessary abstraction layers.


Docs accuracy checks

When writing documentation in code (comments, docstrings, example snippets), ensure every instruction and external link precisely matches the actual package extras and the implemented service/provider.

Apply this checklist:

Example (corrected install snippet):

# Install extra support
pip install -e ".[openai]"
# or
pip install "db-gpt[openai]"

If you’re unsure which doc/link is correct, verify against the project’s packaging metadata (extras) and the exact provider SDK you’re calling.


Use safe URL encoding

When constructing connection strings/URIs that embed user credentials, always URL-encode username/password (and other URI components as needed) using an encoder that safely handles reserved characters. Avoid urllib.parse.quote for credentials where characters like @ and # may appear; prefer quote_plus.

Example:

from urllib.parse import quote_plus

db_url = (
    f"doris://{quote_plus(user)}:{quote_plus(pwd)}@{host}:{port}/{db_name}"
)

This prevents malformed URIs and ensures credentials are interpreted correctly and securely by the client/driver.


Smart model selection

Implement intelligent model selection mechanisms that adapt to different scenarios instead of hardcoding specific AI models. Create abstraction layers that can:

  1. Automatically select appropriate models based on API key availability
  2. Choose models with required capabilities for specific tasks
  3. Handle context size limitations with appropriate fallback strategies

For example, instead of directly referencing specific models:

# Avoid this
async for msg_chunk in sdk.models.gpt350613.stream_chat(context, functions=functions):
    # ...

# Prefer this
model = get_model_with_capability("function_calling")
async for msg_chunk in model.stream_chat(context, functions=functions):
    # ...

Or implement intelligent upgrade paths:

# Allow models to handle their own upgrades based on context requirements
model_to_use = await model_to_use.maybe_upgrade(required_context_length)

This approach makes your AI code more maintainable, adaptable to new models, and cost-efficient while still meeting functional requirements.


User-friendly configuration retrieval

When retrieving configuration values like API keys or environment variables, include helpful error messages that guide users on how to fix missing configurations. Consider centralizing configuration retrieval logic in the appropriate classes based on their usage patterns.

For example, instead of just reporting a missing environment variable:

# Better approach with helpful guidance
async def get_api_key(self, env_var: str) -> str:
    # Provide a helpful default message that references the specific environment variable
    prompt = f"Please add your {env_var} to the .env file"
    return await self.ide.getUserSecret(env_var, prompt=prompt)

This approach not only handles the configuration retrieval but also improves developer experience by providing clear guidance when configuration issues arise. For configuration logic that’s specific to certain components (like Models), consider housing that logic within those component classes rather than in general utility methods.


Secure proxy endpoints

Proxy endpoints that forward requests to external services can be exploited by malicious actors if left unsecured. Always implement proper authentication, authorization, and destination validation for proxy endpoints, especially in production deployments.

Consider these security measures:

Example of a potentially vulnerable proxy configuration:

// next.config.mjs - Unsecured proxy
async rewrites() {
  const ret = [
    {
      source: "/api/proxy/:path*",
      destination: "https://api.openai.com/:path*", // Open proxy - can be abused
    }
  ];
}

Instead, secure the proxy with proper authentication and validation in your API route handlers, and consider environment-specific security controls for production deployments.


Validate parameter boundaries

Always validate that parameters contain expected types and values within safe boundaries, not just null/undefined checks. Optional parameters can receive unexpected types (like event objects), and numeric parameters need boundary validation to prevent invalid operations.

For optional parameters, verify the actual type matches expectations:

// Bad: assumes i is either number or undefined
deleteSession(i?: number) {
  const index = i ?? get().currentSessionIndex; // fails when i is an event object
}

// Good: validate the parameter type
deleteSession(i?: number) {
  const index = (typeof i === 'number') ? i : get().currentSessionIndex;
}

For numeric operations, use boundary checks to prevent invalid results:

// Bad: can create negative indices when historyMessageCount is 0
session.messages.slice(n - config.historyMessageCount)

// Good: ensure non-negative starting index
session.messages.slice(Math.max(0, n - config.historyMessageCount))

This prevents runtime errors from undefined values and invalid array operations.


Robust aiohttp Networking

When implementing HTTP/multipart requests and streaming (SSE/chunked) parsing with aiohttp, follow these rules:

Example patterns:

# Multipart: use aiohttp primitive rather than ad-hoc dict encoding
writer = aiohttp.MultipartWriter()
# ... append parts to writer ...

# Response lifecycle: release to pool (avoid breaking pooling semantics)
resp = await session.request(...)
try:
    # read/parse as needed
    ...
finally:
    if not resp.closed:
        resp.release()  # return connection to pool

# Streaming parser: be chunk-boundary agnostic
async def parse_stream_async(reader):
    async for chunk in reader:
        for line in chunk.splitlines():
            # handle b"data: " prefix / DONE sentinel as appropriate
            ...

Azure AD token responsibility

When adding Azure Active Directory authentication (Security), make token acquisition and dependency responsibility explicit and align it with your SDK’s lifecycle.

Example (documented flow):

from azure.identity import DefaultAzureCredential
import openai

default_credential = DefaultAzureCredential()
# Acquire token for Azure Cognitive Services
token = default_credential.get_token("https://cognitiveservices.azure.com")

openai.api_type = "azure_ad"
openai.api_key = token.token

This keeps the authentication flow predictable (caller-owned, token-only passthrough) and reduces the risk of surprising security behavior or broken SDK integration.


Optimize model token usage

Implement token-efficient patterns when working with AI models to optimize costs and performance. Key practices include:

  1. Batch identical prompts into single API calls where supported
  2. Leverage provider-specific features for token efficiency
  3. Use appropriate token counting methods for accurate estimation

Example of efficient batching with OpenAI:

// Inefficient: Multiple separate calls
const results = await Promise.all(
  inputs.map(input => model.generate(input))
);

// Efficient: Single batched call
const results = await model.generate(
  [promptValue], 
  { n: inputs.length }  // OpenAI charges input tokens only once
);

// For accurate token counting:
const tokenCount = await model.getNumTokensFromMessages(messages);

This approach can significantly reduce costs, especially for use cases with high input token counts relative to output. Different providers may offer varying batching capabilities - consult their documentation for optimal usage patterns.