microsoft/vscode
Before editing, read .github/copilot-instructions.md (the canonical conventions doc referenced by AGENTS.md): tabs not spaces, DI rules (services only via constructor params, never IInstantiationService lookups later), strict disposable discipline (DisposableStore/MutableDisposable), nls.localize for all user strings, no cross-component storage-key access, prefer IEditorService for opening editors, and events are for broadcasting not control flow. Respect the layering (base→platform→editor→workbench; sessions may import workbench, not vice versa) enforced by valid-layers-check. New shared services go through registerSingleton in the right workbench.*.main.ts barrel — never in Workbench.initServices. Test with scripts/test.sh --grep for unit tests; use npm run typecheck-client or the watch tasks for validation, and transpile-client when you only need fresh output.
- Read .github/copilot-instructions.md first — it is the canonical agent doc (AGENTS.md just points to it) covering layers, DI rules, coding style, disposable rules, and validation strategy.
- Layer rule: vs/sessions may import vs/workbench but not vice versa; platform code must not import workbench; layering is machine-checked by npm run valid-layers-check (build/checker/layersChecker.ts) — run it when changing module dependencies.
- Service registration trap: Workbench.initServices has an explicit 'do NOT register services here' comment — use registerSingleton() in workbench.common.main.ts (or web/desktop main for platform-specific services) with InstantiationType.Delayed unless eager startup is required.
- Common-import rule: the banner in workbench.web.main.ts says add common imports to workbench.common.main.ts; import order in these barrels controls module side effects, so keep the regioned structure intact.
- ESM import convention: all in-repo imports use explicit '.js' extensions on TypeScript sources (e.g., '../../base/common/uri.js'); the codebase is 'type: module' and bootstrapped via bootstrapESM.
- Disposable discipline is enforced in review: register disposables immediately (DisposableStore/DisposableMap/MutableDisposable); don't register method-created disposables on the containing class to avoid leaks — return IDisposable to the caller instead.
- Unit tests: put tests in the sibling test/ folder of the layer (e.g., src/vs/platform/x/test), use mocha tdd describe/test style, run via scripts/test.sh --grep on desktop or npm run test-node / test-browser for the relevant suite.
- Validation hierarchy: prefer existing watch-task diagnostics; use npm run transpile-client when tests just need fresh output; npm run typecheck-client for broad src changes; npm run gulp compile-extensions for built-in extensions; avoid redundant typecheck+compile runs.
- User-facing strings must go through vs/nls (nls.localize/localize2) with placeholders, never concatenation; command/menu labels use title-case per the UI-label rules.
- Every file needs the Microsoft copyright header (MIT) — enforced by hygiene (build/hygiene.ts run as precommit).
- Do not read another component's storage keys to mutate its state — add a proper API instead; use IEditorService (not IEditorGroupsService.activeGroup.openEditor) to open editors so revealIfOpened/preserveFocus are honored.
- Perf convention: instrument startup paths with perf.mark('code/...') markers matching the existing naming scheme (code/willX/code/didX); thresholds like setGlobalLeakWarningThreshold(175) exist and tests will flag emitter leaks.