Developer Experience
Improve the path from checkout to a trustworthy change. Treat documentation, language
support, linting, formatting, and test commands as one developer-facing product, but
change each concern only when repository evidence justifies it.
Operating rules
- Read the applicable
AGENTS.md, README, contribution guide, build files, CI files,
and package configuration before editing.
- Preserve user changes and keep the diff small, reviewable, and reversible.
- Prefer existing commands, utilities, and configuration. Do not add a dependency or
replace a tool without an explicit request and a concrete benefit.
- Do not weaken a check by hiding files, lowering severity, or adding broad ignores just
to make the suite green. Every exclusion needs a scope, reason, and owner.
- Keep developer-experience changes separate from production behavior changes. If a
configuration change affects runtime, packaging, generated artifacts, or deployment,
lock the behavior with a regression test before changing it.
- Preserve environment boundaries. Record which interpreter, runtime, package manager,
service, or external credential a command needs; never imply that a command is
hermetic when it is not.
Workflow
1. Establish the baseline
- Inspect
git status and avoid unrelated or pre-existing edits.
- Map the repository with
rg --files, then locate AGENTS.md, README files, build
entrypoints, CI workflows, package manifests, editor settings, formatter configs,
linter configs, type-checker configs, and test configuration.
- Identify supported languages, runtime versions, package managers, and environment
splits. Record the shortest working commands for install, lint, type check, tests,
and a smoke check.
- Run the narrowest relevant baseline checks. Capture duration, warnings, failures,
missing-tool errors, and whether output is actionable.
- Write a short cleanup plan before modifying code or configuration. Rank findings by
developer impact: blocked onboarding, misleading instructions, broken diagnostics,
noisy checks, slow checks, then cosmetic consistency.
2. Repair developer-facing documentation
For each maintained guide, make the happy path executable:
- State prerequisites, supported versions, environment selection, and the expected
result of each important command.
- Give one canonical command for common work. Explain alternatives only when they
represent a real runtime or safety boundary.
- Keep command names, paths, environment variables, service names, and terminology
consistent with the implementation. Search for stale paths, retired identifiers,
duplicate rules, and references to missing plans or tools.
- Put failure recovery next to the command that can fail. Distinguish local failures,
optional integrations, credential-gated operations, and production actions.
- Prefer concise task-oriented prose. Use headings that answer contributor questions:
what it does, when to use it, what it needs, and how to verify it.
- When multiple human languages are present, choose the repository's primary language
from existing contribution practice. Translate explanations consistently while
preserving code symbols, command names, error text, and protocol vocabulary. Do not
translate identifiers or invent parallel terminology.
- Remove prose that merely restates implementation, historical plans, or obsolete
policy. Keep historical decisions in Git history or an explicitly maintained archive.
3. Improve language and editor support
Audit language support as a diagnostic pipeline, not as a list of fashionable tools:
- Identify the language server, formatter, type checker, import resolver, and test
adapter already used by contributors or CI.
- Check that each tool targets the supported language/runtime version and resolves the
same source roots, generated files, optional dependencies, and sibling packages as
the test runner.
- Prefer one clear tool per responsibility. Remove conflicting settings and duplicate
editor instructions before introducing new configuration.
- Separate syntax, style, type, and runtime checks. A type checker must not be used as
a substitute for tests, and a formatter must not silently alter generated or vendored
files.
- Verify diagnostics on representative valid and invalid examples. Confirm that the
failure points to an actionable file and line, exits non-zero, and does not require
unavailable services unless the check is explicitly integration-only.
- Document editor setup only to the degree needed for a contributor to reproduce the
repository's supported checks. Avoid editor-specific rules that contradict CI.
For Python repositories, inspect pyproject.toml, pytest configuration, virtualenv or
conda entrypoints, PYTHONPATH, and package import boundaries together. Test each
interpreter-specific command rather than assuming bare python is equivalent to a
project-managed interpreter.
4. Make linting useful
- Establish a baseline before changing rules: runtime, warning count, failure count,
files covered, and whether the output is stable.
- Classify findings as correctness, maintainability, security, portability, or style.
Prioritize checks that catch defects or shorten review; defer subjective style noise.
- Keep fast, deterministic checks suitable for every local change separate from slow,
integration, network, generated-code, or environment-dependent checks.
- Scope exclusions narrowly to generated, vendored, archived, or intentionally special
files. Explain non-obvious exclusions in the config or adjacent documentation.
- Use the repository's existing formatter and import ordering rules. Avoid a mass
reformat when a targeted change can solve the problem.
- Check that lint output is readable locally and machine-readable in CI, with stable
exit codes and a command contributors can run without hidden wrapper state.
- If a new check is justified, add it in the smallest enforceable mode, document its
invocation, and prove that it catches a representative defect without unacceptable
false positives or runtime cost.
5. Choose test granularity and doubles
Choose the smallest test that crosses the failure boundary being changed, then add a
higher-level test only when it protects wiring or behavior that lower-level tests cannot
observe:
- Use unit tests for pure transformations, state machines, validation, and error
decisions. Keep them fast, deterministic, and independent of network, clocks, random
seeds, processes, and persistent services unless those are the behavior under test.
- Use component or contract tests for module boundaries, serialization, CLI protocols,
persistence adapters, and dependency wiring. Verify the boundary contract rather than
repeating every internal branch already covered by unit tests.
- Use integration tests with real local or ephemeral dependencies when correctness
depends on SQL behavior, filesystem semantics, serialization libraries, process
boundaries, or framework configuration. Prefer a small number of high-signal cases to
a large collection of mocked integration scenarios.
- Use external tests for live APIs, credentials, broker or cloud behavior, and other
environment-dependent contracts. Mark them explicitly, gate them with the repository's
required environment variable or test marker, set timeouts and cleanup, redact secrets,
and make prerequisite failures obvious. Never let a missing external service silently
fall back to a fake while reporting success.
Select test doubles by the behavior they preserve:
- Prefer a real collaborator when it is cheap, deterministic, and stable.
- Use a fake when a deterministic in-memory or local substitute can preserve the public
contract and exercise meaningful behavior.
- Use a stub to provide a narrow input, return value, or failure. Keep the assertion on
the resulting behavior rather than the stub's implementation.
- Use a spy only for an observable side effect or protocol that is itself part of the
contract. Assert semantic events, not incidental call order or private helper calls.
- Use a mock sparingly, mainly when an interaction contract, failure timing, or expensive
boundary cannot be tested otherwise. Do not mock internal methods of the subject under
test or every collaborator in a test that claims to cover integration.
Balance the suite by tracking defect detection, runtime, flakiness, setup cost, and
maintenance cost. Keep deterministic unit and selected contract checks on every change;
run local integration checks before merge; reserve network, credential, broker, and other
external checks for explicit pre-release, scheduled, or manually authorized runs. Delete
or consolidate duplicate tests when a higher-fidelity test protects the same contract,
but retain a lower-level test when it gives materially faster and clearer diagnosis.
6. Implement and verify
Make one smell-focused pass at a time. Update documentation and configuration together
when one describes the other, and add or adjust regression tests for behavior-sensitive
changes. Then run, in order:
- The changed documentation or command-contract tests.
- The targeted formatter, linter, language-server, or type-checker checks.
- The relevant fast test subset and smoke check.
- The repository's documented full gate when practical.
git diff --check and searches for stale commands, paths, identifiers, and duplicate
guidance in the active tree.
Read the outputs; do not infer success from exit codes alone when a tool can skip files
or emit warnings. Report exact commands, interpreter/tool versions when relevant,
duration changes, remaining environment-dependent checks, and any validation gap.
Deliverable shape
Return a compact evidence-based report containing:
- baseline friction and ranked findings;
- files and behavior changed, including deleted or consolidated guidance;
- the canonical contributor commands after the change;
- validation commands and results, including before/after timing when optimization was
requested;
- remaining risks, unsupported environments, and intentionally deferred improvements.
Do not claim that a repository has full language or lint support merely because a config
file exists. Claim support only after the command runs against the intended source set
and produces actionable diagnostics.
1---2name: developer-experience3description: Audit and improve developer-facing documentation, language tooling, editor support, formatting, linting, test granularity, test doubles, and contributor commands while preserving runtime behavior. Use when a repository needs clearer onboarding, reliable language-server or type-checker feedback, less noisy or faster lint checks, a balanced unit-to-external test strategy, consistent local and CI workflows, or a measured developer-experience cleanup.4---56# Developer Experience78Improve the path from checkout to a trustworthy change. Treat documentation, language9support, linting, formatting, and test commands as one developer-facing product, but10change each concern only when repository evidence justifies it.1112## Operating rules1314- Read the applicable `AGENTS.md`, `README`, contribution guide, build files, CI files,15 and package configuration before editing.16- Preserve user changes and keep the diff small, reviewable, and reversible.17- Prefer existing commands, utilities, and configuration. Do not add a dependency or18 replace a tool without an explicit request and a concrete benefit.19- Do not weaken a check by hiding files, lowering severity, or adding broad ignores just20 to make the suite green. Every exclusion needs a scope, reason, and owner.21- Keep developer-experience changes separate from production behavior changes. If a22 configuration change affects runtime, packaging, generated artifacts, or deployment,23 lock the behavior with a regression test before changing it.24- Preserve environment boundaries. Record which interpreter, runtime, package manager,25 service, or external credential a command needs; never imply that a command is26 hermetic when it is not.2728## Workflow2930### 1. Establish the baseline31321. Inspect `git status` and avoid unrelated or pre-existing edits.332. Map the repository with `rg --files`, then locate `AGENTS.md`, README files, build34 entrypoints, CI workflows, package manifests, editor settings, formatter configs,35 linter configs, type-checker configs, and test configuration.363. Identify supported languages, runtime versions, package managers, and environment37 splits. Record the shortest working commands for install, lint, type check, tests,38 and a smoke check.394. Run the narrowest relevant baseline checks. Capture duration, warnings, failures,40 missing-tool errors, and whether output is actionable.415. Write a short cleanup plan before modifying code or configuration. Rank findings by42 developer impact: blocked onboarding, misleading instructions, broken diagnostics,43 noisy checks, slow checks, then cosmetic consistency.4445### 2. Repair developer-facing documentation4647For each maintained guide, make the happy path executable:4849- State prerequisites, supported versions, environment selection, and the expected50 result of each important command.51- Give one canonical command for common work. Explain alternatives only when they52 represent a real runtime or safety boundary.53- Keep command names, paths, environment variables, service names, and terminology54 consistent with the implementation. Search for stale paths, retired identifiers,55 duplicate rules, and references to missing plans or tools.56- Put failure recovery next to the command that can fail. Distinguish local failures,57 optional integrations, credential-gated operations, and production actions.58- Prefer concise task-oriented prose. Use headings that answer contributor questions:59 what it does, when to use it, what it needs, and how to verify it.60- When multiple human languages are present, choose the repository's primary language61 from existing contribution practice. Translate explanations consistently while62 preserving code symbols, command names, error text, and protocol vocabulary. Do not63 translate identifiers or invent parallel terminology.64- Remove prose that merely restates implementation, historical plans, or obsolete65 policy. Keep historical decisions in Git history or an explicitly maintained archive.6667### 3. Improve language and editor support6869Audit language support as a diagnostic pipeline, not as a list of fashionable tools:70711. Identify the language server, formatter, type checker, import resolver, and test72 adapter already used by contributors or CI.732. Check that each tool targets the supported language/runtime version and resolves the74 same source roots, generated files, optional dependencies, and sibling packages as75 the test runner.763. Prefer one clear tool per responsibility. Remove conflicting settings and duplicate77 editor instructions before introducing new configuration.784. Separate syntax, style, type, and runtime checks. A type checker must not be used as79 a substitute for tests, and a formatter must not silently alter generated or vendored80 files.815. Verify diagnostics on representative valid and invalid examples. Confirm that the82 failure points to an actionable file and line, exits non-zero, and does not require83 unavailable services unless the check is explicitly integration-only.846. Document editor setup only to the degree needed for a contributor to reproduce the85 repository's supported checks. Avoid editor-specific rules that contradict CI.8687For Python repositories, inspect `pyproject.toml`, `pytest` configuration, virtualenv or88conda entrypoints, `PYTHONPATH`, and package import boundaries together. Test each89interpreter-specific command rather than assuming bare `python` is equivalent to a90project-managed interpreter.9192### 4. Make linting useful9394- Establish a baseline before changing rules: runtime, warning count, failure count,95 files covered, and whether the output is stable.96- Classify findings as correctness, maintainability, security, portability, or style.97 Prioritize checks that catch defects or shorten review; defer subjective style noise.98- Keep fast, deterministic checks suitable for every local change separate from slow,99 integration, network, generated-code, or environment-dependent checks.100- Scope exclusions narrowly to generated, vendored, archived, or intentionally special101 files. Explain non-obvious exclusions in the config or adjacent documentation.102- Use the repository's existing formatter and import ordering rules. Avoid a mass103 reformat when a targeted change can solve the problem.104- Check that lint output is readable locally and machine-readable in CI, with stable105 exit codes and a command contributors can run without hidden wrapper state.106- If a new check is justified, add it in the smallest enforceable mode, document its107 invocation, and prove that it catches a representative defect without unacceptable108 false positives or runtime cost.109110### 5. Choose test granularity and doubles111112Choose the smallest test that crosses the failure boundary being changed, then add a113higher-level test only when it protects wiring or behavior that lower-level tests cannot114observe:115116- Use unit tests for pure transformations, state machines, validation, and error117 decisions. Keep them fast, deterministic, and independent of network, clocks, random118 seeds, processes, and persistent services unless those are the behavior under test.119- Use component or contract tests for module boundaries, serialization, CLI protocols,120 persistence adapters, and dependency wiring. Verify the boundary contract rather than121 repeating every internal branch already covered by unit tests.122- Use integration tests with real local or ephemeral dependencies when correctness123 depends on SQL behavior, filesystem semantics, serialization libraries, process124 boundaries, or framework configuration. Prefer a small number of high-signal cases to125 a large collection of mocked integration scenarios.126- Use external tests for live APIs, credentials, broker or cloud behavior, and other127 environment-dependent contracts. Mark them explicitly, gate them with the repository's128 required environment variable or test marker, set timeouts and cleanup, redact secrets,129 and make prerequisite failures obvious. Never let a missing external service silently130 fall back to a fake while reporting success.131132Select test doubles by the behavior they preserve:133134- Prefer a real collaborator when it is cheap, deterministic, and stable.135- Use a fake when a deterministic in-memory or local substitute can preserve the public136 contract and exercise meaningful behavior.137- Use a stub to provide a narrow input, return value, or failure. Keep the assertion on138 the resulting behavior rather than the stub's implementation.139- Use a spy only for an observable side effect or protocol that is itself part of the140 contract. Assert semantic events, not incidental call order or private helper calls.141- Use a mock sparingly, mainly when an interaction contract, failure timing, or expensive142 boundary cannot be tested otherwise. Do not mock internal methods of the subject under143 test or every collaborator in a test that claims to cover integration.144145Balance the suite by tracking defect detection, runtime, flakiness, setup cost, and146maintenance cost. Keep deterministic unit and selected contract checks on every change;147run local integration checks before merge; reserve network, credential, broker, and other148external checks for explicit pre-release, scheduled, or manually authorized runs. Delete149or consolidate duplicate tests when a higher-fidelity test protects the same contract,150but retain a lower-level test when it gives materially faster and clearer diagnosis.151152### 6. Implement and verify153154Make one smell-focused pass at a time. Update documentation and configuration together155when one describes the other, and add or adjust regression tests for behavior-sensitive156changes. Then run, in order:1571581. The changed documentation or command-contract tests.1592. The targeted formatter, linter, language-server, or type-checker checks.1603. The relevant fast test subset and smoke check.1614. The repository's documented full gate when practical.1625. `git diff --check` and searches for stale commands, paths, identifiers, and duplicate163 guidance in the active tree.164165Read the outputs; do not infer success from exit codes alone when a tool can skip files166or emit warnings. Report exact commands, interpreter/tool versions when relevant,167duration changes, remaining environment-dependent checks, and any validation gap.168169## Deliverable shape170171Return a compact evidence-based report containing:172173- baseline friction and ranked findings;174- files and behavior changed, including deleted or consolidated guidance;175- the canonical contributor commands after the change;176- validation commands and results, including before/after timing when optimization was177 requested;178- remaining risks, unsupported environments, and intentionally deferred improvements.179180Do not claim that a repository has full language or lint support merely because a config181file exists. Claim support only after the command runs against the intended source set182and produces actionable diagnostics.