Skip to content

Latest commit

 

History

History
45 lines (33 loc) · 5.16 KB

File metadata and controls

45 lines (33 loc) · 5.16 KB

AGENTS.md

This file provides guidance to agents when working with code in this repository.

  • Settings View Pattern: When working on SettingsView, inputs must bind to the local cachedState, NOT the live useExtensionState(). The cachedState acts as a buffer for user edits, isolating them from the ContextProxy source-of-truth until the user explicitly clicks "Save". Wiring inputs directly to the live state causes race conditions.
  • Changesets: Do NOT create .changeset files for each commit or code change. Changesets are managed separately by maintainers and should not be generated by agents during normal development.

ESLint Suppressions

src/eslint-suppressions.json tracks per-file counts of suppressed lint rules. Suppression counts must never increase. When touching a file, prefer reducing its count when the fix is local and low-risk; avoid broad unrelated cleanup.

When writing new code:

  • Fix lint violations in the new code rather than suppressing them.
  • Avoid as any; use typed APIs directly (e.g. RooCodeEventName.X constants with typed on()/listenerCount()), or bracket notation (obj["privateField"]) to access private members. Prefer precise test doubles or unknown with a type guard over double assertions (as unknown as T); use double assertions only as a last resort, with a comment explaining why.
  • Avoid floating promises; add void, await, or .catch() as appropriate.
  • After editing a file, run pnpm --dir src exec eslint --prune-suppressions --max-warnings=0 <relative-file> and confirm the count for that file did not increase.
  • If a suppression is truly unavoidable (e.g. vi.spyOn(Cls.prototype as any, "privateMethod") where no typed alternative exists), document why in a comment next to the cast.

Persisted Setting Checklist

When adding or changing a user setting, trace the complete round trip. A setting is not complete merely because its control renders or its value reaches storage.

  • Define the setting, validation, and optionality in packages/types/src/global-settings.ts (or the appropriate provider/settings schema). Define a shared default constant when multiple readers need the same default.
  • If the webview uses the setting, include it in ExtensionState in packages/types/src/vscode-extension-host.ts and any relevant message types.
  • In SettingsView, initialize and read the control from local cachedState, NOT directly from live useExtensionState(). The cache buffers edits until the user explicitly clicks Save; binding to live state causes races and discarded edits.
  • Update cachedState from the control and include the setting in the updateSettings payload sent by SettingsView.handleSubmit() (or document and test a deliberate immediate-save flow).
  • Verify webviewMessageHandler handles any setting-specific normalization or side effects and persists the final value through ContextProxy. Generic settings normally use contextProxy.setValue().
  • Add the setting to ClineProvider.getState() with the intended default so extension/runtime consumers can read it.
  • Add the setting to both the destructuring and returned object in ClineProvider.getStateToPostToWebview(). This completes the storage-to-webview round trip and prevents a saved control from reverting visually.
  • Update every runtime consumer and ensure all consumers use the same default semantics.
  • If users can import/export the setting, verify its schema inclusion makes it round-trip and add special handling only when required (for example, secrets or non-exportable state).
  • Add focused tests for: UI binding/save behavior, persistence or normalization, and the saved value returned by getStateToPostToWebview(). Include both true and false/unset cases when defaulting can hide omissions.
  • Run the narrowest relevant Vitest suites from the package directory that declares Vitest.

Test Placement Guidance

Prefer the narrowest test layer that proves the behavior. This follows standard test-pyramid guidance: keep most coverage in fast, focused tests; add integration tests for cross-module contracts; reserve end-to-end tests for full workflow confidence.

  • Use package-local unit tests for pure logic, parsing, state transitions, validation, serialization, request construction, retry decisions, and error handling.
  • Use integration tests when behavior depends on multiple internal modules working together, but does not require the real VS Code extension host or browser/webview runtime.
  • Use webview-ui tests for React rendering, hooks, component state, forms, validation, and webview UI wiring.
  • Use apps/vscode-e2e only when the behavior depends on the real VS Code extension host, VS Code workspace APIs, extension activation, webview/extension messaging, file watcher behavior, or a complete user workflow.
  • Keep e2e tests focused on high-value smoke coverage across boundaries. Avoid placing detailed protocol, parsing, storage, retry, or edge-case assertions in e2e when they can be covered reliably at a lower layer.
  • When fixing a regression, add the regression test at the lowest layer that would have failed for the bug. Add an e2e test only if lower-level tests cannot represent the failure mode.