{"owner":"redis","repo":"ioredis","hasSkills":true,"totalSkillsCount":12,"totalTokensCount":17703,"categories":["anthropic-skill","root-instruction"],"hasMcp":false,"mcpConfig":null,"found":[".agents/skills/code-change-verification/SKILL.md",".agents/skills/docs-sync/SKILL.md",".agents/skills/docs-sync/references/doc-coverage-checklist.md",".agents/skills/implement-command/SKILL.md",".agents/skills/pr-draft-summary/SKILL.md",".agents/skills/runtime-behavior-probe/SKILL.md",".agents/skills/runtime-behavior-probe/references/error-cases.md",".agents/skills/runtime-behavior-probe/references/redis-runtime-patterns.md",".agents/skills/runtime-behavior-probe/references/repo-import-patterns.md",".agents/skills/runtime-behavior-probe/references/reporting-format.md",".agents/skills/runtime-behavior-probe/references/validation-matrix.md","AGENTS.md"],"skills":{".agents/skills/code-change-verification/SKILL.md":"---\nname: code-change-verification\ndescription: Verify ioredis code changes before handoff. Use when an agent changes or reviews runtime TypeScript, Redis command support, generated typings, tests, docs tied to behavior, build tooling, release-sensitive files, or any task that needs choosing and running the right local validation commands.\n---\n\n# Code Change Verification\n\nUse this skill to choose the smallest credible validation set for an ioredis change, run it when feasible, and report exactly what passed, failed, or was skipped.\n\n## Workflow\n\n1. Inspect the diff and changed files before choosing commands.\n   - Use `git diff --stat`, `git diff --name-only`, and targeted file reads.\n   - Do not stage, unstage, or commit unless the user explicitly asks.\n   - Treat `built/` and `lib/utils/RedisCommander.ts` as generated outputs; do not hand-edit them.\n\n2. Classify the change.\n   - Runtime code under `lib/`: run focused tests plus build when the change affects exported declarations or compiled output.\n   - Redis command typing or generated command support: inspect `bin/` config, regenerate with `node bin/index.js` if needed, and run tsd or targeted typing tests.\n   - Functional Redis behavior: run the smallest relevant Mocha files and assume a compatible Redis server is on default host/port. If sandboxed Redis access is blocked, ask for permission rather than assuming Redis is unavailable.\n   - Cluster behavior: use `npm run docker:setup` if infrastructure is needed, then targeted `test/cluster/**/*.ts` or `npm run test:cluster`.\n   - Docs-only changes: run `npm run format-check` only if formatting-sensitive files changed; otherwise inspect rendered Markdown manually.\n   - Build/tooling changes: run `npm run build` and the affected script directly.\n\n3. Prefer focused validation before broad validation.\n   - For self-contained pure unit files, run the test file alone first: `TS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/<file>.ts\"`.\n   - Include `test/helpers/*.ts` only when the unit file relies on global hooks or helper setup.\n   - Functional command change: include `test/helpers/*.ts` and the specific `test/functional/...` file.\n   - Typing change: `npm run build` then `npx tsd --files test/typing/<file>.test-d.ts` when a focused file exists.\n   - Public API or cross-cutting behavior: escalate to `npm test` after focused tests pass.\n   - Formatting-only TypeScript edits: run `npm run lint` or `npm run format-check` as appropriate.\n\n4. Handle generated artifacts deliberately.\n   - If `bin/argumentTypes.js`, `bin/returnTypes.js`, `bin/overrides.js`, `bin/sortArguments.js`, `bin/typeMaps.js`, or `bin/template.ts` changes command declarations, regenerate `lib/utils/RedisCommander.ts` with `node bin/index.js`.\n   - If generated output changes unexpectedly, inspect the generator inputs before accepting it.\n   - Build output in `built/` is publish-facing but generated by `npm run build`; mention if it is intentionally not updated.\n\n5. Report results in handoff.\n   - List each command run and its result.\n   - For failures, include the failing test name or key error line and whether it appears related.\n   - For skipped commands, state the concrete reason, such as missing Redis server, blocked sandbox access, or out-of-scope broad suite.\n\n## Command Reference\n\n- `npm run build`: remove `built/` and compile TypeScript.\n- `npm run lint`: ESLint over `lib/`.\n- `npm run format-check`: Prettier check.\n- `npm run test:js`: non-cluster Mocha suite over helpers, unit, and functional tests.\n- `npm run test:cluster`: cluster Mocha suite.\n- `npm run test:tsd`: build and run all tsd tests.\n- `npm test`: `test:js` plus `test:tsd`.\n- `npm run docker:setup` / `npm run docker:teardown`: start/stop Redis test infrastructure.\n",".agents/skills/docs-sync/SKILL.md":"---\nname: docs-sync\ndescription: Keep ioredis documentation synchronized with code behavior. Use when an agent changes public APIs, options, Redis command support, examples, generated typings, connection behavior, Cluster/Sentinel behavior, Pub/Sub, pipelines, transactions, scan streams, reconnect behavior, TypeScript usage, or release-facing behavior that may require README or docs updates.\n---\n\n# Docs Sync\n\nUse this skill to decide whether an ioredis change needs documentation, update the right docs, and keep examples aligned with tested behavior.\n\nFor broad documentation audits, option/API coverage checks, or unclear documentation scope, also read `references/doc-coverage-checklist.md` before deciding what to update.\n\n## Workflow\n\n1. Inspect the changed behavior.\n   - Read the diff and the surrounding implementation.\n   - Identify whether users must know a new capability, option, error case, event, command signature, return shape, or migration concern.\n   - Treat TypeScript declarations and public JSDoc as documentation when command signatures, constructor options, or exported types change.\n\n2. Find the documentation surface.\n   - `README.md`: primary user-facing guide, examples, feature overview, options, and common workflows.\n   - `lib/redis/RedisOptions.ts`: `RedisOptions`, `CommonRedisOptions`, option JSDoc, and `DEFAULT_REDIS_OPTIONS`.\n   - `lib/cluster/ClusterOptions.ts`: `ClusterOptions`, cluster option JSDoc, and `DEFAULT_CLUSTER_OPTIONS`.\n   - `lib/connectors/StandaloneConnector.ts` and `lib/connectors/SentinelConnector/types.ts`: connection option types that contribute to public constructor options.\n   - `docs/`: generated TypeDoc output from public source comments.\n   - `examples/`: runnable snippets that should match current API behavior.\n   - `lib/index.ts` and public TypeDoc comments: exported API documentation surface.\n   - `test/typing/`: executable documentation for TypeScript signatures.\n\n3. Update docs when the change affects users.\n   - Public option or constructor behavior: document option name, default, behavior, topology limitations, and Redis version constraints in JSDoc first; update README/examples when users need prose or usage guidance.\n   - Redis command support: update generator config in `bin/`, regenerate `lib/utils/RedisCommander.ts`, and document only if README/docs mention related command groups or if the change affects command typing, return mapping, or examples.\n   - Pub/Sub, sharded Pub/Sub, monitor, pipeline, transaction, Sentinel, Cluster, TLS, reconnect, or offline queue behavior: update the relevant README/docs section.\n   - New or changed public exports from `lib/index.ts`: update TypeDoc comments and typing tests when the exported type or class is part of the supported API.\n   - Breaking or compatibility-sensitive behavior: add explicit migration or caveat wording.\n   - Internal-only refactors with no behavioral/API impact: state that no docs update is needed and why.\n\n4. Keep examples honest.\n   - Prefer short examples that compile against the current public API.\n   - Avoid documenting behavior that is not covered by tests unless you also add or request coverage.\n   - If an example requires a Redis version, topology, or protocol mode, say so near the example.\n   - Use existing README style and terminology.\n\n5. Verify documentation changes.\n   - For TypeScript examples or declarations, run the focused tsd test or add one when appropriate.\n   - For API docs comments, run `npm run docs` when the change affects generated docs.\n   - For command typing changes, run `node bin/index.js` before validating generated typings.\n   - For Markdown-only edits, inspect nearby formatting and links; run `npm run format-check` only when relevant files are covered by Prettier.\n\n## Documentation Decision Checklist\n\n- Does the change alter public exports from `lib/index.ts`?\n- Does it add, remove, rename, or change JSDoc/defaults for `RedisOptions`, `CommonRedisOptions`, `ClusterOptions`, standalone connection options, or Sentinel connection options?\n- Does it add, remove, or change a Redis command method signature?\n- Does it change reply transformation, Buffer variants, callbacks, or Promise behavior?\n- Does it affect connection lifecycle, retries, ready checks, offline queue, or subscriber mode?\n- Does it affect Cluster routing, redirections, subscriber groups, Sentinel discovery, or TLS?\n- Does it add an option, event, error condition, or environment assumption?\n- Would a user need different code after this change?\n\nIf any answer is yes, update docs or explicitly explain why existing docs already cover it.\n",".agents/skills/docs-sync/references/doc-coverage-checklist.md":"# ioredis Doc Coverage Checklist\n\nUse this checklist to scan the selected scope and validate that user-facing ioredis behavior is documented in the right place. In diff mode, limit the scan to the selected task scope: staged changes, unstaged changes, staged plus unstaged changes, or a branch comparison such as `git diff main...HEAD` for PR-oriented audits. In comprehensive mode, inventory the public surfaces listed below.\n\n## Public API inventory\n\n- Public exports from `lib/index.ts`: default `Redis`, named `Redis`, `Cluster`, exported classes, exported types, and compatibility exports.\n- Constructor and option types:\n  - `lib/redis/RedisOptions.ts`: `RedisOptions`, `CommonRedisOptions`, `RetryStrategy`, `ReconnectOnError`, and `DEFAULT_REDIS_OPTIONS`.\n  - `lib/cluster/ClusterOptions.ts`: `ClusterOptions`, `ClusterNodeRetryStrategy`, DNS/NAT helper types, and `DEFAULT_CLUSTER_OPTIONS`.\n  - `lib/connectors/StandaloneConnector.ts`: standalone TCP/TLS connection options.\n  - `lib/connectors/SentinelConnector/types.ts`: Sentinel connection options, failover behavior, and sentinel-specific limits.\n- Generated command API:\n  - `lib/utils/RedisCommander.ts` is generated and must not be hand-edited.\n  - `bin/overrides.js`, `bin/argumentTypes.js`, `bin/returnTypes.js`, `bin/sortArguments.js`, and `bin/typeMaps.js` define command signature and return documentation inputs.\n- Core classes and behavior surfaces: `lib/Redis.ts`, `lib/cluster/index.ts`, `lib/Command.ts`, `lib/Pipeline.ts`, `lib/transaction.ts`, `lib/ScanStream.ts`, `lib/DataHandler.ts`, `lib/autoPipelining.ts`, `lib/Script.ts`, and `lib/tracing.ts`.\n- User-facing examples and executable docs: `README.md`, `examples/`, and `test/typing/`.\n\n## Option JSDoc requirements\n\n- Every public option on `CommonRedisOptions`, `RedisOptions`-contributing connection types, and `ClusterOptions` should have clear JSDoc unless the option is intentionally internal.\n- JSDoc should include:\n  - What the option changes in user-visible behavior.\n  - Default value with `@default`, matching `DEFAULT_REDIS_OPTIONS` or `DEFAULT_CLUSTER_OPTIONS`.\n  - Accepted values when the TypeScript type is broad, such as callback return contracts or string roles.\n  - Topology limits, such as standalone-only, Sentinel-only, Cluster-only, subscriber-mode, or RESP mode constraints.\n  - Redis version requirements when relevant.\n- Keep JSDoc and defaults synchronized for options such as retry strategies, timeouts, offline queue behavior, ready checks, auto pipelining, client info, authentication, Sentinel discovery, Cluster redirections, SRV lookup, NAT mapping, and sharded subscribers.\n- When an option is deprecated, renamed, or compatibility-only, document that in JSDoc and remove stale README guidance if it no longer applies.\n\n## Documentation surfaces\n\n- `README.md`: main guide, examples, feature overview, constructor options, Cluster, Sentinel, Pub/Sub, pipelines, transactions, Lua scripts, streams/scans, TLS, reconnect behavior, and TypeScript usage.\n- `docs/`: generated TypeDoc output from `npm run docs`; update generated docs only as part of an intentional docs generation change.\n- TypeDoc source comments: public JSDoc in `lib/index.ts`, `lib/redis/RedisOptions.ts`, `lib/cluster/ClusterOptions.ts`, connector option types, tracing types, and public classes.\n- `examples/`: runnable examples that should compile and use current APIs.\n- `test/typing/`: tsd coverage for public TypeScript signatures, command typings, constructor options, and exported types.\n\n## Code-first pass\n\n- Start from code, not existing docs. Identify the changed public symbol, option, command signature, return type, default, error, event, or lifecycle behavior.\n- Map the behavior to the closest existing doc surface. Prefer updating an existing README section, JSDoc block, example, or typing test over creating a new document.\n- For command typing changes, update generator config in `bin/`, regenerate `lib/utils/RedisCommander.ts`, and consider `test/typing/commands.test-d.ts`.\n- For option changes, update the interface JSDoc, default object, README option guidance if present, and tsd coverage when the type surface matters.\n- For behavior changes in Cluster, Sentinel, Pub/Sub, pipelines, transactions, scan streams, reconnect logic, ready checks, timeouts, tracing, or data handling, check both README prose and public JSDoc.\n\n## Evidence capture\n\n- Record the file path and symbol or setting name, for example `lib/redis/RedisOptions.ts:CommonRedisOptions.commandTimeout`.\n- Record the default from `DEFAULT_REDIS_OPTIONS` or `DEFAULT_CLUSTER_OPTIONS` when documenting options.\n- Record the implementation behavior that proves the docs text, such as the method, event handler, retry branch, or command transformer.\n- Avoid large code dumps. A short path plus symbol and behavior note is enough.\n\n## Red flags\n\n- README option names, defaults, or examples differ from `RedisOptions`, `ClusterOptions`, connector option types, or default objects.\n- Public options exist without JSDoc, or JSDoc omits important default/behavior constraints.\n- Generated TypeDoc pages under `docs/` are stale relative to TypeScript source comments.\n- `lib/utils/RedisCommander.ts` was manually edited instead of regenerated from `bin/` config.\n- Command return types, Buffer variants, callbacks, Promise behavior, or pipeline/transaction behavior changed without typing or docs review.\n- Removed, renamed, or deprecated features remain documented as current behavior.\n- Examples rely on unsupported Redis versions, topology assumptions, or undocumented setup.\n\n## Structural changes\n\n- Propose README restructuring only when an existing section mixes quick-start usage with deep reference detail, or when Cluster/Sentinel/Pub/Sub/TypeScript material has no sensible home.\n- Keep quick-start examples short. Move advanced retry, timeout, topology, command typing, and failure-mode details into focused sections or JSDoc.\n- Cross-link related concepts instead of duplicating long explanations, especially for options shared between standalone Redis and Cluster `redisOptions`.\n\n## Diff mode guidance\n\n- Choose the diff source that matches the task:\n  - Staged work: `git diff --cached`.\n  - Unstaged work: `git diff`.\n  - All local in-progress work: inspect both `git diff --cached` and `git diff`.\n  - PR-oriented branch audit: `git diff main...HEAD` or the equivalent branch base.\n- Focus only on changed public behavior: new exports/options, modified defaults, removed features, renamed settings, new command signatures, changed reply transformations, or changed lifecycle behavior.\n- Document removals explicitly so stale README, examples, JSDoc, TypeDoc output, and typing tests can be pruned.\n\n## Patch guidance\n\n- Keep edits scoped and aligned to the existing README/JSDoc tone.\n- Do not hand-edit `lib/utils/RedisCommander.ts`; regenerate it with `node bin/index.js` after command typing config changes.\n- Leave translated or vendored docs untouched unless the task explicitly targets them.\n- For Markdown-only updates, inspect nearby formatting. For JSDoc/API changes, run `npm run docs` when generated docs must be refreshed.\n",".agents/skills/implement-command/SKILL.md":"---\nname: implement-command\ndescription: Use when adding or updating Redis command support in ioredis, including command metadata checks, generator inputs under bin/, generated RedisCommander typings, return and argument overrides, functional command tests, optional tsd coverage, and validation.\n---\n\n# Implement Command\n\nUse this skill when adding a missing Redis command, correcting an existing command signature, changing command return types, or adding coverage for command-specific Buffer, callback, pipeline, or transformer behavior.\n\n## Command Support Map\n\n- `@ioredis/commands`: upstream command metadata consumed by the generator.\n- `bin/index.js`: generator entry point for `lib/utils/RedisCommander.ts`.\n- `bin/returnTypes.js`: command return type map. Most new commands need an entry here.\n- `bin/argumentTypes.js`: command-specific argument shape overrides when metadata or global mapping is insufficient.\n- `bin/typeMaps.js`: global Redis argument category to TypeScript type mapping.\n- `bin/overrides.js`: manual overloads for signatures the generator cannot express cleanly.\n- `bin/sortArguments.js`: argument reordering for commands whose generated order is wrong.\n- `lib/utils/RedisCommander.ts`: generated declarations. Regenerate it; do not hand-edit it.\n- `lib/Command.ts`: command argument and reply transformer registry. Touch only when transformer behavior is needed.\n- `test/functional/commands/<command>.ts`: runtime command coverage.\n- `test/functional/transformer.ts`: transformer runtime coverage.\n- `test/typing/commands.test-d.ts`: public command typing coverage.\n- `test/typing/transformers.test-d.ts`: transformer typing coverage.\n\n## Workflow\n\n1. Establish command scope.\n   - Normalize command keys to lowercase, matching `bin/returnTypes.js`.\n   - Resolve command aliases or subcommands before editing.\n   - Confirm the command exists in `@ioredis/commands`. If it is missing there, stop and report that the metadata package must be updated before ioredis can generate typed command support.\n   - Identify the minimum Redis server version needed and whether functional tests must be version-gated.\n\n2. Inspect current support.\n   - Search `lib/utils/RedisCommander.ts`, `bin/`, `test/functional/commands/`, and `test/typing/` for the command and related aliases.\n   - Inspect nearby command families before choosing types, for example hash expiration commands, sorted-set commands, stream commands, or pub/sub commands.\n   - Check existing argument and reply transformers before adding new ones.\n\n3. Update generator inputs.\n   - Prefer `bin/returnTypes.js` for return type corrections.\n   - Use a string return type for simple fixed replies.\n   - Use a function return type when replies depend on subcommands, options, or tokens.\n   - Reuse `hasToken` and `matchSubcommand` in `bin/returnTypes.js` when they fit.\n   - Use `bin/argumentTypes.js` only for command-specific argument overrides.\n   - Use `bin/typeMaps.js` only for broad metadata category fixes that should affect multiple commands.\n   - Use `bin/overrides.js` only when generated overloads cannot express the supported API cleanly.\n   - Keep command names lowercase in generator maps unless the surrounding file uses another established convention.\n\n4. Regenerate declarations.\n   - In this repo, use `node bin/index.js` unless `package.json` later adds an explicit generation script.\n   - Review the generated diff in `lib/utils/RedisCommander.ts`.\n   - Check the normal method, callback overload, pipeline/transaction shape, and Buffer variant when the command returns strings, arrays, nullable bulk replies, or transformed objects.\n   - If generation changes unrelated commands, inspect the generator input and do not accept surprising churn without an explanation.\n\n5. Add focused runtime coverage.\n   - Put command tests in `test/functional/commands/<lowercase-command>.ts`.\n   - Use `import Redis from \"../../../lib/Redis\";` and `import { expect } from \"chai\";`.\n   - Prefer `let redis: Redis`, `beforeEach(() => { redis = new Redis(); })`, and `afterEach(() => { redis.disconnect(); })`.\n   - For version-gated command tests under `test/functional/commands/`, import `isRedisVersionLowerThan` from `../../helpers/util`, and use `before(async function () { ... this.skip(); })`; use function syntax when calling `this.skip()`.\n   - Use unique keys such as `${command}_${caseName}_${Date.now()}`.\n   - Test the ioredis command surface: accepted argument shapes, option ordering, callback behavior, Buffer variants, and reply shape.\n   - Keep assertions focused on what ioredis sends and returns. Do not test Redis server internals beyond the smallest deterministic setup needed.\n   - Assert exact replies when stable; otherwise assert primitive type, nullable behavior, array/object shape, or Buffer conversion.\n\n6. Add typing coverage when useful.\n   - Add cases to `test/typing/commands.test-d.ts` when the command has nontrivial overloads, return types, Buffer variants, callback typing, or option-dependent replies.\n   - Cover `expectType<Promise<...>>(redis.command(...))`.\n   - Add Buffer variant expectations when the command has one.\n   - Add callback typing for nontrivial return types.\n   - Use `expectError` only for meaningful invalid signatures.\n   - Update `test/typing/transformers.test-d.ts` only when transformer APIs are affected.\n\n7. Consider documentation.\n   - Use the repo `docs-sync` skill when command support changes public signatures, return mapping, examples, or documented command behavior.\n   - Usually command support is documented through generated declarations and typing tests; update README/docs only when existing prose or examples cover the affected command family or users need version/topology caveats.\n\n8. Validate.\n   - Run `node bin/index.js` after generator input changes.\n   - Run the focused functional command test when Redis support is available, using the repo's Mocha pattern with `test/helpers/*.ts`.\n   - Run `npm run build` when generated declarations, public TypeScript, or generator output changed.\n   - If typing tests changed, run `npx tsd --files test/typing/commands.test-d.ts` after building.\n   - Use the repo `code-change-verification` skill before handoff to choose any additional validation.\n   - If Redis access is blocked by sandboxing, ask for permission to access the local Redis server rather than assuming it is unavailable.\n\n## Completion Report\n\nReport:\n\n- Commands added or updated.\n- Metadata/generator inputs changed.\n- Generated files changed.\n- Functional tests added or updated.\n- Typing tests added or updated.\n- Documentation decision.\n- Validation commands run and results.\n- Skipped validation with the concrete reason, including Redis version or local environment limits.\n",".agents/skills/pr-draft-summary/SKILL.md":"---\nname: pr-draft-summary\ndescription: Create the required PR-ready summary block, branch suggestion, title, and draft description for ioredis. Must be used before the final response whenever the actual task diff includes runtime code, tests, examples, build/test configuration, or docs with behavior impact, regardless of perceived change size. Skip only when no eligible files changed, every change is repo-meta or docs-only without behavior impact, the task is conversation-only, or the user explicitly opts out.\n---\n\n# PR Draft Summary\n\n## Purpose\n\nProduce a PR-ready summary after eligible work is complete: a concise change summary plus a PR-ready title and draft description for ioredis.\n\n## Close-out Gate\n\n1. Inspect the actual task diff before sending the final response.\n2. Run this skill when the diff includes runtime code, tests, examples, build/test configuration, or docs with behavior impact. Do not use perceived change size to skip an eligible change.\n3. Run it after any required verification and before sending the \"work complete\" response.\n4. Skip only when no eligible files changed, every change is repo-meta or docs-only without behavior impact, the task is conversation-only, or the user explicitly opts out.\n\n## Inputs to Collect Automatically (do not ask the user)\n\n- Current branch: `git rev-parse --abbrev-ref HEAD`.\n- Working tree: `git status -sb`.\n- Untracked files: `git ls-files --others --exclude-standard` (use with `git status -sb`; `--stat` omits them).\n- Changed files: `git diff --name-only` (unstaged) and `git diff --name-only --cached` (staged); sizes via `git diff --stat` and `git diff --stat --cached`.\n- Pull request base reference (prefer the canonical upstream branch; never use a feature branch's upstream as the PR base):\n  - `BASE_REF=upstream/main`; if it does not exist locally, use `origin/main`; if that does not exist locally, use `main`.\n  - `BASE_COMMIT=$(git merge-base \"$BASE_REF\" HEAD)`.\n- Committed branch diff: `git diff --name-only \"${BASE_COMMIT}..HEAD\"` and `git diff --stat \"${BASE_COMMIT}..HEAD\"`.\n- Commits ahead of the base fork point: `git log --oneline --no-merges ${BASE_COMMIT}..HEAD`.\n- Category signals for this repo: runtime (`lib/`, `bin/`, `examples/`, `benchmark/`), tests (`test/`), docs (`docs/`, `README.md`, `AGENTS.md`, `.agents/`, `.github/`), build/test config (`package.json`, `package-lock.json`, `tsconfig.json`, `.eslintrc*`, `.mocharc*`, `nyc.config.js`, `typedoc.json`).\n\n## Workflow\n\n1. Run the commands above without asking the user; compute `BASE_REF`/`BASE_COMMIT` first so later commands reuse them. Compare against `upstream/main`, `origin/main`, or `main`, not the current branch's upstream.\n2. Combine the committed branch diff with staged, unstaged, and untracked changes. If the combined diff is empty, reply briefly that no code changes were detected and skip emitting the PR block.\n3. Infer change type from the touched paths listed under \"Category signals\"; classify as feature, fix, refactor, or docs-with-impact, and flag backward-compatibility risk only when the diff changes released public APIs, client/command behavior, connection config, or the RESP wire handling. Judge that risk against the latest release tag, not unreleased branch-only churn.\n4. Summarize changes in 1–3 short sentences using the top five paths and stats from the committed, staged, and unstaged diffs. Explicitly call out untracked files because `--stat` does not include them. Use commit messages as supporting context, not as a substitute for inspecting the committed diff.\n5. Choose the lead verb for the description: feature → `adds`, bug fix → `fixes`, refactor/perf → `improves` or `updates`, docs-only → `updates`.\n6. Provide a specific topic branch for the contributor's work. Pull requests must not be prepared from `main` or a fork's `main`.\n   - If already off `main`, keep the current branch name and report it as the branch to use.\n   - If on `main`, propose `feat/<slug>`, `fix/<slug>`, or `docs/<slug>` based on the primary area (for example `docs/pr-draft-summary-guidance`) and show a `git checkout -b <branch>` command.\n7. If the current branch matches `issue-<number>` (digits only), keep that branch suggestion. When an issue number is present, reference `https://github.com/redis/ioredis/issues/<number>` and include an auto-closing line such as `This pull request resolves #<number>.` Do not block if the issue cannot be fetched.\n8. Draft the PR title and description using the template below. Use Conventional Commits prefixes for the title (`feat:`, `fix:`, `docs:`, `chore:`, etc.).\n9. Output only the block in \"Output Format\". Keep any surrounding status note minimal and in English. Do not include company-internal references (e.g. Jira/Confluence IDs) in the branch name, title, or description.\n\n## Output Format\n\nWhen closing out a task, add this concise Markdown block (English only) after any brief status note unless the task falls under the documented skip cases or the user says they do not want it.\n\n```\n# Pull Request Draft\n\n## Branch name suggestion\n\n<Either `Current branch: <existing-topic-branch>` when already off `main`, or `git checkout -b <new-topic-branch>` when currently on `main`. Never suggest using `main` as the pull request branch.>\n\n## Title\n\n<single-line imperative title, which can be a commit message; a Conventional Commits prefix such as feat:, fix:, or docs: is preferred>\n\n## Description\n\n<include what you changed plus a draft pull request title and description for your local changes; start the description with prose such as \"This pull request resolves/updates/adds ...\" using a verb that matches the change (you can use bullets later), explain the change background (for bugs, clearly describe the bug, symptoms, or repro; for features, what is needed and why), any behavior changes or considerations to be aware of, and you do not need to mention any tests you ran.>\n```\n\nKeep it tight—no redundant prose around the block, and avoid repeating details between `Changes` and the description. Tests do not need to be listed unless specifically requested.\n",".agents/skills/runtime-behavior-probe/SKILL.md":"---\nname: runtime-behavior-probe\ndescription: Plan and execute runtime-behavior investigations with temporary TypeScript probe scripts, validation matrices, state controls, and findings-first reports. Use only when the user explicitly invokes this skill to verify actual runtime behavior beyond normal code-level checks, especially to uncover edge cases, undocumented behavior, or common failure modes in local or live integrations. A baseline smoke check is fine as an entry point, but do not stop at happy-path confirmation.\n---\n\n# Runtime Behavior Probe\n\n## Overview\n\nUse this skill to investigate real runtime behavior, not to restate code or documentation. Start by planning the investigation, then execute a case matrix, record observed behavior, and report both the findings and the method used to obtain them.\n\n## Core Rules\n\n- Treat this skill as manual-only. Do not rely on implicit invocation.\n- For `ioredis`, treat this skill as a disposable-probe workflow, not a repository implementation workflow.\n- Unless the user explicitly asks for a reusable repository artifact, the allowed write scope is limited to:\n  - a temporary directory used for probe scripts or artifacts\n  - `.agents/skills/runtime-behavior-probe/**` when the user is editing this skill itself\n- For disposable probes in `ioredis`, do not modify `examples/**`, `lib/**`, `test/**`, any `package.json`, `README.md`, build config, or generated files unless the user explicitly asks for a reusable repository artifact or implementation change.\n- If your draft plan would touch a disallowed path, stop and rewrite the plan before editing anything.\n- A baseline success or smoke case is often the right entry point, but do not stop there when the real question involves edge cases, drift, or failure behavior.\n- Plan before running anything. Write the case matrix first, then fill it in with observed results. The matrix can live in a scratch note, a temporary file, or the probe script header.\n- Default to local or read-only probes. Consider a live service only when it is clearly relevant, then apply the lightweight gates below before you run it.\n- Size the probe to the decision. Start with the smallest matrix that can disqualify or validate the current hypothesis, then expand only when uncertainty remains.\n- Before a live probe, apply three lightweight gates:\n  - Destination gate. Use only a live destination that is clearly allowed for the task.\n  - Intent gate. Run the live probe only when the user explicitly wants runtime verification on that integration, or explicitly approves it after you propose the probe.\n  - Data gate. If the probe will read environment variables, mutate remote state, incur material cost, or exercise non-public or user data, name the exact variable names or data class and get explicit approval first.\n- Classify each case as read-only, mutating, or costly before execution. For mutating or costly cases, or for any live case that will read environment variables, define cleanup or rollback before running the probe.\n- Use temporary files or a temporary directory for one-off probe scripts.\n- In `ioredis`, use disposable probe files outside git-tracked paths by default. Do not add one-off probes, harnesses, benchmarks, or examples under `examples/`, `lib/`, `test/`, or other repository directories unless the user explicitly asks for a checked-in artifact.\n- Keep temporary artifacts until the final response is drafted. Then delete them by default unless the user asked to keep them or they are needed for follow-up. Even when artifacts are deleted, keep a short run summary of the command shape, runtime context, and artifact status in the report.\n- Before executing a live probe that will read environment variables, tell the user the exact variable names you plan to use and why, then wait for explicit approval. Examples include `REDIS_URL`, `REDIS_PASSWORD`, and other expected default names for the system under test.\n- Never print secrets, even when they come from standard environment variables that this skill may use.\n- For Redis command or server semantics, treat the repository source as the truth and use [redis.io/commands](https://redis.io/commands) to confirm contract-sensitive details such as argument order, reply types, and version availability. Use runtime probing to validate or challenge the documented behavior, not to skip the documentation pass entirely. If you rely on the website rather than source, say so in the report.\n- For benchmark or comparison probes, make parity explicit before execution. Record what is held constant, what variable is under test, which reply-shape constraints keep the comparison fair, and any counters or timings that matter for interpreting latency or cost.\n- In `ioredis`, default to a light local loop for probe authoring: temporary `probe.ts` plus temporary `tsconfig.json`, `npx tsc --noEmit -p <tmp-tsconfig>`, then `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register <tmp-probe>`. Escalate to `npm run build` only when the runtime question is specifically about `built/`, emitted declarations, or packaged output.\n- In `ioredis`, do not treat a request for runtime verification, benchmarking, or comparison as permission to add a reusable example, benchmark harness, package script, or checked-in sample. Those repository changes require explicit user intent.\n- For probes that need a running Redis, remove setup ambiguity before attributing a negative result to client behavior:\n  - Confirm the server is reachable and note its mode (standalone, cluster, or sentinel) and RESP version before interpreting reply shapes.\n  - Treat RESP2 and RESP3 as separate cases, not interchangeable setup details, when the question is about reply shapes or push messages.\n  - Clear unsupported server-version or command options first so they do not invalidate the probe. Assume a Redis server with the correct version is running on the default host and port unless the task says otherwise; if sandbox access is blocked, ask for permission to access Redis instead of treating Redis as unavailable.\n\n## Workflow\n\n1. Restate the investigation target in operational terms. Name the runtime surface, the key uncertainty, and the highest-risk behaviors to test.\n2. For `ioredis`, declare the allowed write scope before you do any implementation work. For a normal disposable probe, that means a temporary directory only.\n3. Do a short preflight. Check the relevant code or docs first, decide whether the question needs local or live validation, and note any repo, baseline, or release boundary that matters.\n4. Create a validation matrix before executing probes. Cover both baseline behavior and the most relevant failure or drift cases. The matrix can live in a scratch note, a temporary file, or a structured header inside the probe script.\n5. For each case, choose an execution mode up front:\n   - `single-shot` for deterministic one-run checks.\n   - `repeat-N` for cache, retry, streaming, interruption, rate-limit, concurrency, or other run-to-run-sensitive behavior.\n   - `warm-up + repeat-N` when first-run cold-start effects could distort the result. Use these defaults unless the task clearly needs something else:\n   - Quick screen of a repeat-sensitive question: `repeat-3`.\n   - Decision-grade latency or release recommendation: `warm-up + repeat-10`.\n   - Costly live cases: start at `repeat-3`, then expand only if the answer remains unclear. If it is genuinely unclear whether extra runs are worth the time or cost, ask the user before expanding the probe.\n6. When the question is benchmark-like or comparative, run in phases. Start with a high-signal pilot matrix against a control, then expand only the surviving candidates or unresolved cases.\n7. If the question is about a suspected regression or behavior change, add at least one known-good control case such as `origin/master`, the latest release, or the same request without the suspected option.\n8. For comparative probes, define parity before execution. Record prompt or input shape, tool-choice setup, model-settings parity, state reuse rules, and any response-shape constraint that keeps the comparison fair. If materially different output length could bias the result, record usage or token notes too.\n9. If the question asks whether one option has the same intelligence or quality as another, decide whether the matrix supports only example-pattern parity or a broader quality claim. For broader claims, add at least one harder or more open-ended case. Otherwise say explicitly that the result is limited to the covered patterns.\n10. Plan state controls before execution when hidden state could affect the result. Record whether each case uses fresh or reused state, how cache reuse or cache busting is handled, what unique IDs isolate repeated runs, and how cleanup is verified.\n11. If any live case will read environment variables, list the exact variable names and purpose for each case, then ask the user for approval before execution. Keep the approval ask short and include destination, read-only versus mutating or costly risk, exact variable names, and cleanup or rollback if relevant.\n12. Build task-specific probe scripts in a temporary location. Keep the script small, observable, and easy to discard.\n13. If you are about to propose a checked-in script, example, benchmark, or package script for `ioredis`, stop and verify that the user explicitly asked for a reusable repository artifact. If not, keep the probe temporary.\n14. In `ioredis`, make the runtime context explicit:\n\n- Run TypeScript probes from the repository root with `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register <tmp-probe>` when practical.\n- For probe authoring, create both `probe.ts` and a sibling temporary `tsconfig.json` under `mktemp -d`, then run `npx tsc --noEmit -p <tmp-tsconfig>` before the first live execution.\n- Record the current commit, working directory, Node executable, Node version, and the package or source path you imported.\n- Avoid accidental imports from a different checkout or from `/tmp/node_modules`. If the probe needs repository code, import it from an absolute path resolved from `process.cwd()` and a repo-relative path.\n- Prefer current-branch `lib/` imports when the question is \"what does this branch do now?\" and prefer `built/` imports only when the question is specifically about packaged output after a build.\n- Do not run a repository-wide build just to typecheck a disposable probe. Reserve `npm run build` for `built/` probes or when emitted output is itself part of the question.\n\n15. Execute the matrix and capture evidence. Record request shape, setup, observation summary, unexpected or negative result, error details, timing, runtime context, approved environment-variable names, repeat counts, warm-up handling, variance when relevant, cleanup behavior, and for comparisons note what was held constant plus any response-shape or usage notes that affect interpretation.\n16. Update the matrix with actual outcomes, not guesses.\n17. Keep temporary artifacts until the final response is drafted. Then delete them unless the user asked to keep them or they are needed for follow-up. Benchmark and repeat-heavy probes often need follow-up, so keeping artifacts is normal when the result may be revisited. If deleted, retain and report a short run summary.\n18. Report findings first, with unexpected or negative findings first. Then summarize how the validation was performed and which cases were covered.\n19. If the probe isolates one clear defect, you may include a short implementation hypothesis or minimal repro direction. Do not expand into a larger next-step plan unless the user asked for it.\n\n## Validation Matrix\n\nUse a matrix that makes the news easy to scan. Start from the runtime question and the observation summary, not just from `expected` and `pass` or `fail`.\n\nUse a matrix with at least these columns:\n\n- `case_id`\n- `scenario`\n- `mode`\n- `question`\n- `setup`\n- `observation_summary`\n- `result_flag`\n- `evidence`\n\nAdd these columns when they materially improve the investigation:\n\n- `comparison_basis`\n- `variable_under_test`\n- `held_constant`\n- `output_constraint`\n- `status`\n- `confidence`\n- `state_setup`\n- `repeats`\n- `warm_up`\n- `variance`\n- `usage_note`\n- `risk_profile`\n- `env_vars`\n- `approval`\n- `control`\n\nTreat `result_flag` as a fast scan field such as `unexpected`, `negative`, `expected`, or `blocked`. Use `status` only when there is a credible comparison basis, baseline, or documented contract to compare against.\n\nAlways consider whether the matrix should include these categories:\n\n- Baseline success.\n- Control or baseline comparison when a regression is suspected.\n- Boundary input or parameter variation.\n- Invalid or unsupported input.\n- Missing or incorrect configuration.\n- Transient external failure such as timeout, network interruption, or rate limiting.\n- Retry, idempotence, or cleanup behavior.\n- Concurrency or overlapping operations when shared state or ordering may matter.\n- Open-ended quality or intelligence samples when the question is broader than pattern parity.\n\nOpen [validation-matrix.md](./references/validation-matrix.md) when you need a stronger prioritization model or a reusable case template.\n\n## Temporary Probe Scripts\n\nWrite one-off scripts in a temporary file or temporary directory such as one created by `mktemp -d`. Keep the script outside the repository by default, even when it imports code from the repository.\n\nFor `ioredis`, a disposable runtime probe should stay disposable. Do not add a package script, modify build config, or create a checked-in benchmark or example unless the user explicitly asks for a reusable repository artifact.\n\nFor `ioredis`, the default authoring loop should be:\n\n1. `tmpdir=$(mktemp -d)`\n2. Write `probe.ts` and `tsconfig.json` into `$tmpdir`\n3. From the repository root, run `npx tsc --noEmit -p \"$tmpdir/tsconfig.json\"`\n4. If the quick typecheck passes, run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register \"$tmpdir/probe.ts\"`\n5. Only run `npm run build` if the probe intentionally imports `built/` or validates packaged output\n\nUse a temporary `tsconfig.json` that extends the repository base settings but includes only the disposable probe, for example:\n\n```json\n{\n  \"extends\": \"/absolute/path/to/ioredis/tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"types\": [\"node\"],\n    \"typeRoots\": [\"/absolute/path/to/ioredis/node_modules/@types\"]\n  },\n  \"include\": [\"./probe.ts\"]\n}\n```\n\nIf the probe needs repository code:\n\n- Run it with the repository root as the working directory.\n- Use `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/probe.ts` from the repository root when practical.\n- Use `npx tsc --noEmit -p /tmp/probe-tsconfig.json` as the default quick typecheck step before executing the probe.\n- Import repository modules with an absolute path built from `process.cwd()` and a repo-relative path. Do not assume bare imports such as `ioredis` will resolve to the current checkout from `/tmp`.\n- Use `lib/` imports for current-branch behavior probes and `built/` imports for packaged-output probes.\n\nDesign the probe to maximize observability:\n\n- Print or log the exact scenario being exercised.\n- Capture runtime context such as git SHA, working directory, Node executable and version, relevant package versions, model or deployment name, endpoint or base URL alias, and any retry or tool options that materially affect behavior.\n- For live probes, record only the names of environment variables that were approved for use. Never print their values.\n- Capture structured outputs when possible.\n- Preserve raw error type, message, and status code.\n- For repeat-sensitive cases, capture the attempt index, warm-up status, and any stable identifiers that help compare runs.\n- For repeated or benchmark-style probes, write both raw results and a compact summary artifact when practical.\n- Keep branching minimal so each script answers a narrow question.\n\nBefore deleting the temporary script or directory, keep a short run summary of the script path, command used, runtime context, and whether the evidence was kept or deleted.\n\nOpen [typescript_probe.ts](./templates/typescript_probe.ts) when you want a lightweight disposable TypeScript probe scaffold. Open [repo-import-patterns.md](./references/repo-import-patterns.md) when you need to load current-branch workspace code from a temporary script.\n\n## Reporting\n\nReport in this order:\n\n1. Findings. Put unexpected or negative findings first. If there was no real news, say that explicitly.\n2. Validation approach. Summarize the code used, the runtime surface exercised, the execution modes, and the case matrix coverage.\n3. Case results. Include the matrix or a condensed version of it when the case count is large.\n4. Artifact status and brief run summary. State whether temporary artifacts were deleted or kept, and provide kept paths or the retained summary.\n5. Optional implementation note. Include this only when one clear defect was isolated and a short implementation direction would help.\n\nFor comparative probes, the report should also say what was held constant, what variable was under test, and whether the result supports only pattern parity or a broader quality claim.\n\nOpen [reporting-format.md](./references/reporting-format.md) for the recommended response template.\n\n## Resources\n\n- Open [validation-matrix.md](./references/validation-matrix.md) to design and prioritize the case matrix.\n- Open [error-cases.md](./references/error-cases.md) to expand common failure scenarios.\n- Open [redis-runtime-patterns.md](./references/redis-runtime-patterns.md) for recurring ioredis runtime probe patterns.\n- Open [repo-import-patterns.md](./references/repo-import-patterns.md) for repository-relative TypeScript import guidance.\n- Open [reporting-format.md](./references/reporting-format.md) for the final report structure.\n- Open [typescript_probe.ts](./templates/typescript_probe.ts) for a minimal disposable TypeScript probe scaffold.\n",".agents/skills/runtime-behavior-probe/references/error-cases.md":"# Common Error Cases\n\nUse this reference to expand beyond the happy path. Favor error cases that a real user or operator is likely to hit.\n\n## Configuration Errors\n\nCheck whether the runtime behaves differently for:\n\n- Missing required environment variables.\n- Present but malformed secrets or identifiers.\n- Wrong endpoint or base URL.\n- Wrong model or deployment name.\n- Incompatible local dependency versions.\n\nLook for:\n\n- Error type and status code.\n- Whether the failure is immediate or delayed.\n- Whether the message is actionable.\n- Whether retrying without fixing configuration changes anything.\n\n## Input Errors\n\nProbe common bad-input patterns such as:\n\n- Missing required fields.\n- Wrong data type.\n- Unsupported enum or option value.\n- Empty but syntactically valid input.\n- Oversized input or too many items.\n- Mutually incompatible options.\n\nPrefer realistic invalid inputs over artificial nonsense. The point is to learn how the runtime fails in practice.\n\n## Transport and Availability Errors\n\nWhen networked services are involved, consider:\n\n- Connection failure.\n- Read timeout.\n- Server timeout or upstream gateway error.\n- Rate limit response.\n- Partial stream interruption.\n- Reusing a connection after a failure.\n\nCapture whether the client library retries automatically, whether it surfaces retry metadata, and whether the final exception preserves the original cause.\n\n## State and Repetition Errors\n\nMany surprising bugs appear only when an operation is repeated or interrupted:\n\n- Re-submit the same request.\n- Repeat after a timeout.\n- Retry after a partial tool call or partial stream.\n- Resume after local cleanup or process restart.\n- Repeat with slightly changed inputs while reusing shared state.\n\nObserve whether the operation is idempotent, duplicated, silently ignored, or left in a partial state.\n\n## Concurrency Errors\n\nWhen shared state, ordering, or isolation may matter, consider:\n\n- Two overlapping requests with the same logical input.\n- Parallel runs that reuse the same cache key, session, container, or temporary resource.\n- Concurrent retries, cancellation, or cleanup racing with active work.\n- Output or event streams from one run leaking into another.\n\nCapture whether the runtime serializes, rejects, duplicates, corrupts, or cross-contaminates the work.\n\n## Investigation Heuristics\n\nUse these heuristics to pick error cases quickly:\n\n- Ask which failure a real engineer would debug first in production.\n- Ask which failure is most expensive if it is misunderstood.\n- Ask which failure would be invisible from code review alone.\n- Ask which failure path is likely to differ across environments.\n\nIf the error behavior is already perfectly obvious from a local validator or type system, it is usually low priority for this skill.\n",".agents/skills/runtime-behavior-probe/references/redis-runtime-patterns.md":"# Redis Runtime Patterns\n\nUse this reference for recurring ioredis investigations so you do not have to rediscover the probe strategy each time. Treat the repository source as the truth for client behavior, and use [redis.io/commands](https://redis.io/commands) to confirm contract-sensitive details such as argument order, reply types, and version availability. If you rely on the website rather than source, say so in the report.\n\n## General Rules\n\n- Prefer small, focused probes over large harnesses. Keep one script focused on one uncertainty.\n- For comparative or benchmark-like questions, start with a pilot and expand only when the answer is still unclear.\n- Capture the request shape (command and arguments as sent) and the observed command result or emitted event payload.\n- Preserve raw error type, message, and any Redis error prefix such as `WRONGTYPE`, `MOVED`, `ASK`, `CROSSSLOT`, `NOSCRIPT`, or `LOADING`.\n- Record whether behavior differs between the first call and a repeated call, and across a reconnect.\n- When the question is about regression or contract drift, add a known-good control run before attributing the result to the change under investigation.\n- Keep comparison parity explicit. Record what was held constant, what variable changed, and whether reply-shape or encoding differences could bias the conclusion.\n- Record the runtime context that actually changes Redis client behavior: server mode (standalone, cluster, sentinel), RESP version (2 vs 3), server version, and whether a feature such as auto-pipelining or sharded pub/sub is in use.\n\n## Connection Environment Variables\n\nDo not read these variables automatically. Before a live probe uses any of them, tell the user the exact variable names you plan to read and why each one is needed, then wait for explicit approval. Never print their values:\n\n- `REDIS_URL`\n- `REDIS_PASSWORD`\n- `REDIS_TLS_CA`, `REDIS_TLS_CERT`, `REDIS_TLS_KEY` (and any other `REDIS_TLS_*` the probe needs)\n\nFor most local probes you do not need any of these. ioredis repository instructions assume a Redis server with the correct version is running on the default host and port. Prefer that local Redis server over a live remote service unless the question is specifically about the remote deployment.\n\nIf the task targets another integration, use that integration's expected default variable names under the same rule.\n\n## Environment False Signals\n\nBefore attributing a failure to the patch or client code under review, exclude source-selection and environment problems with a controlled comparison.\n\n- Confirm the commit, worktree, working directory, Node executable/version, and imported module path. A probe of stale `built`, another checkout, `/tmp/node_modules`, or an installed `ioredis` package does not prove current `lib` behavior.\n- Rebuild when emitted declarations, package exports, generated command typings, or `built` is the subject. Otherwise prefer current-source `lib/` imports so stale build output cannot create a false result.\n- Confirm a Redis server is actually running and reachable. A connection refused or timeout against a missing Docker/Redis container is an environment condition, not a client defect, until a controlled rerun against a known-good server ties it to the code.\n- Confirm the RESP version the client negotiated. A reply-shape surprise is often just RESP2 vs RESP3, not a bug.\n- Confirm server mode matches the probe assumptions. Running a cluster-only expectation against a standalone server, or the reverse, produces misleading routing and slot errors.\n- Run base and head controls with the same Node version, dependency graph, server mode, RESP version, environment-variable names, and command shape. Record intentional differences.\n- Treat sandbox denials, unavailable Docker infrastructure, expired remote sessions, authentication, quota, rate limits, service outages, and stale caches as environment conditions until a controlled rerun ties them to the patch.\n- Never print credentials, connection URLs with embedded passwords, or TLS key material. Change only the minimum in-scope environment or disposable state needed for the control and record variable names rather than values.\n\nIn the final report, distinguish code failures, unsupported configurations, environment blockers, and inconclusive probes. Do not collapse them into one failed-test count.\n\n## ioredis Probe Patterns\n\nStart from the uncertainty instead of from the full client surface. The patterns below cover the runtime questions that recur most often in ioredis.\n\n### RESP2 vs RESP3 reply shapes\n\nUse when the uncertainty is what a command returns at runtime.\n\n- Run the same command under RESP2 and RESP3 as separate cases when protocol differences are part of the uncertainty.\n- Capture the observed command result and whether the client returns plain objects, `Map`, arrays, `null`, buffers, strings, or numbers.\n- Watch precision-sensitive numeric replies and record the exact value.\n\n### Single-node vs cluster vs sentinel\n\nUse when key routing, slot ownership, or topology matters.\n\n- For cluster, capture which node served the command and whether a `MOVED` or `ASK` redirect occurred. Probe multi-key commands across keys in different slots to observe `CROSSSLOT` behavior and any client-side slot checks.\n- Use hash tags (`{tag}`) to force keys into the same slot when the probe needs a multi-key command to succeed.\n- For sentinel, capture master discovery and what happens on a simulated failover.\n- Keep mode constant within a case. A standalone control alongside a cluster case is a useful comparison, not a substitute.\n\n### Pub/sub and sharded pub/sub\n\nUse when delivery semantics or resubscription matter.\n\n- Capture subscribe confirmation, message delivery order, emitted event names, and whether messages are delivered to pattern (`PSUBSCRIBE`) and channel subscribers as expected.\n- For sharded pub/sub (`SSUBSCRIBE` and `SPUBLISH`) in cluster, capture which shard delivered the message.\n- Force a reconnect and observe whether the client resubscribes to channels and patterns automatically. This is a common drift point.\n\n### Reconnection, retry, and the offline command queue\n\nUse when the question is about resilience.\n\n- Simulate a dropped connection (stop or restart the container, or close the socket) and capture: whether commands issued while offline are queued, the order they flush in on reconnect, and whether the reconnect strategy backoff behaves as configured.\n- Distinguish commands rejected immediately from commands queued and later resolved or rejected.\n- Capture whether in-flight commands at disconnect are retried, rejected, or hang.\n\n### Pipelining and MULTI/EXEC transactions\n\nUse when batching or atomicity is under test.\n\n- For pipelining, confirm replies map back to the right commands in order, including when one command in the batch errors.\n- For `MULTI`/`EXEC`, capture queueing errors versus execution errors, behavior on `DISCARD`, and `WATCH` optimistic-locking aborts (`EXEC` returning `null`).\n\n### RESP3 push messages and subscribed connection behavior\n\nUse when push-message routing or subscribed connection behavior matters.\n\n- Requires RESP3 when the question depends on push-message behavior. Capture whether push replies are routed to events, whether regular commands are allowed while subscribed, and whether replies preserve expected buffer/string variants.\n- Probe RESP2 and RESP3 separately when subscribed-mode command behavior or push reply shape is part of the uncertainty.\n\n### Blocking commands and connection isolation\n\nUse for `BLPOP`, `BRPOP`, `XREAD BLOCK`, `WAIT`, and similar.\n\n- Capture whether the blocking command monopolizes a connection and whether the caller needs a separate Redis instance so other commands are not stalled.\n- Probe timeout behavior and what resolves when the block is satisfied by another client versus when it times out.\n\n### Auto-pipelining and command queues\n\nUse when same-tick batching, offline queue behavior, or command queue ordering is involved.\n\n- Capture which commands are batched, whether disabled commands bypass auto-pipelining, and whether reply order matches command order.\n- For reconnect-sensitive questions, distinguish offline queue entries, in-flight commands, and commands rejected because the connection state does not allow queuing.\n\n### SCAN iterators\n\nUse for `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`.\n\n- Capture cursor progression, whether the async iterator terminates, and whether `COUNT` and `MATCH` behave as expected. Note that SCAN gives no count or completeness guarantees mid-iteration.\n\n### Large payloads and timeouts\n\nUse when size or latency is the concern.\n\n- Capture behavior with large values and large reply sets, and whether command-level or socket timeouts fire as configured.\n- For repeat-sensitive latency, use warm-up plus repeat-N and record medians, not a single sample.\n\n## What to Capture\n\nFor ioredis probes, try to record:\n\n- The command and arguments as sent, plus the observed result or emitted event payload.\n- The JavaScript value and its type, including buffer variants when relevant.\n- Server mode (standalone, cluster, or sentinel), negotiated RESP version, and server version.\n- Whether fields are absent, `null`, empty, or transformed by the client.\n- Raw error type, message, and any Redis error prefix for failures.\n- Reconnect and retry behavior, offline-queue flush order, and resubscription on reconnect when relevant.\n- For cluster, which node served the command and any redirect.\n- Which environment-variable names were approved for the probe when a live or credentialed server was required.\n\nDo not spend time rediscovering static documentation unless the runtime result seems to contradict what you expected. The value of this skill is in the observed behavior.\n",".agents/skills/runtime-behavior-probe/references/repo-import-patterns.md":"# Repository Import Patterns\n\nUse this reference when a temporary probe script outside the repository needs to load code from the current branch.\n\n## Why This Exists\n\nWhen you run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/probe.ts` from the repository root, `ts-node` itself comes from this repository, but the probe file still lives under `/tmp`. Bare imports such as `ioredis` can resolve as if the script were its own package. That is often not what you want for \"what does the current branch do right now?\" investigations.\n\nThe safe default is to build an absolute path from `process.cwd()`, which should be the repository root, and a repository-relative path.\n\n## Default Rule\n\n- Use `lib/` imports when the question is about current-branch behavior.\n- Use `built/` imports when the question is about packaged output after a build.\n- Avoid bare package imports from `/tmp` unless the probe is explicitly testing published package resolution rather than branch-local source behavior.\n\n## Quick Typecheck Loop\n\nFor disposable probes in `ioredis`, the default loop should stay outside the repository and avoid a full package build:\n\n1. Create a temporary directory with `mktemp -d`.\n2. Write `probe.ts` there.\n3. Write a sibling `tsconfig.json` that extends the repository's `tsconfig.json`.\n4. From the repository root, run `npx tsc --noEmit -p /tmp/.../tsconfig.json`.\n5. If that passes, run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/.../probe.ts`.\n\nExample temporary `tsconfig.json`:\n\n```json\n{\n  \"extends\": \"/absolute/path/to/ioredis/tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"types\": [\"node\"],\n    \"typeRoots\": [\"/absolute/path/to/ioredis/node_modules/@types\"]\n  },\n  \"include\": [\"./probe.ts\"]\n}\n```\n\nThis keeps TypeScript module resolution and strictness close to the repository defaults while limiting the check surface to the disposable probe file.\n\nDo not convert this default loop into a checked-in benchmark, example, or package script unless the user explicitly asks for a reusable repository artifact.\n\n## Recommended Helper\n\nThe disposable TypeScript scaffold exposes:\n\n    const module = await importRepoModule(\"lib/index.ts\");\n\nInternally, the helper should be equivalent to:\n\n    import { createRequire } from \"module\";\n    import { resolve } from \"path\";\n\n    const repoRequire = createRequire(resolve(process.cwd(), \"package.json\"));\n\n    async function importRepoModule(repoRelativePath: string) {\n      const absolutePath = resolve(process.cwd(), repoRelativePath);\n      return Promise.resolve(repoRequire(absolutePath));\n    }\n\nThis keeps the import anchored to the current checkout instead of the temporary script location.\n\n## Choosing `lib/` Versus `built/`\n\nUse `lib/` when:\n\n- You are validating a bug fix or regression on the current branch.\n- You want to know how the repository behaves before packaging.\n- The question is about implementation details or internal helper behavior.\n\nUse `built/` when:\n\n- The question is specifically about what consumers load after `npm run build`.\n- You need to validate export maps or emitted `.js` and `.d.ts` output.\n- The bug only reproduces in generated output.\n\nIf the probe uses `built/`, record whether you ran a fresh build first. A stale `built/` directory can create false positives or false negatives.\n\nDo not run `npm run build` only to typecheck or execute a `lib/`-based disposable probe. The fast path is temp `tsconfig` plus `npx tsc --noEmit`, then `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register`.\n\n## Simple Smoke Targets\n\nWhen you only need to prove the helper works, start with a simple target that has minimal side effects, for example:\n\n- `lib/index.ts`\n- `lib/Redis.ts`\n- `lib/Command.ts`\n- another file with obvious exported symbols and no environment requirement\n\nIf a chosen file pulls in more of the repo than expected, switch to a simpler target rather than weakening the import guidance.\n\n## What To Record\n\nWhen a probe imports repo code, report:\n\n- The repo-relative path you imported.\n- Whether it came from `lib/` or `built/`.\n- The repository root used by `process.cwd()`.\n- Any prerequisite step such as `npm run build`.\n",".agents/skills/runtime-behavior-probe/references/reporting-format.md":"# Reporting Format\n\nLead with findings, not process. The user asked for investigation results, so the answer should start with the most important observed behaviors. Put the real news first.\n\n## Recommended Order\n\n1. Findings.\n2. Validation approach.\n3. Case matrix or condensed case summary.\n4. Artifact status and brief run summary.\n5. Optional implementation note.\n\n## Findings Section\n\nMake each finding answer one user-relevant question. Good findings usually include:\n\n- What was observed.\n- Why it matters.\n- The condition under which it happens.\n- What was held constant when the finding comes from a comparison probe.\n- `scope`: The boundary of the finding, such as commit, model, Node version, live versus local, or repeat mode.\n- `confidence`: `high`, `medium`, or `low`.\n\nAvoid burying the main result under setup details.\n\nPut `unexpected` or `negative` findings first. If there were no unexpected or negative findings in the executed cases, say that explicitly before the rest of the findings section.\n\nIf the probe was comparative, say whether the result supports:\n\n- Pattern parity only.\n- A broader quality claim.\n\nDo not imply a broader quality equivalence than the executed cases justify.\n\n## Validation Approach Section\n\nSummarize:\n\n- The runtime surface you exercised.\n- The shape of the probe code, in overview only.\n- Which categories of cases you covered.\n- Which execution modes you used, including repeat counts or warm-up handling when relevant.\n- Whether live credentials or external services were used.\n- Any important state controls such as fresh state, cache reuse, cache busting, unique IDs, or cleanup verification.\n- For comparison probes, what was held constant, what was varied, and whether output-shape or usage differences could still influence the conclusion.\n- Whether the usual docs path or an official-docs fallback was used for contract-sensitive checks.\n\nKeep this concise. The user needs enough detail to trust the result, not a line-by-line replay of the script.\n\n## Case Summary\n\nInclude either the full matrix or a condensed summary. At minimum, show:\n\n- Which scenarios were executed.\n- Whether the run was a quick pilot, an expanded matrix, or both.\n- Which ones produced `unexpected` or `negative` results.\n- Which ones passed or failed when a real comparison basis existed.\n- Which cases were blocked.\n- Where the supporting evidence lived, or that it was deleted.\n\nIf the matrix is large, show the highest-value cases in the main response and keep the rest as a compact appendix or note.\n\n## Artifact Status And Brief Run Summary\n\nState one of these explicitly:\n\n- Temporary artifacts were kept until the final response was drafted, then deleted after validation.\n- Temporary artifacts were kept at `<path>` because the user asked to keep them.\n- Temporary artifacts were kept at `<path>` because they are needed for follow-up analysis.\n\nEven if artifacts were deleted, retain a short run summary such as:\n\n- Probe command or runner shape.\n- Runtime context summary such as commit, Node executable, Node version, or model.\n- Artifact path and final status.\n\nFor benchmark or repeat-heavy probes, keeping artifacts for follow-up is often the right default even when the immediate report is done.\n\n## Optional Implementation Note\n\nInclude this only when one clear defect was isolated and a short implementation hypothesis or minimal repro direction would help. Keep it brief. Do not turn the report into a broader next-step plan unless the user asked for that.\n\n## Compact Template\n\nUse this outline when you need a fast structure:\n\n    Findings:\n    - <finding 1>\n      held constant: <prompt/tool/state settings kept the same, if comparative>\n      scope: <commit/model/node/live-local/repeat-mode>\n      confidence: <high|medium|low>\n    - <finding 2>\n      held constant: <prompt/tool/state settings kept the same, if comparative>\n      scope: <commit/model/node/live-local/repeat-mode>\n      confidence: <high|medium|low>\n\n    Validation approach:\n    - Surface: <what was exercised>\n    - Probe code: <brief overview>\n    - Coverage: <success, edge, error, repeat-sensitive, and quality categories>\n    - Execution modes: <single-shot|repeat-N|warm-up + repeat-N>\n    - Comparison parity: <what was held constant and what varied, if comparative>\n    - Docs source: <MCP or official-docs fallback, if relevant>\n\n    Case summary:\n    | case_id | scenario | result_flag | status | note |\n    | --- | --- | --- | --- | --- |\n    | S1 | ... | expected | pass | ... |\n    | E1 | ... | negative | fail | ... |\n\n    Artifact status and brief run summary:\n    - Temporary artifacts were kept until the final response was drafted, then deleted.\n    - Summary: <command/runtime-context/artifact-status summary>\n\n    Optional implementation note:\n    - <brief hypothesis or minimal repro direction>\n\nAdjust the format to the task, but preserve the ordering.\n",".agents/skills/runtime-behavior-probe/references/validation-matrix.md":"# Validation Matrix\n\nUse the matrix to decide what to probe before writing scripts. The goal is not exhaustive combinatorics; the goal is high-value coverage that is visible, explainable, and likely to reveal runtime surprises. The matrix should make the real news easy to scan.\n\n## Minimum Columns\n\nUse these columns unless the task clearly needs more:\n\n- `case_id`: Stable identifier such as `S1`, `E3`, or `R2`.\n- `scenario`: Short description of the behavior under test.\n- `mode`: `single-shot`, `repeat-N`, or `warm-up + repeat-N`.\n- `question`: The concrete runtime uncertainty this case is answering.\n- `setup`: Inputs, environment, or preconditions required for the case.\n- `observation_summary`: A compact summary of what actually happened.\n- `result_flag`: `unexpected`, `negative`, `expected`, or `blocked`.\n- `evidence`: Path, log reference, or `deleted`.\n\nAdd these columns when they materially improve the investigation:\n\n- `comparison_basis`: The baseline, docs, or prior behavior you are comparing against.\n- `variable_under_test`: The single factor that is intentionally changing in a comparison case.\n- `held_constant`: Prompt shape, tool setup, model settings, or state rules that were intentionally kept the same.\n- `output_constraint`: Any schema, length, or response-shape constraint used to keep the comparison fair.\n- `status`: Use `pass`, `fail`, `unexpected-pass`, `unexpected-fail`, or `blocked` only when there is a credible comparison basis or control.\n- `confidence`: `high`, `medium`, or `low`.\n- `state_setup`: Fresh or reused state, cache strategy, unique IDs, and cleanup checks.\n- `repeats`: Number of measured runs.\n- `warm_up`: Whether a warm-up run was used and why.\n- `variance`: Any useful spread or instability note across repeated runs.\n- `usage_note`: Token, usage, or output-length note when it materially affects interpretation.\n- `control`: Known-good comparison point for regression or behavior-change questions.\n- `risk_profile`: `read-only`, `mutating`, or `costly` for live probes.\n- `env_vars`: Exact environment-variable names the case plans to read.\n- `approval`: `not-needed`, `pending`, or `approved` for cases that need user permission before execution.\n\nUse `result_flag` as the fast scan field. It is what makes unexpected or negative findings jump out before the reader studies the full report.\n\nUse `status` only when you have a real comparison basis. If the case is exploratory and there is no trustworthy baseline, prefer a strong `observation_summary` plus `result_flag` and `confidence` instead of pretending the result is a clean pass or fail.\n\n## Choosing Execution Mode\n\nPick an execution mode before you run the case:\n\n- Use `single-shot` for deterministic, one-run checks.\n- Use `repeat-N` automatically when the question involves cache behavior, retries, streaming, interruptions, rate limiting, concurrency, or other run-to-run-sensitive behavior.\n- Use `warm-up + repeat-N` when the first run is likely to include cold-start effects such as container provisioning, import caches, or prompt-cache population.\n\nUse these defaults unless the task clearly needs something else:\n\n- `repeat-3` for a quick screen of a repeat-sensitive question.\n- `warm-up + repeat-10` for decision-grade latency comparisons or release-facing recommendations.\n- For costly live probes, start at `repeat-3`, then expand only if the answer is still unclear.\n\nIf it is genuinely unclear whether extra runs are worth the time or cost, ask the user before expanding the probe.\n\n## Phase The Matrix\n\nWhen the question is comparative or benchmark-like, do not jump straight to the largest matrix.\n\nStart with a pilot:\n\n- One control.\n- One or two highest-signal success cases.\n- The smallest repeat count that can disqualify a weak candidate quickly.\n\nExpand only when:\n\n- The candidate survives the pilot.\n- The results are close enough that more samples matter.\n- A major runtime surface is still uncovered.\n- The user explicitly wants decision-grade evidence.\n\n## Coverage Categories\n\nTry to cover at least one case from each relevant category:\n\n- `success`: Normal behavior that should work.\n- `control`: Known-good comparison such as `origin/master`, the latest release, or the same request without the suspected option.\n- `boundary`: Size, count, or parameter limits near a plausible edge.\n- `invalid`: Bad inputs or unsupported combinations.\n- `misconfig`: Missing key, wrong endpoint, bad permissions, or incompatible local setup.\n- `transient`: Timeout, temporary server issue, network breakage, or rate limiting.\n- `recovery`: Retry behavior, partial completion, duplicate submission, or cleanup.\n- `concurrency`: Overlapping operations when shared state, ordering, or isolation may matter.\n- `quality`: A harder or more open-ended sample when the user is asking about model intelligence, not just workflow parity.\n\nIf time is limited, prioritize categories in this order:\n\n1. Known-good control when the question implies regression or drift.\n2. Highest-risk success case.\n3. Most plausible user-facing failure.\n4. Most likely edge case with ambiguous behavior.\n5. Cleanup or retry semantics.\n6. Lower-probability extremes.\n\n## Matrix Template\n\nUse this compact template:\n\n    | case_id | scenario | mode | question | setup | state_setup | variable_under_test | held_constant | comparison_basis | observation_summary | result_flag | status | evidence |\n    | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n    | K1 | Known-good control | single-shot | Does the baseline still show the expected behavior? | Same probe against baseline target | Fresh state | none | current probe shape | `origin/master` or latest release | pending | pending | pending | pending |\n    | S1 | Baseline success | single-shot | What does the normal success path look like at runtime? | Valid config and representative input | Fresh state | none | representative input and setup | current docs or local expectation | pending | pending | pending | pending |\n    | R1 | Cache or retry behavior | warm-up + repeat-N | Does behavior change after the first run or across retries? | Same request repeated under controlled settings | Cache key or retry setup recorded | reuse versus fresh state | prompt shape and tool setup | same request without reuse, or docs if available | pending | pending | pending | pending |\n    | C1 | Model comparison pilot | warm-up + repeat-N | Does candidate B preserve the covered behavior while improving latency? | Same scenario across two models | Fresh state and stable IDs | model name | prompt shape, tool choice, and model settings parity | control model in the same probe | pending | pending | pending | pending |\n    | E1 | Invalid input | single-shot | How does the runtime reject a realistic bad input? | Missing required field | Fresh state | invalid field value | same request with valid field | same request with valid field | pending | pending | pending | pending |\n    | X1 | Concurrent overlap | repeat-N | Do overlapping runs interfere with each other? | Two or more overlapping operations | Unique IDs plus cleanup verification | overlap timing | same logical input | same request serialized, if available | pending | pending | pending | pending |\n\n## Recording Results\n\nKeep `question` unchanged after execution. Put the actual behavior in `observation_summary`, then mark the scan-friendly `result_flag`.\n\nUse these `result_flag` values consistently:\n\n- `unexpected`: The result diverged from the best current understanding in a surprising way.\n- `negative`: The result exposed a user-relevant failure, risk, or sharp edge.\n- `expected`: The result matched the current understanding and did not reveal new risk.\n- `blocked`: The case did not produce a trustworthy observation.\n\nOnly fill `status` when there is a credible comparison basis. Otherwise use `observation_summary`, `result_flag`, and `confidence` to communicate what was learned without over-claiming certainty.\n\nFor comparison cases, use `observation_summary` and the final report to say whether the evidence supports pattern parity only or a broader quality claim.\n\nIf a case reveals a new branch of behavior, add a follow-up case instead of overloading the original one.\n\n## Evidence Discipline\n\nTreat a case as incomplete when:\n\n- The observed output omits the key result you were testing.\n- The script mixed multiple questions and the result is ambiguous.\n- Hidden state, cache behavior, or previous runs may have influenced the result and were not controlled or documented.\n- The question is whether behavior changed, but the case has no credible control or baseline to compare against.\n- The case plans to read environment variables, but the exact variable names were not approved by the user before execution.\n- The case was repeat-sensitive, but it ran only once without a clear rationale.\n\nWhen this happens, narrow the probe and rerun. A smaller script with a cleaner result is better than a more complicated script that is hard to trust.\n","AGENTS.md":"# AGENTS.md\n\nThis file provides guidance to AI coding agents (Claude Code, Codex, Copilot, Cursor, Aider, etc.) when working with code in this repository.\n\n## Project Overview\n\nioredis is a full-featured Redis client for Node.js, written 100% in TypeScript. Source lives in `lib/`, compiles to CommonJS in `built/` (the published artifact), and supports standalone, Sentinel, and Cluster topologies.\n\n## Common Commands\n\n### Building\n\n```bash\nnpm run build          # Wipe built/ and compile TypeScript\nnode bin/index.js      # Regenerate lib/utils/RedisCommander.ts\n```\n\n### Linting and Formatting\n\n```bash\nnpm run lint           # Run ESLint over lib/\nnpm run format         # Format files with Prettier\nnpm run format-check   # Check formatting\n```\n\n### Testing\n\nFunctional and cluster tests require running Redis servers. Unit tests under `test/unit/` mock the network and do not need a server.\n\nTo start and stop local Redis test infrastructure:\n\n```bash\nnpm run docker:setup      # Start standalone Redis on 6379 and cluster nodes on 3000-3005\nnpm run docker:teardown   # Stop test Redis servers\n```\n\n```bash\nnpm test                  # Default non-cluster test: test:js then test:tsd\nnpm run test:js           # Mocha over test/helpers, test/unit, test/functional\nnpm run test:cluster      # Mocha over test/cluster\nnpm run test:tsd          # Build then run tsd against test/typing\nnpm run test:cov          # Test coverage\n\n# Run a single test file\nTS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/foo.ts\"\n\n# Run a single test by name\nTS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/foo.ts\" --grep \"partial test title\"\n```\n\n## Generated Code\n\n**Do not hand-edit**: `lib/utils/RedisCommander.ts` (generated), `built/` (build output), and `node_modules/`.\n\n`lib/utils/RedisCommander.ts` holds the typed signatures for every Redis command. This is what gives calls like `redis.set(...)` their types.\n\nRegenerate it with:\n\n```bash\nnode bin/index.js\n```\n\nGeneration uses `@ioredis/interface-generator` plus per-command config in `bin/`:\n\n- **`bin/template.ts`** — File skeleton; generated interface is spliced into the `////` marker.\n- **`bin/overrides.js`** — Hand-written signatures for commands the generator gets wrong, such as `hgetall` and `mset`.\n- **`bin/argumentTypes.js`**, **`bin/returnTypes.js`**, **`bin/sortArguments.js`**, **`bin/typeMaps.js`** — Argument and return type mapping and ordering.\n\nWhen adding command typing support, edit the `bin/` config and regenerate. Never patch `RedisCommander.ts` directly.\n\n## Architecture\n\n### Layered Design\n\n```text\nPublic API (`Redis`, `Cluster`, `Pipeline`, `Command`, options)\n  → Command facade (`Commander`, generated `RedisCommander` typings, Lua scripts)\n    → Command objects and queues (`Command`, offline queue, command queue, pipeline queue)\n      → Topology routing (standalone, Sentinel, Cluster slots, subscriber groups)\n        → Connection layer (`connectors/`, `redis/event_handler.ts`, retry and ready checks)\n          → RESP parsing and reply handling (`DataHandler`, `redis-parser`)\n```\n\n### Key Source Areas\n\n- **`lib/index.ts`** — Public export surface for the package. Changes here affect the published TypeScript declarations and user-facing API.\n- **`lib/Redis.ts`** — Main standalone and Sentinel client. Manages connection lifecycle (`wait → connecting → connect → ready → close → reconnecting → end`), offline queue behavior, reconnection strategy, and connector selection.\n- **`lib/utils/Commander.ts`** — Shared command facade for `Redis` and `Cluster`. Dynamically attaches builtin Redis commands, string and `Buffer` variants, autopipelining dispatch, direct `sendCommand`, and `defineCommand` Lua registration.\n- **`lib/Command.ts`** — Single Redis command representation. Handles argument transformation, reply transformation, promise/callback resolution, key-slot calculation, and subscriber/monitor-mode command flags.\n- **`lib/DataHandler.ts`** — Parser and reply dispatcher. Wraps `redis-parser`, consumes socket data, resolves queued commands, and routes Pub/Sub replies and monitor messages.\n- **`lib/connectors/`** — Network connector implementations. `StandaloneConnector` handles TCP/TLS sockets; `SentinelConnector/` resolves masters through Sentinel using `FailoverDetector` and `SentinelIterator`.\n- **`lib/cluster/`** — Cluster client, per-node connection pool, slot cache refresh, redirection handling for `MOVED` and `ASK`, retry scheduling, and cluster Pub/Sub through `ClusterSubscriber`, `ShardedSubscriber`, and `ClusterSubscriberGroup`.\n- **`lib/Pipeline.ts`** and **`lib/transaction.ts`** — Batched command execution. `pipeline()` is non-atomic batching; `multi()` adds MULTI/EXEC transaction behavior.\n- **`lib/autoPipelining.ts`** — Same-tick command batching. `notAllowedAutoPipelineCommands` lists commands that must bypass autopipelining, such as auth, subscribe, and multi.\n- **`lib/Script.ts`** — Lua script abstraction used by `defineCommand`, with `EVALSHA` execution and `EVAL` fallback.\n- **`lib/ScanStream.ts`** — Readable stream wrapper for `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`.\n- **`lib/tracing.ts`** — Command and connection tracing hooks with argument sanitization.\n\n### How Commands Execute\n\n1. User calls a method such as `redis.get()` or `cluster.set()`.\n2. `Commander` routes the call through autopipelining, pipeline/transaction handling, or direct `sendCommand`.\n3. A `Command` object is created with transformed arguments and callback/promise state.\n4. Standalone clients enqueue the command on one connection; Cluster clients choose a node by key slot and may retry on redirects.\n5. The command is written to the socket after connection readiness checks and offline queue handling.\n6. `redis-parser` parses the RESP reply from the socket.\n7. `DataHandler` resolves the matching queued command, applies reply transformers, and emits Pub/Sub or monitor events when relevant.\n\n## Commit Messages\n\nFollow [Conventional Commits](https://www.conventionalcommits.org/): `<type>: <subject>`.\n\nCommon types include `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, and `chore`.\n\nReleases are automated via semantic-release (`.releaserc.json`), so commit messages drive the changelog and version bump.\n"},"files":{".agents/skills/code-change-verification/SKILL.md":"---\nname: code-change-verification\ndescription: Verify ioredis code changes before handoff. Use when an agent changes or reviews runtime TypeScript, Redis command support, generated typings, tests, docs tied to behavior, build tooling, release-sensitive files, or any task that needs choosing and running the right local validation commands.\n---\n\n# Code Change Verification\n\nUse this skill to choose the smallest credible validation set for an ioredis change, run it when feasible, and report exactly what passed, failed, or was skipped.\n\n## Workflow\n\n1. Inspect the diff and changed files before choosing commands.\n   - Use `git diff --stat`, `git diff --name-only`, and targeted file reads.\n   - Do not stage, unstage, or commit unless the user explicitly asks.\n   - Treat `built/` and `lib/utils/RedisCommander.ts` as generated outputs; do not hand-edit them.\n\n2. Classify the change.\n   - Runtime code under `lib/`: run focused tests plus build when the change affects exported declarations or compiled output.\n   - Redis command typing or generated command support: inspect `bin/` config, regenerate with `node bin/index.js` if needed, and run tsd or targeted typing tests.\n   - Functional Redis behavior: run the smallest relevant Mocha files and assume a compatible Redis server is on default host/port. If sandboxed Redis access is blocked, ask for permission rather than assuming Redis is unavailable.\n   - Cluster behavior: use `npm run docker:setup` if infrastructure is needed, then targeted `test/cluster/**/*.ts` or `npm run test:cluster`.\n   - Docs-only changes: run `npm run format-check` only if formatting-sensitive files changed; otherwise inspect rendered Markdown manually.\n   - Build/tooling changes: run `npm run build` and the affected script directly.\n\n3. Prefer focused validation before broad validation.\n   - For self-contained pure unit files, run the test file alone first: `TS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/<file>.ts\"`.\n   - Include `test/helpers/*.ts` only when the unit file relies on global hooks or helper setup.\n   - Functional command change: include `test/helpers/*.ts` and the specific `test/functional/...` file.\n   - Typing change: `npm run build` then `npx tsd --files test/typing/<file>.test-d.ts` when a focused file exists.\n   - Public API or cross-cutting behavior: escalate to `npm test` after focused tests pass.\n   - Formatting-only TypeScript edits: run `npm run lint` or `npm run format-check` as appropriate.\n\n4. Handle generated artifacts deliberately.\n   - If `bin/argumentTypes.js`, `bin/returnTypes.js`, `bin/overrides.js`, `bin/sortArguments.js`, `bin/typeMaps.js`, or `bin/template.ts` changes command declarations, regenerate `lib/utils/RedisCommander.ts` with `node bin/index.js`.\n   - If generated output changes unexpectedly, inspect the generator inputs before accepting it.\n   - Build output in `built/` is publish-facing but generated by `npm run build`; mention if it is intentionally not updated.\n\n5. Report results in handoff.\n   - List each command run and its result.\n   - For failures, include the failing test name or key error line and whether it appears related.\n   - For skipped commands, state the concrete reason, such as missing Redis server, blocked sandbox access, or out-of-scope broad suite.\n\n## Command Reference\n\n- `npm run build`: remove `built/` and compile TypeScript.\n- `npm run lint`: ESLint over `lib/`.\n- `npm run format-check`: Prettier check.\n- `npm run test:js`: non-cluster Mocha suite over helpers, unit, and functional tests.\n- `npm run test:cluster`: cluster Mocha suite.\n- `npm run test:tsd`: build and run all tsd tests.\n- `npm test`: `test:js` plus `test:tsd`.\n- `npm run docker:setup` / `npm run docker:teardown`: start/stop Redis test infrastructure.\n",".agents/skills/docs-sync/SKILL.md":"---\nname: docs-sync\ndescription: Keep ioredis documentation synchronized with code behavior. Use when an agent changes public APIs, options, Redis command support, examples, generated typings, connection behavior, Cluster/Sentinel behavior, Pub/Sub, pipelines, transactions, scan streams, reconnect behavior, TypeScript usage, or release-facing behavior that may require README or docs updates.\n---\n\n# Docs Sync\n\nUse this skill to decide whether an ioredis change needs documentation, update the right docs, and keep examples aligned with tested behavior.\n\nFor broad documentation audits, option/API coverage checks, or unclear documentation scope, also read `references/doc-coverage-checklist.md` before deciding what to update.\n\n## Workflow\n\n1. Inspect the changed behavior.\n   - Read the diff and the surrounding implementation.\n   - Identify whether users must know a new capability, option, error case, event, command signature, return shape, or migration concern.\n   - Treat TypeScript declarations and public JSDoc as documentation when command signatures, constructor options, or exported types change.\n\n2. Find the documentation surface.\n   - `README.md`: primary user-facing guide, examples, feature overview, options, and common workflows.\n   - `lib/redis/RedisOptions.ts`: `RedisOptions`, `CommonRedisOptions`, option JSDoc, and `DEFAULT_REDIS_OPTIONS`.\n   - `lib/cluster/ClusterOptions.ts`: `ClusterOptions`, cluster option JSDoc, and `DEFAULT_CLUSTER_OPTIONS`.\n   - `lib/connectors/StandaloneConnector.ts` and `lib/connectors/SentinelConnector/types.ts`: connection option types that contribute to public constructor options.\n   - `docs/`: generated TypeDoc output from public source comments.\n   - `examples/`: runnable snippets that should match current API behavior.\n   - `lib/index.ts` and public TypeDoc comments: exported API documentation surface.\n   - `test/typing/`: executable documentation for TypeScript signatures.\n\n3. Update docs when the change affects users.\n   - Public option or constructor behavior: document option name, default, behavior, topology limitations, and Redis version constraints in JSDoc first; update README/examples when users need prose or usage guidance.\n   - Redis command support: update generator config in `bin/`, regenerate `lib/utils/RedisCommander.ts`, and document only if README/docs mention related command groups or if the change affects command typing, return mapping, or examples.\n   - Pub/Sub, sharded Pub/Sub, monitor, pipeline, transaction, Sentinel, Cluster, TLS, reconnect, or offline queue behavior: update the relevant README/docs section.\n   - New or changed public exports from `lib/index.ts`: update TypeDoc comments and typing tests when the exported type or class is part of the supported API.\n   - Breaking or compatibility-sensitive behavior: add explicit migration or caveat wording.\n   - Internal-only refactors with no behavioral/API impact: state that no docs update is needed and why.\n\n4. Keep examples honest.\n   - Prefer short examples that compile against the current public API.\n   - Avoid documenting behavior that is not covered by tests unless you also add or request coverage.\n   - If an example requires a Redis version, topology, or protocol mode, say so near the example.\n   - Use existing README style and terminology.\n\n5. Verify documentation changes.\n   - For TypeScript examples or declarations, run the focused tsd test or add one when appropriate.\n   - For API docs comments, run `npm run docs` when the change affects generated docs.\n   - For command typing changes, run `node bin/index.js` before validating generated typings.\n   - For Markdown-only edits, inspect nearby formatting and links; run `npm run format-check` only when relevant files are covered by Prettier.\n\n## Documentation Decision Checklist\n\n- Does the change alter public exports from `lib/index.ts`?\n- Does it add, remove, rename, or change JSDoc/defaults for `RedisOptions`, `CommonRedisOptions`, `ClusterOptions`, standalone connection options, or Sentinel connection options?\n- Does it add, remove, or change a Redis command method signature?\n- Does it change reply transformation, Buffer variants, callbacks, or Promise behavior?\n- Does it affect connection lifecycle, retries, ready checks, offline queue, or subscriber mode?\n- Does it affect Cluster routing, redirections, subscriber groups, Sentinel discovery, or TLS?\n- Does it add an option, event, error condition, or environment assumption?\n- Would a user need different code after this change?\n\nIf any answer is yes, update docs or explicitly explain why existing docs already cover it.\n",".agents/skills/docs-sync/references/doc-coverage-checklist.md":"# ioredis Doc Coverage Checklist\n\nUse this checklist to scan the selected scope and validate that user-facing ioredis behavior is documented in the right place. In diff mode, limit the scan to the selected task scope: staged changes, unstaged changes, staged plus unstaged changes, or a branch comparison such as `git diff main...HEAD` for PR-oriented audits. In comprehensive mode, inventory the public surfaces listed below.\n\n## Public API inventory\n\n- Public exports from `lib/index.ts`: default `Redis`, named `Redis`, `Cluster`, exported classes, exported types, and compatibility exports.\n- Constructor and option types:\n  - `lib/redis/RedisOptions.ts`: `RedisOptions`, `CommonRedisOptions`, `RetryStrategy`, `ReconnectOnError`, and `DEFAULT_REDIS_OPTIONS`.\n  - `lib/cluster/ClusterOptions.ts`: `ClusterOptions`, `ClusterNodeRetryStrategy`, DNS/NAT helper types, and `DEFAULT_CLUSTER_OPTIONS`.\n  - `lib/connectors/StandaloneConnector.ts`: standalone TCP/TLS connection options.\n  - `lib/connectors/SentinelConnector/types.ts`: Sentinel connection options, failover behavior, and sentinel-specific limits.\n- Generated command API:\n  - `lib/utils/RedisCommander.ts` is generated and must not be hand-edited.\n  - `bin/overrides.js`, `bin/argumentTypes.js`, `bin/returnTypes.js`, `bin/sortArguments.js`, and `bin/typeMaps.js` define command signature and return documentation inputs.\n- Core classes and behavior surfaces: `lib/Redis.ts`, `lib/cluster/index.ts`, `lib/Command.ts`, `lib/Pipeline.ts`, `lib/transaction.ts`, `lib/ScanStream.ts`, `lib/DataHandler.ts`, `lib/autoPipelining.ts`, `lib/Script.ts`, and `lib/tracing.ts`.\n- User-facing examples and executable docs: `README.md`, `examples/`, and `test/typing/`.\n\n## Option JSDoc requirements\n\n- Every public option on `CommonRedisOptions`, `RedisOptions`-contributing connection types, and `ClusterOptions` should have clear JSDoc unless the option is intentionally internal.\n- JSDoc should include:\n  - What the option changes in user-visible behavior.\n  - Default value with `@default`, matching `DEFAULT_REDIS_OPTIONS` or `DEFAULT_CLUSTER_OPTIONS`.\n  - Accepted values when the TypeScript type is broad, such as callback return contracts or string roles.\n  - Topology limits, such as standalone-only, Sentinel-only, Cluster-only, subscriber-mode, or RESP mode constraints.\n  - Redis version requirements when relevant.\n- Keep JSDoc and defaults synchronized for options such as retry strategies, timeouts, offline queue behavior, ready checks, auto pipelining, client info, authentication, Sentinel discovery, Cluster redirections, SRV lookup, NAT mapping, and sharded subscribers.\n- When an option is deprecated, renamed, or compatibility-only, document that in JSDoc and remove stale README guidance if it no longer applies.\n\n## Documentation surfaces\n\n- `README.md`: main guide, examples, feature overview, constructor options, Cluster, Sentinel, Pub/Sub, pipelines, transactions, Lua scripts, streams/scans, TLS, reconnect behavior, and TypeScript usage.\n- `docs/`: generated TypeDoc output from `npm run docs`; update generated docs only as part of an intentional docs generation change.\n- TypeDoc source comments: public JSDoc in `lib/index.ts`, `lib/redis/RedisOptions.ts`, `lib/cluster/ClusterOptions.ts`, connector option types, tracing types, and public classes.\n- `examples/`: runnable examples that should compile and use current APIs.\n- `test/typing/`: tsd coverage for public TypeScript signatures, command typings, constructor options, and exported types.\n\n## Code-first pass\n\n- Start from code, not existing docs. Identify the changed public symbol, option, command signature, return type, default, error, event, or lifecycle behavior.\n- Map the behavior to the closest existing doc surface. Prefer updating an existing README section, JSDoc block, example, or typing test over creating a new document.\n- For command typing changes, update generator config in `bin/`, regenerate `lib/utils/RedisCommander.ts`, and consider `test/typing/commands.test-d.ts`.\n- For option changes, update the interface JSDoc, default object, README option guidance if present, and tsd coverage when the type surface matters.\n- For behavior changes in Cluster, Sentinel, Pub/Sub, pipelines, transactions, scan streams, reconnect logic, ready checks, timeouts, tracing, or data handling, check both README prose and public JSDoc.\n\n## Evidence capture\n\n- Record the file path and symbol or setting name, for example `lib/redis/RedisOptions.ts:CommonRedisOptions.commandTimeout`.\n- Record the default from `DEFAULT_REDIS_OPTIONS` or `DEFAULT_CLUSTER_OPTIONS` when documenting options.\n- Record the implementation behavior that proves the docs text, such as the method, event handler, retry branch, or command transformer.\n- Avoid large code dumps. A short path plus symbol and behavior note is enough.\n\n## Red flags\n\n- README option names, defaults, or examples differ from `RedisOptions`, `ClusterOptions`, connector option types, or default objects.\n- Public options exist without JSDoc, or JSDoc omits important default/behavior constraints.\n- Generated TypeDoc pages under `docs/` are stale relative to TypeScript source comments.\n- `lib/utils/RedisCommander.ts` was manually edited instead of regenerated from `bin/` config.\n- Command return types, Buffer variants, callbacks, Promise behavior, or pipeline/transaction behavior changed without typing or docs review.\n- Removed, renamed, or deprecated features remain documented as current behavior.\n- Examples rely on unsupported Redis versions, topology assumptions, or undocumented setup.\n\n## Structural changes\n\n- Propose README restructuring only when an existing section mixes quick-start usage with deep reference detail, or when Cluster/Sentinel/Pub/Sub/TypeScript material has no sensible home.\n- Keep quick-start examples short. Move advanced retry, timeout, topology, command typing, and failure-mode details into focused sections or JSDoc.\n- Cross-link related concepts instead of duplicating long explanations, especially for options shared between standalone Redis and Cluster `redisOptions`.\n\n## Diff mode guidance\n\n- Choose the diff source that matches the task:\n  - Staged work: `git diff --cached`.\n  - Unstaged work: `git diff`.\n  - All local in-progress work: inspect both `git diff --cached` and `git diff`.\n  - PR-oriented branch audit: `git diff main...HEAD` or the equivalent branch base.\n- Focus only on changed public behavior: new exports/options, modified defaults, removed features, renamed settings, new command signatures, changed reply transformations, or changed lifecycle behavior.\n- Document removals explicitly so stale README, examples, JSDoc, TypeDoc output, and typing tests can be pruned.\n\n## Patch guidance\n\n- Keep edits scoped and aligned to the existing README/JSDoc tone.\n- Do not hand-edit `lib/utils/RedisCommander.ts`; regenerate it with `node bin/index.js` after command typing config changes.\n- Leave translated or vendored docs untouched unless the task explicitly targets them.\n- For Markdown-only updates, inspect nearby formatting. For JSDoc/API changes, run `npm run docs` when generated docs must be refreshed.\n",".agents/skills/implement-command/SKILL.md":"---\nname: implement-command\ndescription: Use when adding or updating Redis command support in ioredis, including command metadata checks, generator inputs under bin/, generated RedisCommander typings, return and argument overrides, functional command tests, optional tsd coverage, and validation.\n---\n\n# Implement Command\n\nUse this skill when adding a missing Redis command, correcting an existing command signature, changing command return types, or adding coverage for command-specific Buffer, callback, pipeline, or transformer behavior.\n\n## Command Support Map\n\n- `@ioredis/commands`: upstream command metadata consumed by the generator.\n- `bin/index.js`: generator entry point for `lib/utils/RedisCommander.ts`.\n- `bin/returnTypes.js`: command return type map. Most new commands need an entry here.\n- `bin/argumentTypes.js`: command-specific argument shape overrides when metadata or global mapping is insufficient.\n- `bin/typeMaps.js`: global Redis argument category to TypeScript type mapping.\n- `bin/overrides.js`: manual overloads for signatures the generator cannot express cleanly.\n- `bin/sortArguments.js`: argument reordering for commands whose generated order is wrong.\n- `lib/utils/RedisCommander.ts`: generated declarations. Regenerate it; do not hand-edit it.\n- `lib/Command.ts`: command argument and reply transformer registry. Touch only when transformer behavior is needed.\n- `test/functional/commands/<command>.ts`: runtime command coverage.\n- `test/functional/transformer.ts`: transformer runtime coverage.\n- `test/typing/commands.test-d.ts`: public command typing coverage.\n- `test/typing/transformers.test-d.ts`: transformer typing coverage.\n\n## Workflow\n\n1. Establish command scope.\n   - Normalize command keys to lowercase, matching `bin/returnTypes.js`.\n   - Resolve command aliases or subcommands before editing.\n   - Confirm the command exists in `@ioredis/commands`. If it is missing there, stop and report that the metadata package must be updated before ioredis can generate typed command support.\n   - Identify the minimum Redis server version needed and whether functional tests must be version-gated.\n\n2. Inspect current support.\n   - Search `lib/utils/RedisCommander.ts`, `bin/`, `test/functional/commands/`, and `test/typing/` for the command and related aliases.\n   - Inspect nearby command families before choosing types, for example hash expiration commands, sorted-set commands, stream commands, or pub/sub commands.\n   - Check existing argument and reply transformers before adding new ones.\n\n3. Update generator inputs.\n   - Prefer `bin/returnTypes.js` for return type corrections.\n   - Use a string return type for simple fixed replies.\n   - Use a function return type when replies depend on subcommands, options, or tokens.\n   - Reuse `hasToken` and `matchSubcommand` in `bin/returnTypes.js` when they fit.\n   - Use `bin/argumentTypes.js` only for command-specific argument overrides.\n   - Use `bin/typeMaps.js` only for broad metadata category fixes that should affect multiple commands.\n   - Use `bin/overrides.js` only when generated overloads cannot express the supported API cleanly.\n   - Keep command names lowercase in generator maps unless the surrounding file uses another established convention.\n\n4. Regenerate declarations.\n   - In this repo, use `node bin/index.js` unless `package.json` later adds an explicit generation script.\n   - Review the generated diff in `lib/utils/RedisCommander.ts`.\n   - Check the normal method, callback overload, pipeline/transaction shape, and Buffer variant when the command returns strings, arrays, nullable bulk replies, or transformed objects.\n   - If generation changes unrelated commands, inspect the generator input and do not accept surprising churn without an explanation.\n\n5. Add focused runtime coverage.\n   - Put command tests in `test/functional/commands/<lowercase-command>.ts`.\n   - Use `import Redis from \"../../../lib/Redis\";` and `import { expect } from \"chai\";`.\n   - Prefer `let redis: Redis`, `beforeEach(() => { redis = new Redis(); })`, and `afterEach(() => { redis.disconnect(); })`.\n   - For version-gated command tests under `test/functional/commands/`, import `isRedisVersionLowerThan` from `../../helpers/util`, and use `before(async function () { ... this.skip(); })`; use function syntax when calling `this.skip()`.\n   - Use unique keys such as `${command}_${caseName}_${Date.now()}`.\n   - Test the ioredis command surface: accepted argument shapes, option ordering, callback behavior, Buffer variants, and reply shape.\n   - Keep assertions focused on what ioredis sends and returns. Do not test Redis server internals beyond the smallest deterministic setup needed.\n   - Assert exact replies when stable; otherwise assert primitive type, nullable behavior, array/object shape, or Buffer conversion.\n\n6. Add typing coverage when useful.\n   - Add cases to `test/typing/commands.test-d.ts` when the command has nontrivial overloads, return types, Buffer variants, callback typing, or option-dependent replies.\n   - Cover `expectType<Promise<...>>(redis.command(...))`.\n   - Add Buffer variant expectations when the command has one.\n   - Add callback typing for nontrivial return types.\n   - Use `expectError` only for meaningful invalid signatures.\n   - Update `test/typing/transformers.test-d.ts` only when transformer APIs are affected.\n\n7. Consider documentation.\n   - Use the repo `docs-sync` skill when command support changes public signatures, return mapping, examples, or documented command behavior.\n   - Usually command support is documented through generated declarations and typing tests; update README/docs only when existing prose or examples cover the affected command family or users need version/topology caveats.\n\n8. Validate.\n   - Run `node bin/index.js` after generator input changes.\n   - Run the focused functional command test when Redis support is available, using the repo's Mocha pattern with `test/helpers/*.ts`.\n   - Run `npm run build` when generated declarations, public TypeScript, or generator output changed.\n   - If typing tests changed, run `npx tsd --files test/typing/commands.test-d.ts` after building.\n   - Use the repo `code-change-verification` skill before handoff to choose any additional validation.\n   - If Redis access is blocked by sandboxing, ask for permission to access the local Redis server rather than assuming it is unavailable.\n\n## Completion Report\n\nReport:\n\n- Commands added or updated.\n- Metadata/generator inputs changed.\n- Generated files changed.\n- Functional tests added or updated.\n- Typing tests added or updated.\n- Documentation decision.\n- Validation commands run and results.\n- Skipped validation with the concrete reason, including Redis version or local environment limits.\n",".agents/skills/pr-draft-summary/SKILL.md":"---\nname: pr-draft-summary\ndescription: Create the required PR-ready summary block, branch suggestion, title, and draft description for ioredis. Must be used before the final response whenever the actual task diff includes runtime code, tests, examples, build/test configuration, or docs with behavior impact, regardless of perceived change size. Skip only when no eligible files changed, every change is repo-meta or docs-only without behavior impact, the task is conversation-only, or the user explicitly opts out.\n---\n\n# PR Draft Summary\n\n## Purpose\n\nProduce a PR-ready summary after eligible work is complete: a concise change summary plus a PR-ready title and draft description for ioredis.\n\n## Close-out Gate\n\n1. Inspect the actual task diff before sending the final response.\n2. Run this skill when the diff includes runtime code, tests, examples, build/test configuration, or docs with behavior impact. Do not use perceived change size to skip an eligible change.\n3. Run it after any required verification and before sending the \"work complete\" response.\n4. Skip only when no eligible files changed, every change is repo-meta or docs-only without behavior impact, the task is conversation-only, or the user explicitly opts out.\n\n## Inputs to Collect Automatically (do not ask the user)\n\n- Current branch: `git rev-parse --abbrev-ref HEAD`.\n- Working tree: `git status -sb`.\n- Untracked files: `git ls-files --others --exclude-standard` (use with `git status -sb`; `--stat` omits them).\n- Changed files: `git diff --name-only` (unstaged) and `git diff --name-only --cached` (staged); sizes via `git diff --stat` and `git diff --stat --cached`.\n- Pull request base reference (prefer the canonical upstream branch; never use a feature branch's upstream as the PR base):\n  - `BASE_REF=upstream/main`; if it does not exist locally, use `origin/main`; if that does not exist locally, use `main`.\n  - `BASE_COMMIT=$(git merge-base \"$BASE_REF\" HEAD)`.\n- Committed branch diff: `git diff --name-only \"${BASE_COMMIT}..HEAD\"` and `git diff --stat \"${BASE_COMMIT}..HEAD\"`.\n- Commits ahead of the base fork point: `git log --oneline --no-merges ${BASE_COMMIT}..HEAD`.\n- Category signals for this repo: runtime (`lib/`, `bin/`, `examples/`, `benchmark/`), tests (`test/`), docs (`docs/`, `README.md`, `AGENTS.md`, `.agents/`, `.github/`), build/test config (`package.json`, `package-lock.json`, `tsconfig.json`, `.eslintrc*`, `.mocharc*`, `nyc.config.js`, `typedoc.json`).\n\n## Workflow\n\n1. Run the commands above without asking the user; compute `BASE_REF`/`BASE_COMMIT` first so later commands reuse them. Compare against `upstream/main`, `origin/main`, or `main`, not the current branch's upstream.\n2. Combine the committed branch diff with staged, unstaged, and untracked changes. If the combined diff is empty, reply briefly that no code changes were detected and skip emitting the PR block.\n3. Infer change type from the touched paths listed under \"Category signals\"; classify as feature, fix, refactor, or docs-with-impact, and flag backward-compatibility risk only when the diff changes released public APIs, client/command behavior, connection config, or the RESP wire handling. Judge that risk against the latest release tag, not unreleased branch-only churn.\n4. Summarize changes in 1–3 short sentences using the top five paths and stats from the committed, staged, and unstaged diffs. Explicitly call out untracked files because `--stat` does not include them. Use commit messages as supporting context, not as a substitute for inspecting the committed diff.\n5. Choose the lead verb for the description: feature → `adds`, bug fix → `fixes`, refactor/perf → `improves` or `updates`, docs-only → `updates`.\n6. Provide a specific topic branch for the contributor's work. Pull requests must not be prepared from `main` or a fork's `main`.\n   - If already off `main`, keep the current branch name and report it as the branch to use.\n   - If on `main`, propose `feat/<slug>`, `fix/<slug>`, or `docs/<slug>` based on the primary area (for example `docs/pr-draft-summary-guidance`) and show a `git checkout -b <branch>` command.\n7. If the current branch matches `issue-<number>` (digits only), keep that branch suggestion. When an issue number is present, reference `https://github.com/redis/ioredis/issues/<number>` and include an auto-closing line such as `This pull request resolves #<number>.` Do not block if the issue cannot be fetched.\n8. Draft the PR title and description using the template below. Use Conventional Commits prefixes for the title (`feat:`, `fix:`, `docs:`, `chore:`, etc.).\n9. Output only the block in \"Output Format\". Keep any surrounding status note minimal and in English. Do not include company-internal references (e.g. Jira/Confluence IDs) in the branch name, title, or description.\n\n## Output Format\n\nWhen closing out a task, add this concise Markdown block (English only) after any brief status note unless the task falls under the documented skip cases or the user says they do not want it.\n\n```\n# Pull Request Draft\n\n## Branch name suggestion\n\n<Either `Current branch: <existing-topic-branch>` when already off `main`, or `git checkout -b <new-topic-branch>` when currently on `main`. Never suggest using `main` as the pull request branch.>\n\n## Title\n\n<single-line imperative title, which can be a commit message; a Conventional Commits prefix such as feat:, fix:, or docs: is preferred>\n\n## Description\n\n<include what you changed plus a draft pull request title and description for your local changes; start the description with prose such as \"This pull request resolves/updates/adds ...\" using a verb that matches the change (you can use bullets later), explain the change background (for bugs, clearly describe the bug, symptoms, or repro; for features, what is needed and why), any behavior changes or considerations to be aware of, and you do not need to mention any tests you ran.>\n```\n\nKeep it tight—no redundant prose around the block, and avoid repeating details between `Changes` and the description. Tests do not need to be listed unless specifically requested.\n",".agents/skills/runtime-behavior-probe/SKILL.md":"---\nname: runtime-behavior-probe\ndescription: Plan and execute runtime-behavior investigations with temporary TypeScript probe scripts, validation matrices, state controls, and findings-first reports. Use only when the user explicitly invokes this skill to verify actual runtime behavior beyond normal code-level checks, especially to uncover edge cases, undocumented behavior, or common failure modes in local or live integrations. A baseline smoke check is fine as an entry point, but do not stop at happy-path confirmation.\n---\n\n# Runtime Behavior Probe\n\n## Overview\n\nUse this skill to investigate real runtime behavior, not to restate code or documentation. Start by planning the investigation, then execute a case matrix, record observed behavior, and report both the findings and the method used to obtain them.\n\n## Core Rules\n\n- Treat this skill as manual-only. Do not rely on implicit invocation.\n- For `ioredis`, treat this skill as a disposable-probe workflow, not a repository implementation workflow.\n- Unless the user explicitly asks for a reusable repository artifact, the allowed write scope is limited to:\n  - a temporary directory used for probe scripts or artifacts\n  - `.agents/skills/runtime-behavior-probe/**` when the user is editing this skill itself\n- For disposable probes in `ioredis`, do not modify `examples/**`, `lib/**`, `test/**`, any `package.json`, `README.md`, build config, or generated files unless the user explicitly asks for a reusable repository artifact or implementation change.\n- If your draft plan would touch a disallowed path, stop and rewrite the plan before editing anything.\n- A baseline success or smoke case is often the right entry point, but do not stop there when the real question involves edge cases, drift, or failure behavior.\n- Plan before running anything. Write the case matrix first, then fill it in with observed results. The matrix can live in a scratch note, a temporary file, or the probe script header.\n- Default to local or read-only probes. Consider a live service only when it is clearly relevant, then apply the lightweight gates below before you run it.\n- Size the probe to the decision. Start with the smallest matrix that can disqualify or validate the current hypothesis, then expand only when uncertainty remains.\n- Before a live probe, apply three lightweight gates:\n  - Destination gate. Use only a live destination that is clearly allowed for the task.\n  - Intent gate. Run the live probe only when the user explicitly wants runtime verification on that integration, or explicitly approves it after you propose the probe.\n  - Data gate. If the probe will read environment variables, mutate remote state, incur material cost, or exercise non-public or user data, name the exact variable names or data class and get explicit approval first.\n- Classify each case as read-only, mutating, or costly before execution. For mutating or costly cases, or for any live case that will read environment variables, define cleanup or rollback before running the probe.\n- Use temporary files or a temporary directory for one-off probe scripts.\n- In `ioredis`, use disposable probe files outside git-tracked paths by default. Do not add one-off probes, harnesses, benchmarks, or examples under `examples/`, `lib/`, `test/`, or other repository directories unless the user explicitly asks for a checked-in artifact.\n- Keep temporary artifacts until the final response is drafted. Then delete them by default unless the user asked to keep them or they are needed for follow-up. Even when artifacts are deleted, keep a short run summary of the command shape, runtime context, and artifact status in the report.\n- Before executing a live probe that will read environment variables, tell the user the exact variable names you plan to use and why, then wait for explicit approval. Examples include `REDIS_URL`, `REDIS_PASSWORD`, and other expected default names for the system under test.\n- Never print secrets, even when they come from standard environment variables that this skill may use.\n- For Redis command or server semantics, treat the repository source as the truth and use [redis.io/commands](https://redis.io/commands) to confirm contract-sensitive details such as argument order, reply types, and version availability. Use runtime probing to validate or challenge the documented behavior, not to skip the documentation pass entirely. If you rely on the website rather than source, say so in the report.\n- For benchmark or comparison probes, make parity explicit before execution. Record what is held constant, what variable is under test, which reply-shape constraints keep the comparison fair, and any counters or timings that matter for interpreting latency or cost.\n- In `ioredis`, default to a light local loop for probe authoring: temporary `probe.ts` plus temporary `tsconfig.json`, `npx tsc --noEmit -p <tmp-tsconfig>`, then `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register <tmp-probe>`. Escalate to `npm run build` only when the runtime question is specifically about `built/`, emitted declarations, or packaged output.\n- In `ioredis`, do not treat a request for runtime verification, benchmarking, or comparison as permission to add a reusable example, benchmark harness, package script, or checked-in sample. Those repository changes require explicit user intent.\n- For probes that need a running Redis, remove setup ambiguity before attributing a negative result to client behavior:\n  - Confirm the server is reachable and note its mode (standalone, cluster, or sentinel) and RESP version before interpreting reply shapes.\n  - Treat RESP2 and RESP3 as separate cases, not interchangeable setup details, when the question is about reply shapes or push messages.\n  - Clear unsupported server-version or command options first so they do not invalidate the probe. Assume a Redis server with the correct version is running on the default host and port unless the task says otherwise; if sandbox access is blocked, ask for permission to access Redis instead of treating Redis as unavailable.\n\n## Workflow\n\n1. Restate the investigation target in operational terms. Name the runtime surface, the key uncertainty, and the highest-risk behaviors to test.\n2. For `ioredis`, declare the allowed write scope before you do any implementation work. For a normal disposable probe, that means a temporary directory only.\n3. Do a short preflight. Check the relevant code or docs first, decide whether the question needs local or live validation, and note any repo, baseline, or release boundary that matters.\n4. Create a validation matrix before executing probes. Cover both baseline behavior and the most relevant failure or drift cases. The matrix can live in a scratch note, a temporary file, or a structured header inside the probe script.\n5. For each case, choose an execution mode up front:\n   - `single-shot` for deterministic one-run checks.\n   - `repeat-N` for cache, retry, streaming, interruption, rate-limit, concurrency, or other run-to-run-sensitive behavior.\n   - `warm-up + repeat-N` when first-run cold-start effects could distort the result. Use these defaults unless the task clearly needs something else:\n   - Quick screen of a repeat-sensitive question: `repeat-3`.\n   - Decision-grade latency or release recommendation: `warm-up + repeat-10`.\n   - Costly live cases: start at `repeat-3`, then expand only if the answer remains unclear. If it is genuinely unclear whether extra runs are worth the time or cost, ask the user before expanding the probe.\n6. When the question is benchmark-like or comparative, run in phases. Start with a high-signal pilot matrix against a control, then expand only the surviving candidates or unresolved cases.\n7. If the question is about a suspected regression or behavior change, add at least one known-good control case such as `origin/master`, the latest release, or the same request without the suspected option.\n8. For comparative probes, define parity before execution. Record prompt or input shape, tool-choice setup, model-settings parity, state reuse rules, and any response-shape constraint that keeps the comparison fair. If materially different output length could bias the result, record usage or token notes too.\n9. If the question asks whether one option has the same intelligence or quality as another, decide whether the matrix supports only example-pattern parity or a broader quality claim. For broader claims, add at least one harder or more open-ended case. Otherwise say explicitly that the result is limited to the covered patterns.\n10. Plan state controls before execution when hidden state could affect the result. Record whether each case uses fresh or reused state, how cache reuse or cache busting is handled, what unique IDs isolate repeated runs, and how cleanup is verified.\n11. If any live case will read environment variables, list the exact variable names and purpose for each case, then ask the user for approval before execution. Keep the approval ask short and include destination, read-only versus mutating or costly risk, exact variable names, and cleanup or rollback if relevant.\n12. Build task-specific probe scripts in a temporary location. Keep the script small, observable, and easy to discard.\n13. If you are about to propose a checked-in script, example, benchmark, or package script for `ioredis`, stop and verify that the user explicitly asked for a reusable repository artifact. If not, keep the probe temporary.\n14. In `ioredis`, make the runtime context explicit:\n\n- Run TypeScript probes from the repository root with `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register <tmp-probe>` when practical.\n- For probe authoring, create both `probe.ts` and a sibling temporary `tsconfig.json` under `mktemp -d`, then run `npx tsc --noEmit -p <tmp-tsconfig>` before the first live execution.\n- Record the current commit, working directory, Node executable, Node version, and the package or source path you imported.\n- Avoid accidental imports from a different checkout or from `/tmp/node_modules`. If the probe needs repository code, import it from an absolute path resolved from `process.cwd()` and a repo-relative path.\n- Prefer current-branch `lib/` imports when the question is \"what does this branch do now?\" and prefer `built/` imports only when the question is specifically about packaged output after a build.\n- Do not run a repository-wide build just to typecheck a disposable probe. Reserve `npm run build` for `built/` probes or when emitted output is itself part of the question.\n\n15. Execute the matrix and capture evidence. Record request shape, setup, observation summary, unexpected or negative result, error details, timing, runtime context, approved environment-variable names, repeat counts, warm-up handling, variance when relevant, cleanup behavior, and for comparisons note what was held constant plus any response-shape or usage notes that affect interpretation.\n16. Update the matrix with actual outcomes, not guesses.\n17. Keep temporary artifacts until the final response is drafted. Then delete them unless the user asked to keep them or they are needed for follow-up. Benchmark and repeat-heavy probes often need follow-up, so keeping artifacts is normal when the result may be revisited. If deleted, retain and report a short run summary.\n18. Report findings first, with unexpected or negative findings first. Then summarize how the validation was performed and which cases were covered.\n19. If the probe isolates one clear defect, you may include a short implementation hypothesis or minimal repro direction. Do not expand into a larger next-step plan unless the user asked for it.\n\n## Validation Matrix\n\nUse a matrix that makes the news easy to scan. Start from the runtime question and the observation summary, not just from `expected` and `pass` or `fail`.\n\nUse a matrix with at least these columns:\n\n- `case_id`\n- `scenario`\n- `mode`\n- `question`\n- `setup`\n- `observation_summary`\n- `result_flag`\n- `evidence`\n\nAdd these columns when they materially improve the investigation:\n\n- `comparison_basis`\n- `variable_under_test`\n- `held_constant`\n- `output_constraint`\n- `status`\n- `confidence`\n- `state_setup`\n- `repeats`\n- `warm_up`\n- `variance`\n- `usage_note`\n- `risk_profile`\n- `env_vars`\n- `approval`\n- `control`\n\nTreat `result_flag` as a fast scan field such as `unexpected`, `negative`, `expected`, or `blocked`. Use `status` only when there is a credible comparison basis, baseline, or documented contract to compare against.\n\nAlways consider whether the matrix should include these categories:\n\n- Baseline success.\n- Control or baseline comparison when a regression is suspected.\n- Boundary input or parameter variation.\n- Invalid or unsupported input.\n- Missing or incorrect configuration.\n- Transient external failure such as timeout, network interruption, or rate limiting.\n- Retry, idempotence, or cleanup behavior.\n- Concurrency or overlapping operations when shared state or ordering may matter.\n- Open-ended quality or intelligence samples when the question is broader than pattern parity.\n\nOpen [validation-matrix.md](./references/validation-matrix.md) when you need a stronger prioritization model or a reusable case template.\n\n## Temporary Probe Scripts\n\nWrite one-off scripts in a temporary file or temporary directory such as one created by `mktemp -d`. Keep the script outside the repository by default, even when it imports code from the repository.\n\nFor `ioredis`, a disposable runtime probe should stay disposable. Do not add a package script, modify build config, or create a checked-in benchmark or example unless the user explicitly asks for a reusable repository artifact.\n\nFor `ioredis`, the default authoring loop should be:\n\n1. `tmpdir=$(mktemp -d)`\n2. Write `probe.ts` and `tsconfig.json` into `$tmpdir`\n3. From the repository root, run `npx tsc --noEmit -p \"$tmpdir/tsconfig.json\"`\n4. If the quick typecheck passes, run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register \"$tmpdir/probe.ts\"`\n5. Only run `npm run build` if the probe intentionally imports `built/` or validates packaged output\n\nUse a temporary `tsconfig.json` that extends the repository base settings but includes only the disposable probe, for example:\n\n```json\n{\n  \"extends\": \"/absolute/path/to/ioredis/tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"types\": [\"node\"],\n    \"typeRoots\": [\"/absolute/path/to/ioredis/node_modules/@types\"]\n  },\n  \"include\": [\"./probe.ts\"]\n}\n```\n\nIf the probe needs repository code:\n\n- Run it with the repository root as the working directory.\n- Use `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/probe.ts` from the repository root when practical.\n- Use `npx tsc --noEmit -p /tmp/probe-tsconfig.json` as the default quick typecheck step before executing the probe.\n- Import repository modules with an absolute path built from `process.cwd()` and a repo-relative path. Do not assume bare imports such as `ioredis` will resolve to the current checkout from `/tmp`.\n- Use `lib/` imports for current-branch behavior probes and `built/` imports for packaged-output probes.\n\nDesign the probe to maximize observability:\n\n- Print or log the exact scenario being exercised.\n- Capture runtime context such as git SHA, working directory, Node executable and version, relevant package versions, model or deployment name, endpoint or base URL alias, and any retry or tool options that materially affect behavior.\n- For live probes, record only the names of environment variables that were approved for use. Never print their values.\n- Capture structured outputs when possible.\n- Preserve raw error type, message, and status code.\n- For repeat-sensitive cases, capture the attempt index, warm-up status, and any stable identifiers that help compare runs.\n- For repeated or benchmark-style probes, write both raw results and a compact summary artifact when practical.\n- Keep branching minimal so each script answers a narrow question.\n\nBefore deleting the temporary script or directory, keep a short run summary of the script path, command used, runtime context, and whether the evidence was kept or deleted.\n\nOpen [typescript_probe.ts](./templates/typescript_probe.ts) when you want a lightweight disposable TypeScript probe scaffold. Open [repo-import-patterns.md](./references/repo-import-patterns.md) when you need to load current-branch workspace code from a temporary script.\n\n## Reporting\n\nReport in this order:\n\n1. Findings. Put unexpected or negative findings first. If there was no real news, say that explicitly.\n2. Validation approach. Summarize the code used, the runtime surface exercised, the execution modes, and the case matrix coverage.\n3. Case results. Include the matrix or a condensed version of it when the case count is large.\n4. Artifact status and brief run summary. State whether temporary artifacts were deleted or kept, and provide kept paths or the retained summary.\n5. Optional implementation note. Include this only when one clear defect was isolated and a short implementation direction would help.\n\nFor comparative probes, the report should also say what was held constant, what variable was under test, and whether the result supports only pattern parity or a broader quality claim.\n\nOpen [reporting-format.md](./references/reporting-format.md) for the recommended response template.\n\n## Resources\n\n- Open [validation-matrix.md](./references/validation-matrix.md) to design and prioritize the case matrix.\n- Open [error-cases.md](./references/error-cases.md) to expand common failure scenarios.\n- Open [redis-runtime-patterns.md](./references/redis-runtime-patterns.md) for recurring ioredis runtime probe patterns.\n- Open [repo-import-patterns.md](./references/repo-import-patterns.md) for repository-relative TypeScript import guidance.\n- Open [reporting-format.md](./references/reporting-format.md) for the final report structure.\n- Open [typescript_probe.ts](./templates/typescript_probe.ts) for a minimal disposable TypeScript probe scaffold.\n",".agents/skills/runtime-behavior-probe/references/error-cases.md":"# Common Error Cases\n\nUse this reference to expand beyond the happy path. Favor error cases that a real user or operator is likely to hit.\n\n## Configuration Errors\n\nCheck whether the runtime behaves differently for:\n\n- Missing required environment variables.\n- Present but malformed secrets or identifiers.\n- Wrong endpoint or base URL.\n- Wrong model or deployment name.\n- Incompatible local dependency versions.\n\nLook for:\n\n- Error type and status code.\n- Whether the failure is immediate or delayed.\n- Whether the message is actionable.\n- Whether retrying without fixing configuration changes anything.\n\n## Input Errors\n\nProbe common bad-input patterns such as:\n\n- Missing required fields.\n- Wrong data type.\n- Unsupported enum or option value.\n- Empty but syntactically valid input.\n- Oversized input or too many items.\n- Mutually incompatible options.\n\nPrefer realistic invalid inputs over artificial nonsense. The point is to learn how the runtime fails in practice.\n\n## Transport and Availability Errors\n\nWhen networked services are involved, consider:\n\n- Connection failure.\n- Read timeout.\n- Server timeout or upstream gateway error.\n- Rate limit response.\n- Partial stream interruption.\n- Reusing a connection after a failure.\n\nCapture whether the client library retries automatically, whether it surfaces retry metadata, and whether the final exception preserves the original cause.\n\n## State and Repetition Errors\n\nMany surprising bugs appear only when an operation is repeated or interrupted:\n\n- Re-submit the same request.\n- Repeat after a timeout.\n- Retry after a partial tool call or partial stream.\n- Resume after local cleanup or process restart.\n- Repeat with slightly changed inputs while reusing shared state.\n\nObserve whether the operation is idempotent, duplicated, silently ignored, or left in a partial state.\n\n## Concurrency Errors\n\nWhen shared state, ordering, or isolation may matter, consider:\n\n- Two overlapping requests with the same logical input.\n- Parallel runs that reuse the same cache key, session, container, or temporary resource.\n- Concurrent retries, cancellation, or cleanup racing with active work.\n- Output or event streams from one run leaking into another.\n\nCapture whether the runtime serializes, rejects, duplicates, corrupts, or cross-contaminates the work.\n\n## Investigation Heuristics\n\nUse these heuristics to pick error cases quickly:\n\n- Ask which failure a real engineer would debug first in production.\n- Ask which failure is most expensive if it is misunderstood.\n- Ask which failure would be invisible from code review alone.\n- Ask which failure path is likely to differ across environments.\n\nIf the error behavior is already perfectly obvious from a local validator or type system, it is usually low priority for this skill.\n",".agents/skills/runtime-behavior-probe/references/redis-runtime-patterns.md":"# Redis Runtime Patterns\n\nUse this reference for recurring ioredis investigations so you do not have to rediscover the probe strategy each time. Treat the repository source as the truth for client behavior, and use [redis.io/commands](https://redis.io/commands) to confirm contract-sensitive details such as argument order, reply types, and version availability. If you rely on the website rather than source, say so in the report.\n\n## General Rules\n\n- Prefer small, focused probes over large harnesses. Keep one script focused on one uncertainty.\n- For comparative or benchmark-like questions, start with a pilot and expand only when the answer is still unclear.\n- Capture the request shape (command and arguments as sent) and the observed command result or emitted event payload.\n- Preserve raw error type, message, and any Redis error prefix such as `WRONGTYPE`, `MOVED`, `ASK`, `CROSSSLOT`, `NOSCRIPT`, or `LOADING`.\n- Record whether behavior differs between the first call and a repeated call, and across a reconnect.\n- When the question is about regression or contract drift, add a known-good control run before attributing the result to the change under investigation.\n- Keep comparison parity explicit. Record what was held constant, what variable changed, and whether reply-shape or encoding differences could bias the conclusion.\n- Record the runtime context that actually changes Redis client behavior: server mode (standalone, cluster, sentinel), RESP version (2 vs 3), server version, and whether a feature such as auto-pipelining or sharded pub/sub is in use.\n\n## Connection Environment Variables\n\nDo not read these variables automatically. Before a live probe uses any of them, tell the user the exact variable names you plan to read and why each one is needed, then wait for explicit approval. Never print their values:\n\n- `REDIS_URL`\n- `REDIS_PASSWORD`\n- `REDIS_TLS_CA`, `REDIS_TLS_CERT`, `REDIS_TLS_KEY` (and any other `REDIS_TLS_*` the probe needs)\n\nFor most local probes you do not need any of these. ioredis repository instructions assume a Redis server with the correct version is running on the default host and port. Prefer that local Redis server over a live remote service unless the question is specifically about the remote deployment.\n\nIf the task targets another integration, use that integration's expected default variable names under the same rule.\n\n## Environment False Signals\n\nBefore attributing a failure to the patch or client code under review, exclude source-selection and environment problems with a controlled comparison.\n\n- Confirm the commit, worktree, working directory, Node executable/version, and imported module path. A probe of stale `built`, another checkout, `/tmp/node_modules`, or an installed `ioredis` package does not prove current `lib` behavior.\n- Rebuild when emitted declarations, package exports, generated command typings, or `built` is the subject. Otherwise prefer current-source `lib/` imports so stale build output cannot create a false result.\n- Confirm a Redis server is actually running and reachable. A connection refused or timeout against a missing Docker/Redis container is an environment condition, not a client defect, until a controlled rerun against a known-good server ties it to the code.\n- Confirm the RESP version the client negotiated. A reply-shape surprise is often just RESP2 vs RESP3, not a bug.\n- Confirm server mode matches the probe assumptions. Running a cluster-only expectation against a standalone server, or the reverse, produces misleading routing and slot errors.\n- Run base and head controls with the same Node version, dependency graph, server mode, RESP version, environment-variable names, and command shape. Record intentional differences.\n- Treat sandbox denials, unavailable Docker infrastructure, expired remote sessions, authentication, quota, rate limits, service outages, and stale caches as environment conditions until a controlled rerun ties them to the patch.\n- Never print credentials, connection URLs with embedded passwords, or TLS key material. Change only the minimum in-scope environment or disposable state needed for the control and record variable names rather than values.\n\nIn the final report, distinguish code failures, unsupported configurations, environment blockers, and inconclusive probes. Do not collapse them into one failed-test count.\n\n## ioredis Probe Patterns\n\nStart from the uncertainty instead of from the full client surface. The patterns below cover the runtime questions that recur most often in ioredis.\n\n### RESP2 vs RESP3 reply shapes\n\nUse when the uncertainty is what a command returns at runtime.\n\n- Run the same command under RESP2 and RESP3 as separate cases when protocol differences are part of the uncertainty.\n- Capture the observed command result and whether the client returns plain objects, `Map`, arrays, `null`, buffers, strings, or numbers.\n- Watch precision-sensitive numeric replies and record the exact value.\n\n### Single-node vs cluster vs sentinel\n\nUse when key routing, slot ownership, or topology matters.\n\n- For cluster, capture which node served the command and whether a `MOVED` or `ASK` redirect occurred. Probe multi-key commands across keys in different slots to observe `CROSSSLOT` behavior and any client-side slot checks.\n- Use hash tags (`{tag}`) to force keys into the same slot when the probe needs a multi-key command to succeed.\n- For sentinel, capture master discovery and what happens on a simulated failover.\n- Keep mode constant within a case. A standalone control alongside a cluster case is a useful comparison, not a substitute.\n\n### Pub/sub and sharded pub/sub\n\nUse when delivery semantics or resubscription matter.\n\n- Capture subscribe confirmation, message delivery order, emitted event names, and whether messages are delivered to pattern (`PSUBSCRIBE`) and channel subscribers as expected.\n- For sharded pub/sub (`SSUBSCRIBE` and `SPUBLISH`) in cluster, capture which shard delivered the message.\n- Force a reconnect and observe whether the client resubscribes to channels and patterns automatically. This is a common drift point.\n\n### Reconnection, retry, and the offline command queue\n\nUse when the question is about resilience.\n\n- Simulate a dropped connection (stop or restart the container, or close the socket) and capture: whether commands issued while offline are queued, the order they flush in on reconnect, and whether the reconnect strategy backoff behaves as configured.\n- Distinguish commands rejected immediately from commands queued and later resolved or rejected.\n- Capture whether in-flight commands at disconnect are retried, rejected, or hang.\n\n### Pipelining and MULTI/EXEC transactions\n\nUse when batching or atomicity is under test.\n\n- For pipelining, confirm replies map back to the right commands in order, including when one command in the batch errors.\n- For `MULTI`/`EXEC`, capture queueing errors versus execution errors, behavior on `DISCARD`, and `WATCH` optimistic-locking aborts (`EXEC` returning `null`).\n\n### RESP3 push messages and subscribed connection behavior\n\nUse when push-message routing or subscribed connection behavior matters.\n\n- Requires RESP3 when the question depends on push-message behavior. Capture whether push replies are routed to events, whether regular commands are allowed while subscribed, and whether replies preserve expected buffer/string variants.\n- Probe RESP2 and RESP3 separately when subscribed-mode command behavior or push reply shape is part of the uncertainty.\n\n### Blocking commands and connection isolation\n\nUse for `BLPOP`, `BRPOP`, `XREAD BLOCK`, `WAIT`, and similar.\n\n- Capture whether the blocking command monopolizes a connection and whether the caller needs a separate Redis instance so other commands are not stalled.\n- Probe timeout behavior and what resolves when the block is satisfied by another client versus when it times out.\n\n### Auto-pipelining and command queues\n\nUse when same-tick batching, offline queue behavior, or command queue ordering is involved.\n\n- Capture which commands are batched, whether disabled commands bypass auto-pipelining, and whether reply order matches command order.\n- For reconnect-sensitive questions, distinguish offline queue entries, in-flight commands, and commands rejected because the connection state does not allow queuing.\n\n### SCAN iterators\n\nUse for `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`.\n\n- Capture cursor progression, whether the async iterator terminates, and whether `COUNT` and `MATCH` behave as expected. Note that SCAN gives no count or completeness guarantees mid-iteration.\n\n### Large payloads and timeouts\n\nUse when size or latency is the concern.\n\n- Capture behavior with large values and large reply sets, and whether command-level or socket timeouts fire as configured.\n- For repeat-sensitive latency, use warm-up plus repeat-N and record medians, not a single sample.\n\n## What to Capture\n\nFor ioredis probes, try to record:\n\n- The command and arguments as sent, plus the observed result or emitted event payload.\n- The JavaScript value and its type, including buffer variants when relevant.\n- Server mode (standalone, cluster, or sentinel), negotiated RESP version, and server version.\n- Whether fields are absent, `null`, empty, or transformed by the client.\n- Raw error type, message, and any Redis error prefix for failures.\n- Reconnect and retry behavior, offline-queue flush order, and resubscription on reconnect when relevant.\n- For cluster, which node served the command and any redirect.\n- Which environment-variable names were approved for the probe when a live or credentialed server was required.\n\nDo not spend time rediscovering static documentation unless the runtime result seems to contradict what you expected. The value of this skill is in the observed behavior.\n",".agents/skills/runtime-behavior-probe/references/repo-import-patterns.md":"# Repository Import Patterns\n\nUse this reference when a temporary probe script outside the repository needs to load code from the current branch.\n\n## Why This Exists\n\nWhen you run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/probe.ts` from the repository root, `ts-node` itself comes from this repository, but the probe file still lives under `/tmp`. Bare imports such as `ioredis` can resolve as if the script were its own package. That is often not what you want for \"what does the current branch do right now?\" investigations.\n\nThe safe default is to build an absolute path from `process.cwd()`, which should be the repository root, and a repository-relative path.\n\n## Default Rule\n\n- Use `lib/` imports when the question is about current-branch behavior.\n- Use `built/` imports when the question is about packaged output after a build.\n- Avoid bare package imports from `/tmp` unless the probe is explicitly testing published package resolution rather than branch-local source behavior.\n\n## Quick Typecheck Loop\n\nFor disposable probes in `ioredis`, the default loop should stay outside the repository and avoid a full package build:\n\n1. Create a temporary directory with `mktemp -d`.\n2. Write `probe.ts` there.\n3. Write a sibling `tsconfig.json` that extends the repository's `tsconfig.json`.\n4. From the repository root, run `npx tsc --noEmit -p /tmp/.../tsconfig.json`.\n5. If that passes, run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/.../probe.ts`.\n\nExample temporary `tsconfig.json`:\n\n```json\n{\n  \"extends\": \"/absolute/path/to/ioredis/tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"types\": [\"node\"],\n    \"typeRoots\": [\"/absolute/path/to/ioredis/node_modules/@types\"]\n  },\n  \"include\": [\"./probe.ts\"]\n}\n```\n\nThis keeps TypeScript module resolution and strictness close to the repository defaults while limiting the check surface to the disposable probe file.\n\nDo not convert this default loop into a checked-in benchmark, example, or package script unless the user explicitly asks for a reusable repository artifact.\n\n## Recommended Helper\n\nThe disposable TypeScript scaffold exposes:\n\n    const module = await importRepoModule(\"lib/index.ts\");\n\nInternally, the helper should be equivalent to:\n\n    import { createRequire } from \"module\";\n    import { resolve } from \"path\";\n\n    const repoRequire = createRequire(resolve(process.cwd(), \"package.json\"));\n\n    async function importRepoModule(repoRelativePath: string) {\n      const absolutePath = resolve(process.cwd(), repoRelativePath);\n      return Promise.resolve(repoRequire(absolutePath));\n    }\n\nThis keeps the import anchored to the current checkout instead of the temporary script location.\n\n## Choosing `lib/` Versus `built/`\n\nUse `lib/` when:\n\n- You are validating a bug fix or regression on the current branch.\n- You want to know how the repository behaves before packaging.\n- The question is about implementation details or internal helper behavior.\n\nUse `built/` when:\n\n- The question is specifically about what consumers load after `npm run build`.\n- You need to validate export maps or emitted `.js` and `.d.ts` output.\n- The bug only reproduces in generated output.\n\nIf the probe uses `built/`, record whether you ran a fresh build first. A stale `built/` directory can create false positives or false negatives.\n\nDo not run `npm run build` only to typecheck or execute a `lib/`-based disposable probe. The fast path is temp `tsconfig` plus `npx tsc --noEmit`, then `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register`.\n\n## Simple Smoke Targets\n\nWhen you only need to prove the helper works, start with a simple target that has minimal side effects, for example:\n\n- `lib/index.ts`\n- `lib/Redis.ts`\n- `lib/Command.ts`\n- another file with obvious exported symbols and no environment requirement\n\nIf a chosen file pulls in more of the repo than expected, switch to a simpler target rather than weakening the import guidance.\n\n## What To Record\n\nWhen a probe imports repo code, report:\n\n- The repo-relative path you imported.\n- Whether it came from `lib/` or `built/`.\n- The repository root used by `process.cwd()`.\n- Any prerequisite step such as `npm run build`.\n",".agents/skills/runtime-behavior-probe/references/reporting-format.md":"# Reporting Format\n\nLead with findings, not process. The user asked for investigation results, so the answer should start with the most important observed behaviors. Put the real news first.\n\n## Recommended Order\n\n1. Findings.\n2. Validation approach.\n3. Case matrix or condensed case summary.\n4. Artifact status and brief run summary.\n5. Optional implementation note.\n\n## Findings Section\n\nMake each finding answer one user-relevant question. Good findings usually include:\n\n- What was observed.\n- Why it matters.\n- The condition under which it happens.\n- What was held constant when the finding comes from a comparison probe.\n- `scope`: The boundary of the finding, such as commit, model, Node version, live versus local, or repeat mode.\n- `confidence`: `high`, `medium`, or `low`.\n\nAvoid burying the main result under setup details.\n\nPut `unexpected` or `negative` findings first. If there were no unexpected or negative findings in the executed cases, say that explicitly before the rest of the findings section.\n\nIf the probe was comparative, say whether the result supports:\n\n- Pattern parity only.\n- A broader quality claim.\n\nDo not imply a broader quality equivalence than the executed cases justify.\n\n## Validation Approach Section\n\nSummarize:\n\n- The runtime surface you exercised.\n- The shape of the probe code, in overview only.\n- Which categories of cases you covered.\n- Which execution modes you used, including repeat counts or warm-up handling when relevant.\n- Whether live credentials or external services were used.\n- Any important state controls such as fresh state, cache reuse, cache busting, unique IDs, or cleanup verification.\n- For comparison probes, what was held constant, what was varied, and whether output-shape or usage differences could still influence the conclusion.\n- Whether the usual docs path or an official-docs fallback was used for contract-sensitive checks.\n\nKeep this concise. The user needs enough detail to trust the result, not a line-by-line replay of the script.\n\n## Case Summary\n\nInclude either the full matrix or a condensed summary. At minimum, show:\n\n- Which scenarios were executed.\n- Whether the run was a quick pilot, an expanded matrix, or both.\n- Which ones produced `unexpected` or `negative` results.\n- Which ones passed or failed when a real comparison basis existed.\n- Which cases were blocked.\n- Where the supporting evidence lived, or that it was deleted.\n\nIf the matrix is large, show the highest-value cases in the main response and keep the rest as a compact appendix or note.\n\n## Artifact Status And Brief Run Summary\n\nState one of these explicitly:\n\n- Temporary artifacts were kept until the final response was drafted, then deleted after validation.\n- Temporary artifacts were kept at `<path>` because the user asked to keep them.\n- Temporary artifacts were kept at `<path>` because they are needed for follow-up analysis.\n\nEven if artifacts were deleted, retain a short run summary such as:\n\n- Probe command or runner shape.\n- Runtime context summary such as commit, Node executable, Node version, or model.\n- Artifact path and final status.\n\nFor benchmark or repeat-heavy probes, keeping artifacts for follow-up is often the right default even when the immediate report is done.\n\n## Optional Implementation Note\n\nInclude this only when one clear defect was isolated and a short implementation hypothesis or minimal repro direction would help. Keep it brief. Do not turn the report into a broader next-step plan unless the user asked for that.\n\n## Compact Template\n\nUse this outline when you need a fast structure:\n\n    Findings:\n    - <finding 1>\n      held constant: <prompt/tool/state settings kept the same, if comparative>\n      scope: <commit/model/node/live-local/repeat-mode>\n      confidence: <high|medium|low>\n    - <finding 2>\n      held constant: <prompt/tool/state settings kept the same, if comparative>\n      scope: <commit/model/node/live-local/repeat-mode>\n      confidence: <high|medium|low>\n\n    Validation approach:\n    - Surface: <what was exercised>\n    - Probe code: <brief overview>\n    - Coverage: <success, edge, error, repeat-sensitive, and quality categories>\n    - Execution modes: <single-shot|repeat-N|warm-up + repeat-N>\n    - Comparison parity: <what was held constant and what varied, if comparative>\n    - Docs source: <MCP or official-docs fallback, if relevant>\n\n    Case summary:\n    | case_id | scenario | result_flag | status | note |\n    | --- | --- | --- | --- | --- |\n    | S1 | ... | expected | pass | ... |\n    | E1 | ... | negative | fail | ... |\n\n    Artifact status and brief run summary:\n    - Temporary artifacts were kept until the final response was drafted, then deleted.\n    - Summary: <command/runtime-context/artifact-status summary>\n\n    Optional implementation note:\n    - <brief hypothesis or minimal repro direction>\n\nAdjust the format to the task, but preserve the ordering.\n",".agents/skills/runtime-behavior-probe/references/validation-matrix.md":"# Validation Matrix\n\nUse the matrix to decide what to probe before writing scripts. The goal is not exhaustive combinatorics; the goal is high-value coverage that is visible, explainable, and likely to reveal runtime surprises. The matrix should make the real news easy to scan.\n\n## Minimum Columns\n\nUse these columns unless the task clearly needs more:\n\n- `case_id`: Stable identifier such as `S1`, `E3`, or `R2`.\n- `scenario`: Short description of the behavior under test.\n- `mode`: `single-shot`, `repeat-N`, or `warm-up + repeat-N`.\n- `question`: The concrete runtime uncertainty this case is answering.\n- `setup`: Inputs, environment, or preconditions required for the case.\n- `observation_summary`: A compact summary of what actually happened.\n- `result_flag`: `unexpected`, `negative`, `expected`, or `blocked`.\n- `evidence`: Path, log reference, or `deleted`.\n\nAdd these columns when they materially improve the investigation:\n\n- `comparison_basis`: The baseline, docs, or prior behavior you are comparing against.\n- `variable_under_test`: The single factor that is intentionally changing in a comparison case.\n- `held_constant`: Prompt shape, tool setup, model settings, or state rules that were intentionally kept the same.\n- `output_constraint`: Any schema, length, or response-shape constraint used to keep the comparison fair.\n- `status`: Use `pass`, `fail`, `unexpected-pass`, `unexpected-fail`, or `blocked` only when there is a credible comparison basis or control.\n- `confidence`: `high`, `medium`, or `low`.\n- `state_setup`: Fresh or reused state, cache strategy, unique IDs, and cleanup checks.\n- `repeats`: Number of measured runs.\n- `warm_up`: Whether a warm-up run was used and why.\n- `variance`: Any useful spread or instability note across repeated runs.\n- `usage_note`: Token, usage, or output-length note when it materially affects interpretation.\n- `control`: Known-good comparison point for regression or behavior-change questions.\n- `risk_profile`: `read-only`, `mutating`, or `costly` for live probes.\n- `env_vars`: Exact environment-variable names the case plans to read.\n- `approval`: `not-needed`, `pending`, or `approved` for cases that need user permission before execution.\n\nUse `result_flag` as the fast scan field. It is what makes unexpected or negative findings jump out before the reader studies the full report.\n\nUse `status` only when you have a real comparison basis. If the case is exploratory and there is no trustworthy baseline, prefer a strong `observation_summary` plus `result_flag` and `confidence` instead of pretending the result is a clean pass or fail.\n\n## Choosing Execution Mode\n\nPick an execution mode before you run the case:\n\n- Use `single-shot` for deterministic, one-run checks.\n- Use `repeat-N` automatically when the question involves cache behavior, retries, streaming, interruptions, rate limiting, concurrency, or other run-to-run-sensitive behavior.\n- Use `warm-up + repeat-N` when the first run is likely to include cold-start effects such as container provisioning, import caches, or prompt-cache population.\n\nUse these defaults unless the task clearly needs something else:\n\n- `repeat-3` for a quick screen of a repeat-sensitive question.\n- `warm-up + repeat-10` for decision-grade latency comparisons or release-facing recommendations.\n- For costly live probes, start at `repeat-3`, then expand only if the answer is still unclear.\n\nIf it is genuinely unclear whether extra runs are worth the time or cost, ask the user before expanding the probe.\n\n## Phase The Matrix\n\nWhen the question is comparative or benchmark-like, do not jump straight to the largest matrix.\n\nStart with a pilot:\n\n- One control.\n- One or two highest-signal success cases.\n- The smallest repeat count that can disqualify a weak candidate quickly.\n\nExpand only when:\n\n- The candidate survives the pilot.\n- The results are close enough that more samples matter.\n- A major runtime surface is still uncovered.\n- The user explicitly wants decision-grade evidence.\n\n## Coverage Categories\n\nTry to cover at least one case from each relevant category:\n\n- `success`: Normal behavior that should work.\n- `control`: Known-good comparison such as `origin/master`, the latest release, or the same request without the suspected option.\n- `boundary`: Size, count, or parameter limits near a plausible edge.\n- `invalid`: Bad inputs or unsupported combinations.\n- `misconfig`: Missing key, wrong endpoint, bad permissions, or incompatible local setup.\n- `transient`: Timeout, temporary server issue, network breakage, or rate limiting.\n- `recovery`: Retry behavior, partial completion, duplicate submission, or cleanup.\n- `concurrency`: Overlapping operations when shared state, ordering, or isolation may matter.\n- `quality`: A harder or more open-ended sample when the user is asking about model intelligence, not just workflow parity.\n\nIf time is limited, prioritize categories in this order:\n\n1. Known-good control when the question implies regression or drift.\n2. Highest-risk success case.\n3. Most plausible user-facing failure.\n4. Most likely edge case with ambiguous behavior.\n5. Cleanup or retry semantics.\n6. Lower-probability extremes.\n\n## Matrix Template\n\nUse this compact template:\n\n    | case_id | scenario | mode | question | setup | state_setup | variable_under_test | held_constant | comparison_basis | observation_summary | result_flag | status | evidence |\n    | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n    | K1 | Known-good control | single-shot | Does the baseline still show the expected behavior? | Same probe against baseline target | Fresh state | none | current probe shape | `origin/master` or latest release | pending | pending | pending | pending |\n    | S1 | Baseline success | single-shot | What does the normal success path look like at runtime? | Valid config and representative input | Fresh state | none | representative input and setup | current docs or local expectation | pending | pending | pending | pending |\n    | R1 | Cache or retry behavior | warm-up + repeat-N | Does behavior change after the first run or across retries? | Same request repeated under controlled settings | Cache key or retry setup recorded | reuse versus fresh state | prompt shape and tool setup | same request without reuse, or docs if available | pending | pending | pending | pending |\n    | C1 | Model comparison pilot | warm-up + repeat-N | Does candidate B preserve the covered behavior while improving latency? | Same scenario across two models | Fresh state and stable IDs | model name | prompt shape, tool choice, and model settings parity | control model in the same probe | pending | pending | pending | pending |\n    | E1 | Invalid input | single-shot | How does the runtime reject a realistic bad input? | Missing required field | Fresh state | invalid field value | same request with valid field | same request with valid field | pending | pending | pending | pending |\n    | X1 | Concurrent overlap | repeat-N | Do overlapping runs interfere with each other? | Two or more overlapping operations | Unique IDs plus cleanup verification | overlap timing | same logical input | same request serialized, if available | pending | pending | pending | pending |\n\n## Recording Results\n\nKeep `question` unchanged after execution. Put the actual behavior in `observation_summary`, then mark the scan-friendly `result_flag`.\n\nUse these `result_flag` values consistently:\n\n- `unexpected`: The result diverged from the best current understanding in a surprising way.\n- `negative`: The result exposed a user-relevant failure, risk, or sharp edge.\n- `expected`: The result matched the current understanding and did not reveal new risk.\n- `blocked`: The case did not produce a trustworthy observation.\n\nOnly fill `status` when there is a credible comparison basis. Otherwise use `observation_summary`, `result_flag`, and `confidence` to communicate what was learned without over-claiming certainty.\n\nFor comparison cases, use `observation_summary` and the final report to say whether the evidence supports pattern parity only or a broader quality claim.\n\nIf a case reveals a new branch of behavior, add a follow-up case instead of overloading the original one.\n\n## Evidence Discipline\n\nTreat a case as incomplete when:\n\n- The observed output omits the key result you were testing.\n- The script mixed multiple questions and the result is ambiguous.\n- Hidden state, cache behavior, or previous runs may have influenced the result and were not controlled or documented.\n- The question is whether behavior changed, but the case has no credible control or baseline to compare against.\n- The case plans to read environment variables, but the exact variable names were not approved by the user before execution.\n- The case was repeat-sensitive, but it ran only once without a clear rationale.\n\nWhen this happens, narrow the probe and rerun. A smaller script with a cleaner result is better than a more complicated script that is hard to trust.\n","AGENTS.md":"# AGENTS.md\n\nThis file provides guidance to AI coding agents (Claude Code, Codex, Copilot, Cursor, Aider, etc.) when working with code in this repository.\n\n## Project Overview\n\nioredis is a full-featured Redis client for Node.js, written 100% in TypeScript. Source lives in `lib/`, compiles to CommonJS in `built/` (the published artifact), and supports standalone, Sentinel, and Cluster topologies.\n\n## Common Commands\n\n### Building\n\n```bash\nnpm run build          # Wipe built/ and compile TypeScript\nnode bin/index.js      # Regenerate lib/utils/RedisCommander.ts\n```\n\n### Linting and Formatting\n\n```bash\nnpm run lint           # Run ESLint over lib/\nnpm run format         # Format files with Prettier\nnpm run format-check   # Check formatting\n```\n\n### Testing\n\nFunctional and cluster tests require running Redis servers. Unit tests under `test/unit/` mock the network and do not need a server.\n\nTo start and stop local Redis test infrastructure:\n\n```bash\nnpm run docker:setup      # Start standalone Redis on 6379 and cluster nodes on 3000-3005\nnpm run docker:teardown   # Stop test Redis servers\n```\n\n```bash\nnpm test                  # Default non-cluster test: test:js then test:tsd\nnpm run test:js           # Mocha over test/helpers, test/unit, test/functional\nnpm run test:cluster      # Mocha over test/cluster\nnpm run test:tsd          # Build then run tsd against test/typing\nnpm run test:cov          # Test coverage\n\n# Run a single test file\nTS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/foo.ts\"\n\n# Run a single test by name\nTS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/foo.ts\" --grep \"partial test title\"\n```\n\n## Generated Code\n\n**Do not hand-edit**: `lib/utils/RedisCommander.ts` (generated), `built/` (build output), and `node_modules/`.\n\n`lib/utils/RedisCommander.ts` holds the typed signatures for every Redis command. This is what gives calls like `redis.set(...)` their types.\n\nRegenerate it with:\n\n```bash\nnode bin/index.js\n```\n\nGeneration uses `@ioredis/interface-generator` plus per-command config in `bin/`:\n\n- **`bin/template.ts`** — File skeleton; generated interface is spliced into the `////` marker.\n- **`bin/overrides.js`** — Hand-written signatures for commands the generator gets wrong, such as `hgetall` and `mset`.\n- **`bin/argumentTypes.js`**, **`bin/returnTypes.js`**, **`bin/sortArguments.js`**, **`bin/typeMaps.js`** — Argument and return type mapping and ordering.\n\nWhen adding command typing support, edit the `bin/` config and regenerate. Never patch `RedisCommander.ts` directly.\n\n## Architecture\n\n### Layered Design\n\n```text\nPublic API (`Redis`, `Cluster`, `Pipeline`, `Command`, options)\n  → Command facade (`Commander`, generated `RedisCommander` typings, Lua scripts)\n    → Command objects and queues (`Command`, offline queue, command queue, pipeline queue)\n      → Topology routing (standalone, Sentinel, Cluster slots, subscriber groups)\n        → Connection layer (`connectors/`, `redis/event_handler.ts`, retry and ready checks)\n          → RESP parsing and reply handling (`DataHandler`, `redis-parser`)\n```\n\n### Key Source Areas\n\n- **`lib/index.ts`** — Public export surface for the package. Changes here affect the published TypeScript declarations and user-facing API.\n- **`lib/Redis.ts`** — Main standalone and Sentinel client. Manages connection lifecycle (`wait → connecting → connect → ready → close → reconnecting → end`), offline queue behavior, reconnection strategy, and connector selection.\n- **`lib/utils/Commander.ts`** — Shared command facade for `Redis` and `Cluster`. Dynamically attaches builtin Redis commands, string and `Buffer` variants, autopipelining dispatch, direct `sendCommand`, and `defineCommand` Lua registration.\n- **`lib/Command.ts`** — Single Redis command representation. Handles argument transformation, reply transformation, promise/callback resolution, key-slot calculation, and subscriber/monitor-mode command flags.\n- **`lib/DataHandler.ts`** — Parser and reply dispatcher. Wraps `redis-parser`, consumes socket data, resolves queued commands, and routes Pub/Sub replies and monitor messages.\n- **`lib/connectors/`** — Network connector implementations. `StandaloneConnector` handles TCP/TLS sockets; `SentinelConnector/` resolves masters through Sentinel using `FailoverDetector` and `SentinelIterator`.\n- **`lib/cluster/`** — Cluster client, per-node connection pool, slot cache refresh, redirection handling for `MOVED` and `ASK`, retry scheduling, and cluster Pub/Sub through `ClusterSubscriber`, `ShardedSubscriber`, and `ClusterSubscriberGroup`.\n- **`lib/Pipeline.ts`** and **`lib/transaction.ts`** — Batched command execution. `pipeline()` is non-atomic batching; `multi()` adds MULTI/EXEC transaction behavior.\n- **`lib/autoPipelining.ts`** — Same-tick command batching. `notAllowedAutoPipelineCommands` lists commands that must bypass autopipelining, such as auth, subscribe, and multi.\n- **`lib/Script.ts`** — Lua script abstraction used by `defineCommand`, with `EVALSHA` execution and `EVAL` fallback.\n- **`lib/ScanStream.ts`** — Readable stream wrapper for `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`.\n- **`lib/tracing.ts`** — Command and connection tracing hooks with argument sanitization.\n\n### How Commands Execute\n\n1. User calls a method such as `redis.get()` or `cluster.set()`.\n2. `Commander` routes the call through autopipelining, pipeline/transaction handling, or direct `sendCommand`.\n3. A `Command` object is created with transformed arguments and callback/promise state.\n4. Standalone clients enqueue the command on one connection; Cluster clients choose a node by key slot and may retry on redirects.\n5. The command is written to the socket after connection readiness checks and offline queue handling.\n6. `redis-parser` parses the RESP reply from the socket.\n7. `DataHandler` resolves the matching queued command, applies reply transformers, and emits Pub/Sub or monitor events when relevant.\n\n## Commit Messages\n\nFollow [Conventional Commits](https://www.conventionalcommits.org/): `<type>: <subject>`.\n\nCommon types include `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, and `chore`.\n\nReleases are automated via semantic-release (`.releaserc.json`), so commit messages drive the changelog and version bump.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\nThis file provides guidance to AI coding agents (Claude Code, Codex, Copilot, Cursor, Aider, etc.) when working with code in this repository.\n\n## Project Overview\n\nioredis is a full-featured Redis client for Node.js, written 100% in TypeScript. Source lives in `lib/`, compiles to CommonJS in `built/` (the published artifact), and supports standalone, Sentinel, and Cluster topologies.\n\n## Common Commands\n\n### Building\n\n```bash\nnpm run build          # Wipe built/ and compile TypeScript\nnode bin/index.js      # Regenerate lib/utils/RedisCommander.ts\n```\n\n### Linting and Formatting\n\n```bash\nnpm run lint           # Run ESLint over lib/\nnpm run format         # Format files with Prettier\nnpm run format-check   # Check formatting\n```\n\n### Testing\n\nFunctional and cluster tests require running Redis servers. Unit tests under `test/unit/` mock the network and do not need a server.\n\nTo start and stop local Redis test infrastructure:\n\n```bash\nnpm run docker:setup      # Start standalone Redis on 6379 and cluster nodes on 3000-3005\nnpm run docker:teardown   # Stop test Redis servers\n```\n\n```bash\nnpm test                  # Default non-cluster test: test:js then test:tsd\nnpm run test:js           # Mocha over test/helpers, test/unit, test/functional\nnpm run test:cluster      # Mocha over test/cluster\nnpm run test:tsd          # Build then run tsd against test/typing\nnpm run test:cov          # Test coverage\n\n# Run a single test file\nTS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/foo.ts\"\n\n# Run a single test by name\nTS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/foo.ts\" --grep \"partial test title\"\n```\n\n## Generated Code\n\n**Do not hand-edit**: `lib/utils/RedisCommander.ts` (generated), `built/` (build output), and `node_modules/`.\n\n`lib/utils/RedisCommander.ts` holds the typed signatures for every Redis command. This is what gives calls like `redis.set(...)` their types.\n\nRegenerate it with:\n\n```bash\nnode bin/index.js\n```\n\nGeneration uses `@ioredis/interface-generator` plus per-command config in `bin/`:\n\n- **`bin/template.ts`** — File skeleton; generated interface is spliced into the `////` marker.\n- **`bin/overrides.js`** — Hand-written signatures for commands the generator gets wrong, such as `hgetall` and `mset`.\n- **`bin/argumentTypes.js`**, **`bin/returnTypes.js`**, **`bin/sortArguments.js`**, **`bin/typeMaps.js`** — Argument and return type mapping and ordering.\n\nWhen adding command typing support, edit the `bin/` config and regenerate. Never patch `RedisCommander.ts` directly.\n\n## Architecture\n\n### Layered Design\n\n```text\nPublic API (`Redis`, `Cluster`, `Pipeline`, `Command`, options)\n  → Command facade (`Commander`, generated `RedisCommander` typings, Lua scripts)\n    → Command objects and queues (`Command`, offline queue, command queue, pipeline queue)\n      → Topology routing (standalone, Sentinel, Cluster slots, subscriber groups)\n        → Connection layer (`connectors/`, `redis/event_handler.ts`, retry and ready checks)\n          → RESP parsing and reply handling (`DataHandler`, `redis-parser`)\n```\n\n### Key Source Areas\n\n- **`lib/index.ts`** — Public export surface for the package. Changes here affect the published TypeScript declarations and user-facing API.\n- **`lib/Redis.ts`** — Main standalone and Sentinel client. Manages connection lifecycle (`wait → connecting → connect → ready → close → reconnecting → end`), offline queue behavior, reconnection strategy, and connector selection.\n- **`lib/utils/Commander.ts`** — Shared command facade for `Redis` and `Cluster`. Dynamically attaches builtin Redis commands, string and `Buffer` variants, autopipelining dispatch, direct `sendCommand`, and `defineCommand` Lua registration.\n- **`lib/Command.ts`** — Single Redis command representation. Handles argument transformation, reply transformation, promise/callback resolution, key-slot calculation, and subscriber/monitor-mode command flags.\n- **`lib/DataHandler.ts`** — Parser and reply dispatcher. Wraps `redis-parser`, consumes socket data, resolves queued commands, and routes Pub/Sub replies and monitor messages.\n- **`lib/connectors/`** — Network connector implementations. `StandaloneConnector` handles TCP/TLS sockets; `SentinelConnector/` resolves masters through Sentinel using `FailoverDetector` and `SentinelIterator`.\n- **`lib/cluster/`** — Cluster client, per-node connection pool, slot cache refresh, redirection handling for `MOVED` and `ASK`, retry scheduling, and cluster Pub/Sub through `ClusterSubscriber`, `ShardedSubscriber`, and `ClusterSubscriberGroup`.\n- **`lib/Pipeline.ts`** and **`lib/transaction.ts`** — Batched command execution. `pipeline()` is non-atomic batching; `multi()` adds MULTI/EXEC transaction behavior.\n- **`lib/autoPipelining.ts`** — Same-tick command batching. `notAllowedAutoPipelineCommands` lists commands that must bypass autopipelining, such as auth, subscribe, and multi.\n- **`lib/Script.ts`** — Lua script abstraction used by `defineCommand`, with `EVALSHA` execution and `EVAL` fallback.\n- **`lib/ScanStream.ts`** — Readable stream wrapper for `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`.\n- **`lib/tracing.ts`** — Command and connection tracing hooks with argument sanitization.\n\n### How Commands Execute\n\n1. User calls a method such as `redis.get()` or `cluster.set()`.\n2. `Commander` routes the call through autopipelining, pipeline/transaction handling, or direct `sendCommand`.\n3. A `Command` object is created with transformed arguments and callback/promise state.\n4. Standalone clients enqueue the command on one connection; Cluster clients choose a node by key slot and may retry on redirects.\n5. The command is written to the socket after connection readiness checks and offline queue handling.\n6. `redis-parser` parses the RESP reply from the socket.\n7. `DataHandler` resolves the matching queued command, applies reply transformers, and emits Pub/Sub or monitor events when relevant.\n\n## Commit Messages\n\nFollow [Conventional Commits](https://www.conventionalcommits.org/): `<type>: <subject>`.\n\nCommon types include `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, and `chore`.\n\nReleases are automated via semantic-release (`.releaserc.json`), so commit messages drive the changelog and version bump.\n","isInternal":false,"tokens":1490,"sizeBytes":6385},{"name":"SKILL.md","path":".agents/skills/code-change-verification/SKILL.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/code-change-verification/SKILL.md","title":"code-change-verification","category":"anthropic-skill","format":"markdown","content":"---\nname: code-change-verification\ndescription: Verify ioredis code changes before handoff. Use when an agent changes or reviews runtime TypeScript, Redis command support, generated typings, tests, docs tied to behavior, build tooling, release-sensitive files, or any task that needs choosing and running the right local validation commands.\n---\n\n# Code Change Verification\n\nUse this skill to choose the smallest credible validation set for an ioredis change, run it when feasible, and report exactly what passed, failed, or was skipped.\n\n## Workflow\n\n1. Inspect the diff and changed files before choosing commands.\n   - Use `git diff --stat`, `git diff --name-only`, and targeted file reads.\n   - Do not stage, unstage, or commit unless the user explicitly asks.\n   - Treat `built/` and `lib/utils/RedisCommander.ts` as generated outputs; do not hand-edit them.\n\n2. Classify the change.\n   - Runtime code under `lib/`: run focused tests plus build when the change affects exported declarations or compiled output.\n   - Redis command typing or generated command support: inspect `bin/` config, regenerate with `node bin/index.js` if needed, and run tsd or targeted typing tests.\n   - Functional Redis behavior: run the smallest relevant Mocha files and assume a compatible Redis server is on default host/port. If sandboxed Redis access is blocked, ask for permission rather than assuming Redis is unavailable.\n   - Cluster behavior: use `npm run docker:setup` if infrastructure is needed, then targeted `test/cluster/**/*.ts` or `npm run test:cluster`.\n   - Docs-only changes: run `npm run format-check` only if formatting-sensitive files changed; otherwise inspect rendered Markdown manually.\n   - Build/tooling changes: run `npm run build` and the affected script directly.\n\n3. Prefer focused validation before broad validation.\n   - For self-contained pure unit files, run the test file alone first: `TS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/<file>.ts\"`.\n   - Include `test/helpers/*.ts` only when the unit file relies on global hooks or helper setup.\n   - Functional command change: include `test/helpers/*.ts` and the specific `test/functional/...` file.\n   - Typing change: `npm run build` then `npx tsd --files test/typing/<file>.test-d.ts` when a focused file exists.\n   - Public API or cross-cutting behavior: escalate to `npm test` after focused tests pass.\n   - Formatting-only TypeScript edits: run `npm run lint` or `npm run format-check` as appropriate.\n\n4. Handle generated artifacts deliberately.\n   - If `bin/argumentTypes.js`, `bin/returnTypes.js`, `bin/overrides.js`, `bin/sortArguments.js`, `bin/typeMaps.js`, or `bin/template.ts` changes command declarations, regenerate `lib/utils/RedisCommander.ts` with `node bin/index.js`.\n   - If generated output changes unexpectedly, inspect the generator inputs before accepting it.\n   - Build output in `built/` is publish-facing but generated by `npm run build`; mention if it is intentionally not updated.\n\n5. Report results in handoff.\n   - List each command run and its result.\n   - For failures, include the failing test name or key error line and whether it appears related.\n   - For skipped commands, state the concrete reason, such as missing Redis server, blocked sandbox access, or out-of-scope broad suite.\n\n## Command Reference\n\n- `npm run build`: remove `built/` and compile TypeScript.\n- `npm run lint`: ESLint over `lib/`.\n- `npm run format-check`: Prettier check.\n- `npm run test:js`: non-cluster Mocha suite over helpers, unit, and functional tests.\n- `npm run test:cluster`: cluster Mocha suite.\n- `npm run test:tsd`: build and run all tsd tests.\n- `npm test`: `test:js` plus `test:tsd`.\n- `npm run docker:setup` / `npm run docker:teardown`: start/stop Redis test infrastructure.\n","frontmatter":{"name":"code-change-verification","description":"Verify ioredis code changes before handoff. Use when an agent changes or reviews runtime TypeScript, Redis command support, generated typings, tests, docs tied to behavior, build tooling, release-sensitive files, or any task that needs choosing and running the right local validation commands."},"isInternal":false,"tokens":876,"sizeBytes":3814},{"name":"doc-coverage-checklist.md","path":".agents/skills/docs-sync/references/doc-coverage-checklist.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/docs-sync/references/doc-coverage-checklist.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# ioredis Doc Coverage Checklist\n\nUse this checklist to scan the selected scope and validate that user-facing ioredis behavior is documented in the right place. In diff mode, limit the scan to the selected task scope: staged changes, unstaged changes, staged plus unstaged changes, or a branch comparison such as `git diff main...HEAD` for PR-oriented audits. In comprehensive mode, inventory the public surfaces listed below.\n\n## Public API inventory\n\n- Public exports from `lib/index.ts`: default `Redis`, named `Redis`, `Cluster`, exported classes, exported types, and compatibility exports.\n- Constructor and option types:\n  - `lib/redis/RedisOptions.ts`: `RedisOptions`, `CommonRedisOptions`, `RetryStrategy`, `ReconnectOnError`, and `DEFAULT_REDIS_OPTIONS`.\n  - `lib/cluster/ClusterOptions.ts`: `ClusterOptions`, `ClusterNodeRetryStrategy`, DNS/NAT helper types, and `DEFAULT_CLUSTER_OPTIONS`.\n  - `lib/connectors/StandaloneConnector.ts`: standalone TCP/TLS connection options.\n  - `lib/connectors/SentinelConnector/types.ts`: Sentinel connection options, failover behavior, and sentinel-specific limits.\n- Generated command API:\n  - `lib/utils/RedisCommander.ts` is generated and must not be hand-edited.\n  - `bin/overrides.js`, `bin/argumentTypes.js`, `bin/returnTypes.js`, `bin/sortArguments.js`, and `bin/typeMaps.js` define command signature and return documentation inputs.\n- Core classes and behavior surfaces: `lib/Redis.ts`, `lib/cluster/index.ts`, `lib/Command.ts`, `lib/Pipeline.ts`, `lib/transaction.ts`, `lib/ScanStream.ts`, `lib/DataHandler.ts`, `lib/autoPipelining.ts`, `lib/Script.ts`, and `lib/tracing.ts`.\n- User-facing examples and executable docs: `README.md`, `examples/`, and `test/typing/`.\n\n## Option JSDoc requirements\n\n- Every public option on `CommonRedisOptions`, `RedisOptions`-contributing connection types, and `ClusterOptions` should have clear JSDoc unless the option is intentionally internal.\n- JSDoc should include:\n  - What the option changes in user-visible behavior.\n  - Default value with `@default`, matching `DEFAULT_REDIS_OPTIONS` or `DEFAULT_CLUSTER_OPTIONS`.\n  - Accepted values when the TypeScript type is broad, such as callback return contracts or string roles.\n  - Topology limits, such as standalone-only, Sentinel-only, Cluster-only, subscriber-mode, or RESP mode constraints.\n  - Redis version requirements when relevant.\n- Keep JSDoc and defaults synchronized for options such as retry strategies, timeouts, offline queue behavior, ready checks, auto pipelining, client info, authentication, Sentinel discovery, Cluster redirections, SRV lookup, NAT mapping, and sharded subscribers.\n- When an option is deprecated, renamed, or compatibility-only, document that in JSDoc and remove stale README guidance if it no longer applies.\n\n## Documentation surfaces\n\n- `README.md`: main guide, examples, feature overview, constructor options, Cluster, Sentinel, Pub/Sub, pipelines, transactions, Lua scripts, streams/scans, TLS, reconnect behavior, and TypeScript usage.\n- `docs/`: generated TypeDoc output from `npm run docs`; update generated docs only as part of an intentional docs generation change.\n- TypeDoc source comments: public JSDoc in `lib/index.ts`, `lib/redis/RedisOptions.ts`, `lib/cluster/ClusterOptions.ts`, connector option types, tracing types, and public classes.\n- `examples/`: runnable examples that should compile and use current APIs.\n- `test/typing/`: tsd coverage for public TypeScript signatures, command typings, constructor options, and exported types.\n\n## Code-first pass\n\n- Start from code, not existing docs. Identify the changed public symbol, option, command signature, return type, default, error, event, or lifecycle behavior.\n- Map the behavior to the closest existing doc surface. Prefer updating an existing README section, JSDoc block, example, or typing test over creating a new document.\n- For command typing changes, update generator config in `bin/`, regenerate `lib/utils/RedisCommander.ts`, and consider `test/typing/commands.test-d.ts`.\n- For option changes, update the interface JSDoc, default object, README option guidance if present, and tsd coverage when the type surface matters.\n- For behavior changes in Cluster, Sentinel, Pub/Sub, pipelines, transactions, scan streams, reconnect logic, ready checks, timeouts, tracing, or data handling, check both README prose and public JSDoc.\n\n## Evidence capture\n\n- Record the file path and symbol or setting name, for example `lib/redis/RedisOptions.ts:CommonRedisOptions.commandTimeout`.\n- Record the default from `DEFAULT_REDIS_OPTIONS` or `DEFAULT_CLUSTER_OPTIONS` when documenting options.\n- Record the implementation behavior that proves the docs text, such as the method, event handler, retry branch, or command transformer.\n- Avoid large code dumps. A short path plus symbol and behavior note is enough.\n\n## Red flags\n\n- README option names, defaults, or examples differ from `RedisOptions`, `ClusterOptions`, connector option types, or default objects.\n- Public options exist without JSDoc, or JSDoc omits important default/behavior constraints.\n- Generated TypeDoc pages under `docs/` are stale relative to TypeScript source comments.\n- `lib/utils/RedisCommander.ts` was manually edited instead of regenerated from `bin/` config.\n- Command return types, Buffer variants, callbacks, Promise behavior, or pipeline/transaction behavior changed without typing or docs review.\n- Removed, renamed, or deprecated features remain documented as current behavior.\n- Examples rely on unsupported Redis versions, topology assumptions, or undocumented setup.\n\n## Structural changes\n\n- Propose README restructuring only when an existing section mixes quick-start usage with deep reference detail, or when Cluster/Sentinel/Pub/Sub/TypeScript material has no sensible home.\n- Keep quick-start examples short. Move advanced retry, timeout, topology, command typing, and failure-mode details into focused sections or JSDoc.\n- Cross-link related concepts instead of duplicating long explanations, especially for options shared between standalone Redis and Cluster `redisOptions`.\n\n## Diff mode guidance\n\n- Choose the diff source that matches the task:\n  - Staged work: `git diff --cached`.\n  - Unstaged work: `git diff`.\n  - All local in-progress work: inspect both `git diff --cached` and `git diff`.\n  - PR-oriented branch audit: `git diff main...HEAD` or the equivalent branch base.\n- Focus only on changed public behavior: new exports/options, modified defaults, removed features, renamed settings, new command signatures, changed reply transformations, or changed lifecycle behavior.\n- Document removals explicitly so stale README, examples, JSDoc, TypeDoc output, and typing tests can be pruned.\n\n## Patch guidance\n\n- Keep edits scoped and aligned to the existing README/JSDoc tone.\n- Do not hand-edit `lib/utils/RedisCommander.ts`; regenerate it with `node bin/index.js` after command typing config changes.\n- Leave translated or vendored docs untouched unless the task explicitly targets them.\n- For Markdown-only updates, inspect nearby formatting. For JSDoc/API changes, run `npm run docs` when generated docs must be refreshed.\n","isInternal":false,"tokens":1541,"sizeBytes":7174},{"name":"SKILL.md","path":".agents/skills/docs-sync/SKILL.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/docs-sync/SKILL.md","title":"docs-sync","category":"anthropic-skill","format":"markdown","content":"---\nname: docs-sync\ndescription: Keep ioredis documentation synchronized with code behavior. Use when an agent changes public APIs, options, Redis command support, examples, generated typings, connection behavior, Cluster/Sentinel behavior, Pub/Sub, pipelines, transactions, scan streams, reconnect behavior, TypeScript usage, or release-facing behavior that may require README or docs updates.\n---\n\n# Docs Sync\n\nUse this skill to decide whether an ioredis change needs documentation, update the right docs, and keep examples aligned with tested behavior.\n\nFor broad documentation audits, option/API coverage checks, or unclear documentation scope, also read `references/doc-coverage-checklist.md` before deciding what to update.\n\n## Workflow\n\n1. Inspect the changed behavior.\n   - Read the diff and the surrounding implementation.\n   - Identify whether users must know a new capability, option, error case, event, command signature, return shape, or migration concern.\n   - Treat TypeScript declarations and public JSDoc as documentation when command signatures, constructor options, or exported types change.\n\n2. Find the documentation surface.\n   - `README.md`: primary user-facing guide, examples, feature overview, options, and common workflows.\n   - `lib/redis/RedisOptions.ts`: `RedisOptions`, `CommonRedisOptions`, option JSDoc, and `DEFAULT_REDIS_OPTIONS`.\n   - `lib/cluster/ClusterOptions.ts`: `ClusterOptions`, cluster option JSDoc, and `DEFAULT_CLUSTER_OPTIONS`.\n   - `lib/connectors/StandaloneConnector.ts` and `lib/connectors/SentinelConnector/types.ts`: connection option types that contribute to public constructor options.\n   - `docs/`: generated TypeDoc output from public source comments.\n   - `examples/`: runnable snippets that should match current API behavior.\n   - `lib/index.ts` and public TypeDoc comments: exported API documentation surface.\n   - `test/typing/`: executable documentation for TypeScript signatures.\n\n3. Update docs when the change affects users.\n   - Public option or constructor behavior: document option name, default, behavior, topology limitations, and Redis version constraints in JSDoc first; update README/examples when users need prose or usage guidance.\n   - Redis command support: update generator config in `bin/`, regenerate `lib/utils/RedisCommander.ts`, and document only if README/docs mention related command groups or if the change affects command typing, return mapping, or examples.\n   - Pub/Sub, sharded Pub/Sub, monitor, pipeline, transaction, Sentinel, Cluster, TLS, reconnect, or offline queue behavior: update the relevant README/docs section.\n   - New or changed public exports from `lib/index.ts`: update TypeDoc comments and typing tests when the exported type or class is part of the supported API.\n   - Breaking or compatibility-sensitive behavior: add explicit migration or caveat wording.\n   - Internal-only refactors with no behavioral/API impact: state that no docs update is needed and why.\n\n4. Keep examples honest.\n   - Prefer short examples that compile against the current public API.\n   - Avoid documenting behavior that is not covered by tests unless you also add or request coverage.\n   - If an example requires a Redis version, topology, or protocol mode, say so near the example.\n   - Use existing README style and terminology.\n\n5. Verify documentation changes.\n   - For TypeScript examples or declarations, run the focused tsd test or add one when appropriate.\n   - For API docs comments, run `npm run docs` when the change affects generated docs.\n   - For command typing changes, run `node bin/index.js` before validating generated typings.\n   - For Markdown-only edits, inspect nearby formatting and links; run `npm run format-check` only when relevant files are covered by Prettier.\n\n## Documentation Decision Checklist\n\n- Does the change alter public exports from `lib/index.ts`?\n- Does it add, remove, rename, or change JSDoc/defaults for `RedisOptions`, `CommonRedisOptions`, `ClusterOptions`, standalone connection options, or Sentinel connection options?\n- Does it add, remove, or change a Redis command method signature?\n- Does it change reply transformation, Buffer variants, callbacks, or Promise behavior?\n- Does it affect connection lifecycle, retries, ready checks, offline queue, or subscriber mode?\n- Does it affect Cluster routing, redirections, subscriber groups, Sentinel discovery, or TLS?\n- Does it add an option, event, error condition, or environment assumption?\n- Would a user need different code after this change?\n\nIf any answer is yes, update docs or explicitly explain why existing docs already cover it.\n","frontmatter":{"name":"docs-sync","description":"Keep ioredis documentation synchronized with code behavior. Use when an agent changes public APIs, options, Redis command support, examples, generated typings, connection behavior, Cluster/Sentinel behavior, Pub/Sub, pipelines, transactions, scan streams, reconnect behavior, TypeScript usage, or release-facing behavior that may require README or docs updates."},"isInternal":false,"tokens":935,"sizeBytes":4620},{"name":"SKILL.md","path":".agents/skills/implement-command/SKILL.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/implement-command/SKILL.md","title":"implement-command","category":"anthropic-skill","format":"markdown","content":"---\nname: implement-command\ndescription: Use when adding or updating Redis command support in ioredis, including command metadata checks, generator inputs under bin/, generated RedisCommander typings, return and argument overrides, functional command tests, optional tsd coverage, and validation.\n---\n\n# Implement Command\n\nUse this skill when adding a missing Redis command, correcting an existing command signature, changing command return types, or adding coverage for command-specific Buffer, callback, pipeline, or transformer behavior.\n\n## Command Support Map\n\n- `@ioredis/commands`: upstream command metadata consumed by the generator.\n- `bin/index.js`: generator entry point for `lib/utils/RedisCommander.ts`.\n- `bin/returnTypes.js`: command return type map. Most new commands need an entry here.\n- `bin/argumentTypes.js`: command-specific argument shape overrides when metadata or global mapping is insufficient.\n- `bin/typeMaps.js`: global Redis argument category to TypeScript type mapping.\n- `bin/overrides.js`: manual overloads for signatures the generator cannot express cleanly.\n- `bin/sortArguments.js`: argument reordering for commands whose generated order is wrong.\n- `lib/utils/RedisCommander.ts`: generated declarations. Regenerate it; do not hand-edit it.\n- `lib/Command.ts`: command argument and reply transformer registry. Touch only when transformer behavior is needed.\n- `test/functional/commands/<command>.ts`: runtime command coverage.\n- `test/functional/transformer.ts`: transformer runtime coverage.\n- `test/typing/commands.test-d.ts`: public command typing coverage.\n- `test/typing/transformers.test-d.ts`: transformer typing coverage.\n\n## Workflow\n\n1. Establish command scope.\n   - Normalize command keys to lowercase, matching `bin/returnTypes.js`.\n   - Resolve command aliases or subcommands before editing.\n   - Confirm the command exists in `@ioredis/commands`. If it is missing there, stop and report that the metadata package must be updated before ioredis can generate typed command support.\n   - Identify the minimum Redis server version needed and whether functional tests must be version-gated.\n\n2. Inspect current support.\n   - Search `lib/utils/RedisCommander.ts`, `bin/`, `test/functional/commands/`, and `test/typing/` for the command and related aliases.\n   - Inspect nearby command families before choosing types, for example hash expiration commands, sorted-set commands, stream commands, or pub/sub commands.\n   - Check existing argument and reply transformers before adding new ones.\n\n3. Update generator inputs.\n   - Prefer `bin/returnTypes.js` for return type corrections.\n   - Use a string return type for simple fixed replies.\n   - Use a function return type when replies depend on subcommands, options, or tokens.\n   - Reuse `hasToken` and `matchSubcommand` in `bin/returnTypes.js` when they fit.\n   - Use `bin/argumentTypes.js` only for command-specific argument overrides.\n   - Use `bin/typeMaps.js` only for broad metadata category fixes that should affect multiple commands.\n   - Use `bin/overrides.js` only when generated overloads cannot express the supported API cleanly.\n   - Keep command names lowercase in generator maps unless the surrounding file uses another established convention.\n\n4. Regenerate declarations.\n   - In this repo, use `node bin/index.js` unless `package.json` later adds an explicit generation script.\n   - Review the generated diff in `lib/utils/RedisCommander.ts`.\n   - Check the normal method, callback overload, pipeline/transaction shape, and Buffer variant when the command returns strings, arrays, nullable bulk replies, or transformed objects.\n   - If generation changes unrelated commands, inspect the generator input and do not accept surprising churn without an explanation.\n\n5. Add focused runtime coverage.\n   - Put command tests in `test/functional/commands/<lowercase-command>.ts`.\n   - Use `import Redis from \"../../../lib/Redis\";` and `import { expect } from \"chai\";`.\n   - Prefer `let redis: Redis`, `beforeEach(() => { redis = new Redis(); })`, and `afterEach(() => { redis.disconnect(); })`.\n   - For version-gated command tests under `test/functional/commands/`, import `isRedisVersionLowerThan` from `../../helpers/util`, and use `before(async function () { ... this.skip(); })`; use function syntax when calling `this.skip()`.\n   - Use unique keys such as `${command}_${caseName}_${Date.now()}`.\n   - Test the ioredis command surface: accepted argument shapes, option ordering, callback behavior, Buffer variants, and reply shape.\n   - Keep assertions focused on what ioredis sends and returns. Do not test Redis server internals beyond the smallest deterministic setup needed.\n   - Assert exact replies when stable; otherwise assert primitive type, nullable behavior, array/object shape, or Buffer conversion.\n\n6. Add typing coverage when useful.\n   - Add cases to `test/typing/commands.test-d.ts` when the command has nontrivial overloads, return types, Buffer variants, callback typing, or option-dependent replies.\n   - Cover `expectType<Promise<...>>(redis.command(...))`.\n   - Add Buffer variant expectations when the command has one.\n   - Add callback typing for nontrivial return types.\n   - Use `expectError` only for meaningful invalid signatures.\n   - Update `test/typing/transformers.test-d.ts` only when transformer APIs are affected.\n\n7. Consider documentation.\n   - Use the repo `docs-sync` skill when command support changes public signatures, return mapping, examples, or documented command behavior.\n   - Usually command support is documented through generated declarations and typing tests; update README/docs only when existing prose or examples cover the affected command family or users need version/topology caveats.\n\n8. Validate.\n   - Run `node bin/index.js` after generator input changes.\n   - Run the focused functional command test when Redis support is available, using the repo's Mocha pattern with `test/helpers/*.ts`.\n   - Run `npm run build` when generated declarations, public TypeScript, or generator output changed.\n   - If typing tests changed, run `npx tsd --files test/typing/commands.test-d.ts` after building.\n   - Use the repo `code-change-verification` skill before handoff to choose any additional validation.\n   - If Redis access is blocked by sandboxing, ask for permission to access the local Redis server rather than assuming it is unavailable.\n\n## Completion Report\n\nReport:\n\n- Commands added or updated.\n- Metadata/generator inputs changed.\n- Generated files changed.\n- Functional tests added or updated.\n- Typing tests added or updated.\n- Documentation decision.\n- Validation commands run and results.\n- Skipped validation with the concrete reason, including Redis version or local environment limits.\n","frontmatter":{"name":"implement-command","description":"Use when adding or updating Redis command support in ioredis, including command metadata checks, generator inputs under bin/, generated RedisCommander typings, return and argument overrides, functional command tests, optional tsd coverage, and validation."},"isInternal":false,"tokens":1413,"sizeBytes":6760},{"name":"SKILL.md","path":".agents/skills/pr-draft-summary/SKILL.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/pr-draft-summary/SKILL.md","title":"pr-draft-summary","category":"anthropic-skill","format":"markdown","content":"---\nname: pr-draft-summary\ndescription: Create the required PR-ready summary block, branch suggestion, title, and draft description for ioredis. Must be used before the final response whenever the actual task diff includes runtime code, tests, examples, build/test configuration, or docs with behavior impact, regardless of perceived change size. Skip only when no eligible files changed, every change is repo-meta or docs-only without behavior impact, the task is conversation-only, or the user explicitly opts out.\n---\n\n# PR Draft Summary\n\n## Purpose\n\nProduce a PR-ready summary after eligible work is complete: a concise change summary plus a PR-ready title and draft description for ioredis.\n\n## Close-out Gate\n\n1. Inspect the actual task diff before sending the final response.\n2. Run this skill when the diff includes runtime code, tests, examples, build/test configuration, or docs with behavior impact. Do not use perceived change size to skip an eligible change.\n3. Run it after any required verification and before sending the \"work complete\" response.\n4. Skip only when no eligible files changed, every change is repo-meta or docs-only without behavior impact, the task is conversation-only, or the user explicitly opts out.\n\n## Inputs to Collect Automatically (do not ask the user)\n\n- Current branch: `git rev-parse --abbrev-ref HEAD`.\n- Working tree: `git status -sb`.\n- Untracked files: `git ls-files --others --exclude-standard` (use with `git status -sb`; `--stat` omits them).\n- Changed files: `git diff --name-only` (unstaged) and `git diff --name-only --cached` (staged); sizes via `git diff --stat` and `git diff --stat --cached`.\n- Pull request base reference (prefer the canonical upstream branch; never use a feature branch's upstream as the PR base):\n  - `BASE_REF=upstream/main`; if it does not exist locally, use `origin/main`; if that does not exist locally, use `main`.\n  - `BASE_COMMIT=$(git merge-base \"$BASE_REF\" HEAD)`.\n- Committed branch diff: `git diff --name-only \"${BASE_COMMIT}..HEAD\"` and `git diff --stat \"${BASE_COMMIT}..HEAD\"`.\n- Commits ahead of the base fork point: `git log --oneline --no-merges ${BASE_COMMIT}..HEAD`.\n- Category signals for this repo: runtime (`lib/`, `bin/`, `examples/`, `benchmark/`), tests (`test/`), docs (`docs/`, `README.md`, `AGENTS.md`, `.agents/`, `.github/`), build/test config (`package.json`, `package-lock.json`, `tsconfig.json`, `.eslintrc*`, `.mocharc*`, `nyc.config.js`, `typedoc.json`).\n\n## Workflow\n\n1. Run the commands above without asking the user; compute `BASE_REF`/`BASE_COMMIT` first so later commands reuse them. Compare against `upstream/main`, `origin/main`, or `main`, not the current branch's upstream.\n2. Combine the committed branch diff with staged, unstaged, and untracked changes. If the combined diff is empty, reply briefly that no code changes were detected and skip emitting the PR block.\n3. Infer change type from the touched paths listed under \"Category signals\"; classify as feature, fix, refactor, or docs-with-impact, and flag backward-compatibility risk only when the diff changes released public APIs, client/command behavior, connection config, or the RESP wire handling. Judge that risk against the latest release tag, not unreleased branch-only churn.\n4. Summarize changes in 1–3 short sentences using the top five paths and stats from the committed, staged, and unstaged diffs. Explicitly call out untracked files because `--stat` does not include them. Use commit messages as supporting context, not as a substitute for inspecting the committed diff.\n5. Choose the lead verb for the description: feature → `adds`, bug fix → `fixes`, refactor/perf → `improves` or `updates`, docs-only → `updates`.\n6. Provide a specific topic branch for the contributor's work. Pull requests must not be prepared from `main` or a fork's `main`.\n   - If already off `main`, keep the current branch name and report it as the branch to use.\n   - If on `main`, propose `feat/<slug>`, `fix/<slug>`, or `docs/<slug>` based on the primary area (for example `docs/pr-draft-summary-guidance`) and show a `git checkout -b <branch>` command.\n7. If the current branch matches `issue-<number>` (digits only), keep that branch suggestion. When an issue number is present, reference `https://github.com/redis/ioredis/issues/<number>` and include an auto-closing line such as `This pull request resolves #<number>.` Do not block if the issue cannot be fetched.\n8. Draft the PR title and description using the template below. Use Conventional Commits prefixes for the title (`feat:`, `fix:`, `docs:`, `chore:`, etc.).\n9. Output only the block in \"Output Format\". Keep any surrounding status note minimal and in English. Do not include company-internal references (e.g. Jira/Confluence IDs) in the branch name, title, or description.\n\n## Output Format\n\nWhen closing out a task, add this concise Markdown block (English only) after any brief status note unless the task falls under the documented skip cases or the user says they do not want it.\n\n```\n# Pull Request Draft\n\n## Branch name suggestion\n\n<Either `Current branch: <existing-topic-branch>` when already off `main`, or `git checkout -b <new-topic-branch>` when currently on `main`. Never suggest using `main` as the pull request branch.>\n\n## Title\n\n<single-line imperative title, which can be a commit message; a Conventional Commits prefix such as feat:, fix:, or docs: is preferred>\n\n## Description\n\n<include what you changed plus a draft pull request title and description for your local changes; start the description with prose such as \"This pull request resolves/updates/adds ...\" using a verb that matches the change (you can use bullets later), explain the change background (for bugs, clearly describe the bug, symptoms, or repro; for features, what is needed and why), any behavior changes or considerations to be aware of, and you do not need to mention any tests you ran.>\n```\n\nKeep it tight—no redundant prose around the block, and avoid repeating details between `Changes` and the description. Tests do not need to be listed unless specifically requested.\n","frontmatter":{"name":"pr-draft-summary","description":"Create the required PR-ready summary block, branch suggestion, title, and draft description for ioredis. Must be used before the final response whenever the actual task diff includes runtime code, tests, examples, build/test configuration, or docs with behavior impact, regardless of perceived change size. Skip only when no eligible files changed, every change is repo-meta or docs-only without behavior impact, the task is conversation-only, or the user explicitly opts out."},"isInternal":false,"tokens":1413,"sizeBytes":6117},{"name":"error-cases.md","path":".agents/skills/runtime-behavior-probe/references/error-cases.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/runtime-behavior-probe/references/error-cases.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Common Error Cases\n\nUse this reference to expand beyond the happy path. Favor error cases that a real user or operator is likely to hit.\n\n## Configuration Errors\n\nCheck whether the runtime behaves differently for:\n\n- Missing required environment variables.\n- Present but malformed secrets or identifiers.\n- Wrong endpoint or base URL.\n- Wrong model or deployment name.\n- Incompatible local dependency versions.\n\nLook for:\n\n- Error type and status code.\n- Whether the failure is immediate or delayed.\n- Whether the message is actionable.\n- Whether retrying without fixing configuration changes anything.\n\n## Input Errors\n\nProbe common bad-input patterns such as:\n\n- Missing required fields.\n- Wrong data type.\n- Unsupported enum or option value.\n- Empty but syntactically valid input.\n- Oversized input or too many items.\n- Mutually incompatible options.\n\nPrefer realistic invalid inputs over artificial nonsense. The point is to learn how the runtime fails in practice.\n\n## Transport and Availability Errors\n\nWhen networked services are involved, consider:\n\n- Connection failure.\n- Read timeout.\n- Server timeout or upstream gateway error.\n- Rate limit response.\n- Partial stream interruption.\n- Reusing a connection after a failure.\n\nCapture whether the client library retries automatically, whether it surfaces retry metadata, and whether the final exception preserves the original cause.\n\n## State and Repetition Errors\n\nMany surprising bugs appear only when an operation is repeated or interrupted:\n\n- Re-submit the same request.\n- Repeat after a timeout.\n- Retry after a partial tool call or partial stream.\n- Resume after local cleanup or process restart.\n- Repeat with slightly changed inputs while reusing shared state.\n\nObserve whether the operation is idempotent, duplicated, silently ignored, or left in a partial state.\n\n## Concurrency Errors\n\nWhen shared state, ordering, or isolation may matter, consider:\n\n- Two overlapping requests with the same logical input.\n- Parallel runs that reuse the same cache key, session, container, or temporary resource.\n- Concurrent retries, cancellation, or cleanup racing with active work.\n- Output or event streams from one run leaking into another.\n\nCapture whether the runtime serializes, rejects, duplicates, corrupts, or cross-contaminates the work.\n\n## Investigation Heuristics\n\nUse these heuristics to pick error cases quickly:\n\n- Ask which failure a real engineer would debug first in production.\n- Ask which failure is most expensive if it is misunderstood.\n- Ask which failure would be invisible from code review alone.\n- Ask which failure path is likely to differ across environments.\n\nIf the error behavior is already perfectly obvious from a local validator or type system, it is usually low priority for this skill.\n","isInternal":false,"tokens":532,"sizeBytes":2781},{"name":"redis-runtime-patterns.md","path":".agents/skills/runtime-behavior-probe/references/redis-runtime-patterns.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/runtime-behavior-probe/references/redis-runtime-patterns.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Redis Runtime Patterns\n\nUse this reference for recurring ioredis investigations so you do not have to rediscover the probe strategy each time. Treat the repository source as the truth for client behavior, and use [redis.io/commands](https://redis.io/commands) to confirm contract-sensitive details such as argument order, reply types, and version availability. If you rely on the website rather than source, say so in the report.\n\n## General Rules\n\n- Prefer small, focused probes over large harnesses. Keep one script focused on one uncertainty.\n- For comparative or benchmark-like questions, start with a pilot and expand only when the answer is still unclear.\n- Capture the request shape (command and arguments as sent) and the observed command result or emitted event payload.\n- Preserve raw error type, message, and any Redis error prefix such as `WRONGTYPE`, `MOVED`, `ASK`, `CROSSSLOT`, `NOSCRIPT`, or `LOADING`.\n- Record whether behavior differs between the first call and a repeated call, and across a reconnect.\n- When the question is about regression or contract drift, add a known-good control run before attributing the result to the change under investigation.\n- Keep comparison parity explicit. Record what was held constant, what variable changed, and whether reply-shape or encoding differences could bias the conclusion.\n- Record the runtime context that actually changes Redis client behavior: server mode (standalone, cluster, sentinel), RESP version (2 vs 3), server version, and whether a feature such as auto-pipelining or sharded pub/sub is in use.\n\n## Connection Environment Variables\n\nDo not read these variables automatically. Before a live probe uses any of them, tell the user the exact variable names you plan to read and why each one is needed, then wait for explicit approval. Never print their values:\n\n- `REDIS_URL`\n- `REDIS_PASSWORD`\n- `REDIS_TLS_CA`, `REDIS_TLS_CERT`, `REDIS_TLS_KEY` (and any other `REDIS_TLS_*` the probe needs)\n\nFor most local probes you do not need any of these. ioredis repository instructions assume a Redis server with the correct version is running on the default host and port. Prefer that local Redis server over a live remote service unless the question is specifically about the remote deployment.\n\nIf the task targets another integration, use that integration's expected default variable names under the same rule.\n\n## Environment False Signals\n\nBefore attributing a failure to the patch or client code under review, exclude source-selection and environment problems with a controlled comparison.\n\n- Confirm the commit, worktree, working directory, Node executable/version, and imported module path. A probe of stale `built`, another checkout, `/tmp/node_modules`, or an installed `ioredis` package does not prove current `lib` behavior.\n- Rebuild when emitted declarations, package exports, generated command typings, or `built` is the subject. Otherwise prefer current-source `lib/` imports so stale build output cannot create a false result.\n- Confirm a Redis server is actually running and reachable. A connection refused or timeout against a missing Docker/Redis container is an environment condition, not a client defect, until a controlled rerun against a known-good server ties it to the code.\n- Confirm the RESP version the client negotiated. A reply-shape surprise is often just RESP2 vs RESP3, not a bug.\n- Confirm server mode matches the probe assumptions. Running a cluster-only expectation against a standalone server, or the reverse, produces misleading routing and slot errors.\n- Run base and head controls with the same Node version, dependency graph, server mode, RESP version, environment-variable names, and command shape. Record intentional differences.\n- Treat sandbox denials, unavailable Docker infrastructure, expired remote sessions, authentication, quota, rate limits, service outages, and stale caches as environment conditions until a controlled rerun ties them to the patch.\n- Never print credentials, connection URLs with embedded passwords, or TLS key material. Change only the minimum in-scope environment or disposable state needed for the control and record variable names rather than values.\n\nIn the final report, distinguish code failures, unsupported configurations, environment blockers, and inconclusive probes. Do not collapse them into one failed-test count.\n\n## ioredis Probe Patterns\n\nStart from the uncertainty instead of from the full client surface. The patterns below cover the runtime questions that recur most often in ioredis.\n\n### RESP2 vs RESP3 reply shapes\n\nUse when the uncertainty is what a command returns at runtime.\n\n- Run the same command under RESP2 and RESP3 as separate cases when protocol differences are part of the uncertainty.\n- Capture the observed command result and whether the client returns plain objects, `Map`, arrays, `null`, buffers, strings, or numbers.\n- Watch precision-sensitive numeric replies and record the exact value.\n\n### Single-node vs cluster vs sentinel\n\nUse when key routing, slot ownership, or topology matters.\n\n- For cluster, capture which node served the command and whether a `MOVED` or `ASK` redirect occurred. Probe multi-key commands across keys in different slots to observe `CROSSSLOT` behavior and any client-side slot checks.\n- Use hash tags (`{tag}`) to force keys into the same slot when the probe needs a multi-key command to succeed.\n- For sentinel, capture master discovery and what happens on a simulated failover.\n- Keep mode constant within a case. A standalone control alongside a cluster case is a useful comparison, not a substitute.\n\n### Pub/sub and sharded pub/sub\n\nUse when delivery semantics or resubscription matter.\n\n- Capture subscribe confirmation, message delivery order, emitted event names, and whether messages are delivered to pattern (`PSUBSCRIBE`) and channel subscribers as expected.\n- For sharded pub/sub (`SSUBSCRIBE` and `SPUBLISH`) in cluster, capture which shard delivered the message.\n- Force a reconnect and observe whether the client resubscribes to channels and patterns automatically. This is a common drift point.\n\n### Reconnection, retry, and the offline command queue\n\nUse when the question is about resilience.\n\n- Simulate a dropped connection (stop or restart the container, or close the socket) and capture: whether commands issued while offline are queued, the order they flush in on reconnect, and whether the reconnect strategy backoff behaves as configured.\n- Distinguish commands rejected immediately from commands queued and later resolved or rejected.\n- Capture whether in-flight commands at disconnect are retried, rejected, or hang.\n\n### Pipelining and MULTI/EXEC transactions\n\nUse when batching or atomicity is under test.\n\n- For pipelining, confirm replies map back to the right commands in order, including when one command in the batch errors.\n- For `MULTI`/`EXEC`, capture queueing errors versus execution errors, behavior on `DISCARD`, and `WATCH` optimistic-locking aborts (`EXEC` returning `null`).\n\n### RESP3 push messages and subscribed connection behavior\n\nUse when push-message routing or subscribed connection behavior matters.\n\n- Requires RESP3 when the question depends on push-message behavior. Capture whether push replies are routed to events, whether regular commands are allowed while subscribed, and whether replies preserve expected buffer/string variants.\n- Probe RESP2 and RESP3 separately when subscribed-mode command behavior or push reply shape is part of the uncertainty.\n\n### Blocking commands and connection isolation\n\nUse for `BLPOP`, `BRPOP`, `XREAD BLOCK`, `WAIT`, and similar.\n\n- Capture whether the blocking command monopolizes a connection and whether the caller needs a separate Redis instance so other commands are not stalled.\n- Probe timeout behavior and what resolves when the block is satisfied by another client versus when it times out.\n\n### Auto-pipelining and command queues\n\nUse when same-tick batching, offline queue behavior, or command queue ordering is involved.\n\n- Capture which commands are batched, whether disabled commands bypass auto-pipelining, and whether reply order matches command order.\n- For reconnect-sensitive questions, distinguish offline queue entries, in-flight commands, and commands rejected because the connection state does not allow queuing.\n\n### SCAN iterators\n\nUse for `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`.\n\n- Capture cursor progression, whether the async iterator terminates, and whether `COUNT` and `MATCH` behave as expected. Note that SCAN gives no count or completeness guarantees mid-iteration.\n\n### Large payloads and timeouts\n\nUse when size or latency is the concern.\n\n- Capture behavior with large values and large reply sets, and whether command-level or socket timeouts fire as configured.\n- For repeat-sensitive latency, use warm-up plus repeat-N and record medians, not a single sample.\n\n## What to Capture\n\nFor ioredis probes, try to record:\n\n- The command and arguments as sent, plus the observed result or emitted event payload.\n- The JavaScript value and its type, including buffer variants when relevant.\n- Server mode (standalone, cluster, or sentinel), negotiated RESP version, and server version.\n- Whether fields are absent, `null`, empty, or transformed by the client.\n- Raw error type, message, and any Redis error prefix for failures.\n- Reconnect and retry behavior, offline-queue flush order, and resubscription on reconnect when relevant.\n- For cluster, which node served the command and any redirect.\n- Which environment-variable names were approved for the probe when a live or credentialed server was required.\n\nDo not spend time rediscovering static documentation unless the runtime result seems to contradict what you expected. The value of this skill is in the observed behavior.\n","isInternal":false,"tokens":1946,"sizeBytes":9812},{"name":"repo-import-patterns.md","path":".agents/skills/runtime-behavior-probe/references/repo-import-patterns.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/runtime-behavior-probe/references/repo-import-patterns.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Repository Import Patterns\n\nUse this reference when a temporary probe script outside the repository needs to load code from the current branch.\n\n## Why This Exists\n\nWhen you run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/probe.ts` from the repository root, `ts-node` itself comes from this repository, but the probe file still lives under `/tmp`. Bare imports such as `ioredis` can resolve as if the script were its own package. That is often not what you want for \"what does the current branch do right now?\" investigations.\n\nThe safe default is to build an absolute path from `process.cwd()`, which should be the repository root, and a repository-relative path.\n\n## Default Rule\n\n- Use `lib/` imports when the question is about current-branch behavior.\n- Use `built/` imports when the question is about packaged output after a build.\n- Avoid bare package imports from `/tmp` unless the probe is explicitly testing published package resolution rather than branch-local source behavior.\n\n## Quick Typecheck Loop\n\nFor disposable probes in `ioredis`, the default loop should stay outside the repository and avoid a full package build:\n\n1. Create a temporary directory with `mktemp -d`.\n2. Write `probe.ts` there.\n3. Write a sibling `tsconfig.json` that extends the repository's `tsconfig.json`.\n4. From the repository root, run `npx tsc --noEmit -p /tmp/.../tsconfig.json`.\n5. If that passes, run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/.../probe.ts`.\n\nExample temporary `tsconfig.json`:\n\n```json\n{\n  \"extends\": \"/absolute/path/to/ioredis/tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"types\": [\"node\"],\n    \"typeRoots\": [\"/absolute/path/to/ioredis/node_modules/@types\"]\n  },\n  \"include\": [\"./probe.ts\"]\n}\n```\n\nThis keeps TypeScript module resolution and strictness close to the repository defaults while limiting the check surface to the disposable probe file.\n\nDo not convert this default loop into a checked-in benchmark, example, or package script unless the user explicitly asks for a reusable repository artifact.\n\n## Recommended Helper\n\nThe disposable TypeScript scaffold exposes:\n\n    const module = await importRepoModule(\"lib/index.ts\");\n\nInternally, the helper should be equivalent to:\n\n    import { createRequire } from \"module\";\n    import { resolve } from \"path\";\n\n    const repoRequire = createRequire(resolve(process.cwd(), \"package.json\"));\n\n    async function importRepoModule(repoRelativePath: string) {\n      const absolutePath = resolve(process.cwd(), repoRelativePath);\n      return Promise.resolve(repoRequire(absolutePath));\n    }\n\nThis keeps the import anchored to the current checkout instead of the temporary script location.\n\n## Choosing `lib/` Versus `built/`\n\nUse `lib/` when:\n\n- You are validating a bug fix or regression on the current branch.\n- You want to know how the repository behaves before packaging.\n- The question is about implementation details or internal helper behavior.\n\nUse `built/` when:\n\n- The question is specifically about what consumers load after `npm run build`.\n- You need to validate export maps or emitted `.js` and `.d.ts` output.\n- The bug only reproduces in generated output.\n\nIf the probe uses `built/`, record whether you ran a fresh build first. A stale `built/` directory can create false positives or false negatives.\n\nDo not run `npm run build` only to typecheck or execute a `lib/`-based disposable probe. The fast path is temp `tsconfig` plus `npx tsc --noEmit`, then `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register`.\n\n## Simple Smoke Targets\n\nWhen you only need to prove the helper works, start with a simple target that has minimal side effects, for example:\n\n- `lib/index.ts`\n- `lib/Redis.ts`\n- `lib/Command.ts`\n- another file with obvious exported symbols and no environment requirement\n\nIf a chosen file pulls in more of the repo than expected, switch to a simpler target rather than weakening the import guidance.\n\n## What To Record\n\nWhen a probe imports repo code, report:\n\n- The repo-relative path you imported.\n- Whether it came from `lib/` or `built/`.\n- The repository root used by `process.cwd()`.\n- Any prerequisite step such as `npm run build`.\n","isInternal":false,"tokens":934,"sizeBytes":4185},{"name":"reporting-format.md","path":".agents/skills/runtime-behavior-probe/references/reporting-format.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/runtime-behavior-probe/references/reporting-format.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Reporting Format\n\nLead with findings, not process. The user asked for investigation results, so the answer should start with the most important observed behaviors. Put the real news first.\n\n## Recommended Order\n\n1. Findings.\n2. Validation approach.\n3. Case matrix or condensed case summary.\n4. Artifact status and brief run summary.\n5. Optional implementation note.\n\n## Findings Section\n\nMake each finding answer one user-relevant question. Good findings usually include:\n\n- What was observed.\n- Why it matters.\n- The condition under which it happens.\n- What was held constant when the finding comes from a comparison probe.\n- `scope`: The boundary of the finding, such as commit, model, Node version, live versus local, or repeat mode.\n- `confidence`: `high`, `medium`, or `low`.\n\nAvoid burying the main result under setup details.\n\nPut `unexpected` or `negative` findings first. If there were no unexpected or negative findings in the executed cases, say that explicitly before the rest of the findings section.\n\nIf the probe was comparative, say whether the result supports:\n\n- Pattern parity only.\n- A broader quality claim.\n\nDo not imply a broader quality equivalence than the executed cases justify.\n\n## Validation Approach Section\n\nSummarize:\n\n- The runtime surface you exercised.\n- The shape of the probe code, in overview only.\n- Which categories of cases you covered.\n- Which execution modes you used, including repeat counts or warm-up handling when relevant.\n- Whether live credentials or external services were used.\n- Any important state controls such as fresh state, cache reuse, cache busting, unique IDs, or cleanup verification.\n- For comparison probes, what was held constant, what was varied, and whether output-shape or usage differences could still influence the conclusion.\n- Whether the usual docs path or an official-docs fallback was used for contract-sensitive checks.\n\nKeep this concise. The user needs enough detail to trust the result, not a line-by-line replay of the script.\n\n## Case Summary\n\nInclude either the full matrix or a condensed summary. At minimum, show:\n\n- Which scenarios were executed.\n- Whether the run was a quick pilot, an expanded matrix, or both.\n- Which ones produced `unexpected` or `negative` results.\n- Which ones passed or failed when a real comparison basis existed.\n- Which cases were blocked.\n- Where the supporting evidence lived, or that it was deleted.\n\nIf the matrix is large, show the highest-value cases in the main response and keep the rest as a compact appendix or note.\n\n## Artifact Status And Brief Run Summary\n\nState one of these explicitly:\n\n- Temporary artifacts were kept until the final response was drafted, then deleted after validation.\n- Temporary artifacts were kept at `<path>` because the user asked to keep them.\n- Temporary artifacts were kept at `<path>` because they are needed for follow-up analysis.\n\nEven if artifacts were deleted, retain a short run summary such as:\n\n- Probe command or runner shape.\n- Runtime context summary such as commit, Node executable, Node version, or model.\n- Artifact path and final status.\n\nFor benchmark or repeat-heavy probes, keeping artifacts for follow-up is often the right default even when the immediate report is done.\n\n## Optional Implementation Note\n\nInclude this only when one clear defect was isolated and a short implementation hypothesis or minimal repro direction would help. Keep it brief. Do not turn the report into a broader next-step plan unless the user asked for that.\n\n## Compact Template\n\nUse this outline when you need a fast structure:\n\n    Findings:\n    - <finding 1>\n      held constant: <prompt/tool/state settings kept the same, if comparative>\n      scope: <commit/model/node/live-local/repeat-mode>\n      confidence: <high|medium|low>\n    - <finding 2>\n      held constant: <prompt/tool/state settings kept the same, if comparative>\n      scope: <commit/model/node/live-local/repeat-mode>\n      confidence: <high|medium|low>\n\n    Validation approach:\n    - Surface: <what was exercised>\n    - Probe code: <brief overview>\n    - Coverage: <success, edge, error, repeat-sensitive, and quality categories>\n    - Execution modes: <single-shot|repeat-N|warm-up + repeat-N>\n    - Comparison parity: <what was held constant and what varied, if comparative>\n    - Docs source: <MCP or official-docs fallback, if relevant>\n\n    Case summary:\n    | case_id | scenario | result_flag | status | note |\n    | --- | --- | --- | --- | --- |\n    | S1 | ... | expected | pass | ... |\n    | E1 | ... | negative | fail | ... |\n\n    Artifact status and brief run summary:\n    - Temporary artifacts were kept until the final response was drafted, then deleted.\n    - Summary: <command/runtime-context/artifact-status summary>\n\n    Optional implementation note:\n    - <brief hypothesis or minimal repro direction>\n\nAdjust the format to the task, but preserve the ordering.\n","isInternal":false,"tokens":1024,"sizeBytes":4904},{"name":"validation-matrix.md","path":".agents/skills/runtime-behavior-probe/references/validation-matrix.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/runtime-behavior-probe/references/validation-matrix.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# Validation Matrix\n\nUse the matrix to decide what to probe before writing scripts. The goal is not exhaustive combinatorics; the goal is high-value coverage that is visible, explainable, and likely to reveal runtime surprises. The matrix should make the real news easy to scan.\n\n## Minimum Columns\n\nUse these columns unless the task clearly needs more:\n\n- `case_id`: Stable identifier such as `S1`, `E3`, or `R2`.\n- `scenario`: Short description of the behavior under test.\n- `mode`: `single-shot`, `repeat-N`, or `warm-up + repeat-N`.\n- `question`: The concrete runtime uncertainty this case is answering.\n- `setup`: Inputs, environment, or preconditions required for the case.\n- `observation_summary`: A compact summary of what actually happened.\n- `result_flag`: `unexpected`, `negative`, `expected`, or `blocked`.\n- `evidence`: Path, log reference, or `deleted`.\n\nAdd these columns when they materially improve the investigation:\n\n- `comparison_basis`: The baseline, docs, or prior behavior you are comparing against.\n- `variable_under_test`: The single factor that is intentionally changing in a comparison case.\n- `held_constant`: Prompt shape, tool setup, model settings, or state rules that were intentionally kept the same.\n- `output_constraint`: Any schema, length, or response-shape constraint used to keep the comparison fair.\n- `status`: Use `pass`, `fail`, `unexpected-pass`, `unexpected-fail`, or `blocked` only when there is a credible comparison basis or control.\n- `confidence`: `high`, `medium`, or `low`.\n- `state_setup`: Fresh or reused state, cache strategy, unique IDs, and cleanup checks.\n- `repeats`: Number of measured runs.\n- `warm_up`: Whether a warm-up run was used and why.\n- `variance`: Any useful spread or instability note across repeated runs.\n- `usage_note`: Token, usage, or output-length note when it materially affects interpretation.\n- `control`: Known-good comparison point for regression or behavior-change questions.\n- `risk_profile`: `read-only`, `mutating`, or `costly` for live probes.\n- `env_vars`: Exact environment-variable names the case plans to read.\n- `approval`: `not-needed`, `pending`, or `approved` for cases that need user permission before execution.\n\nUse `result_flag` as the fast scan field. It is what makes unexpected or negative findings jump out before the reader studies the full report.\n\nUse `status` only when you have a real comparison basis. If the case is exploratory and there is no trustworthy baseline, prefer a strong `observation_summary` plus `result_flag` and `confidence` instead of pretending the result is a clean pass or fail.\n\n## Choosing Execution Mode\n\nPick an execution mode before you run the case:\n\n- Use `single-shot` for deterministic, one-run checks.\n- Use `repeat-N` automatically when the question involves cache behavior, retries, streaming, interruptions, rate limiting, concurrency, or other run-to-run-sensitive behavior.\n- Use `warm-up + repeat-N` when the first run is likely to include cold-start effects such as container provisioning, import caches, or prompt-cache population.\n\nUse these defaults unless the task clearly needs something else:\n\n- `repeat-3` for a quick screen of a repeat-sensitive question.\n- `warm-up + repeat-10` for decision-grade latency comparisons or release-facing recommendations.\n- For costly live probes, start at `repeat-3`, then expand only if the answer is still unclear.\n\nIf it is genuinely unclear whether extra runs are worth the time or cost, ask the user before expanding the probe.\n\n## Phase The Matrix\n\nWhen the question is comparative or benchmark-like, do not jump straight to the largest matrix.\n\nStart with a pilot:\n\n- One control.\n- One or two highest-signal success cases.\n- The smallest repeat count that can disqualify a weak candidate quickly.\n\nExpand only when:\n\n- The candidate survives the pilot.\n- The results are close enough that more samples matter.\n- A major runtime surface is still uncovered.\n- The user explicitly wants decision-grade evidence.\n\n## Coverage Categories\n\nTry to cover at least one case from each relevant category:\n\n- `success`: Normal behavior that should work.\n- `control`: Known-good comparison such as `origin/master`, the latest release, or the same request without the suspected option.\n- `boundary`: Size, count, or parameter limits near a plausible edge.\n- `invalid`: Bad inputs or unsupported combinations.\n- `misconfig`: Missing key, wrong endpoint, bad permissions, or incompatible local setup.\n- `transient`: Timeout, temporary server issue, network breakage, or rate limiting.\n- `recovery`: Retry behavior, partial completion, duplicate submission, or cleanup.\n- `concurrency`: Overlapping operations when shared state, ordering, or isolation may matter.\n- `quality`: A harder or more open-ended sample when the user is asking about model intelligence, not just workflow parity.\n\nIf time is limited, prioritize categories in this order:\n\n1. Known-good control when the question implies regression or drift.\n2. Highest-risk success case.\n3. Most plausible user-facing failure.\n4. Most likely edge case with ambiguous behavior.\n5. Cleanup or retry semantics.\n6. Lower-probability extremes.\n\n## Matrix Template\n\nUse this compact template:\n\n    | case_id | scenario | mode | question | setup | state_setup | variable_under_test | held_constant | comparison_basis | observation_summary | result_flag | status | evidence |\n    | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n    | K1 | Known-good control | single-shot | Does the baseline still show the expected behavior? | Same probe against baseline target | Fresh state | none | current probe shape | `origin/master` or latest release | pending | pending | pending | pending |\n    | S1 | Baseline success | single-shot | What does the normal success path look like at runtime? | Valid config and representative input | Fresh state | none | representative input and setup | current docs or local expectation | pending | pending | pending | pending |\n    | R1 | Cache or retry behavior | warm-up + repeat-N | Does behavior change after the first run or across retries? | Same request repeated under controlled settings | Cache key or retry setup recorded | reuse versus fresh state | prompt shape and tool setup | same request without reuse, or docs if available | pending | pending | pending | pending |\n    | C1 | Model comparison pilot | warm-up + repeat-N | Does candidate B preserve the covered behavior while improving latency? | Same scenario across two models | Fresh state and stable IDs | model name | prompt shape, tool choice, and model settings parity | control model in the same probe | pending | pending | pending | pending |\n    | E1 | Invalid input | single-shot | How does the runtime reject a realistic bad input? | Missing required field | Fresh state | invalid field value | same request with valid field | same request with valid field | pending | pending | pending | pending |\n    | X1 | Concurrent overlap | repeat-N | Do overlapping runs interfere with each other? | Two or more overlapping operations | Unique IDs plus cleanup verification | overlap timing | same logical input | same request serialized, if available | pending | pending | pending | pending |\n\n## Recording Results\n\nKeep `question` unchanged after execution. Put the actual behavior in `observation_summary`, then mark the scan-friendly `result_flag`.\n\nUse these `result_flag` values consistently:\n\n- `unexpected`: The result diverged from the best current understanding in a surprising way.\n- `negative`: The result exposed a user-relevant failure, risk, or sharp edge.\n- `expected`: The result matched the current understanding and did not reveal new risk.\n- `blocked`: The case did not produce a trustworthy observation.\n\nOnly fill `status` when there is a credible comparison basis. Otherwise use `observation_summary`, `result_flag`, and `confidence` to communicate what was learned without over-claiming certainty.\n\nFor comparison cases, use `observation_summary` and the final report to say whether the evidence supports pattern parity only or a broader quality claim.\n\nIf a case reveals a new branch of behavior, add a follow-up case instead of overloading the original one.\n\n## Evidence Discipline\n\nTreat a case as incomplete when:\n\n- The observed output omits the key result you were testing.\n- The script mixed multiple questions and the result is ambiguous.\n- Hidden state, cache behavior, or previous runs may have influenced the result and were not controlled or documented.\n- The question is whether behavior changed, but the case has no credible control or baseline to compare against.\n- The case plans to read environment variables, but the exact variable names were not approved by the user before execution.\n- The case was repeat-sensitive, but it ran only once without a clear rationale.\n\nWhen this happens, narrow the probe and rerun. A smaller script with a cleaner result is better than a more complicated script that is hard to trust.\n","isInternal":false,"tokens":1874,"sizeBytes":9018},{"name":"SKILL.md","path":".agents/skills/runtime-behavior-probe/SKILL.md","rawUrl":"https://raw.githubusercontent.com/redis/ioredis/HEAD/.agents/skills/runtime-behavior-probe/SKILL.md","title":"runtime-behavior-probe","category":"anthropic-skill","format":"markdown","content":"---\nname: runtime-behavior-probe\ndescription: Plan and execute runtime-behavior investigations with temporary TypeScript probe scripts, validation matrices, state controls, and findings-first reports. Use only when the user explicitly invokes this skill to verify actual runtime behavior beyond normal code-level checks, especially to uncover edge cases, undocumented behavior, or common failure modes in local or live integrations. A baseline smoke check is fine as an entry point, but do not stop at happy-path confirmation.\n---\n\n# Runtime Behavior Probe\n\n## Overview\n\nUse this skill to investigate real runtime behavior, not to restate code or documentation. Start by planning the investigation, then execute a case matrix, record observed behavior, and report both the findings and the method used to obtain them.\n\n## Core Rules\n\n- Treat this skill as manual-only. Do not rely on implicit invocation.\n- For `ioredis`, treat this skill as a disposable-probe workflow, not a repository implementation workflow.\n- Unless the user explicitly asks for a reusable repository artifact, the allowed write scope is limited to:\n  - a temporary directory used for probe scripts or artifacts\n  - `.agents/skills/runtime-behavior-probe/**` when the user is editing this skill itself\n- For disposable probes in `ioredis`, do not modify `examples/**`, `lib/**`, `test/**`, any `package.json`, `README.md`, build config, or generated files unless the user explicitly asks for a reusable repository artifact or implementation change.\n- If your draft plan would touch a disallowed path, stop and rewrite the plan before editing anything.\n- A baseline success or smoke case is often the right entry point, but do not stop there when the real question involves edge cases, drift, or failure behavior.\n- Plan before running anything. Write the case matrix first, then fill it in with observed results. The matrix can live in a scratch note, a temporary file, or the probe script header.\n- Default to local or read-only probes. Consider a live service only when it is clearly relevant, then apply the lightweight gates below before you run it.\n- Size the probe to the decision. Start with the smallest matrix that can disqualify or validate the current hypothesis, then expand only when uncertainty remains.\n- Before a live probe, apply three lightweight gates:\n  - Destination gate. Use only a live destination that is clearly allowed for the task.\n  - Intent gate. Run the live probe only when the user explicitly wants runtime verification on that integration, or explicitly approves it after you propose the probe.\n  - Data gate. If the probe will read environment variables, mutate remote state, incur material cost, or exercise non-public or user data, name the exact variable names or data class and get explicit approval first.\n- Classify each case as read-only, mutating, or costly before execution. For mutating or costly cases, or for any live case that will read environment variables, define cleanup or rollback before running the probe.\n- Use temporary files or a temporary directory for one-off probe scripts.\n- In `ioredis`, use disposable probe files outside git-tracked paths by default. Do not add one-off probes, harnesses, benchmarks, or examples under `examples/`, `lib/`, `test/`, or other repository directories unless the user explicitly asks for a checked-in artifact.\n- Keep temporary artifacts until the final response is drafted. Then delete them by default unless the user asked to keep them or they are needed for follow-up. Even when artifacts are deleted, keep a short run summary of the command shape, runtime context, and artifact status in the report.\n- Before executing a live probe that will read environment variables, tell the user the exact variable names you plan to use and why, then wait for explicit approval. Examples include `REDIS_URL`, `REDIS_PASSWORD`, and other expected default names for the system under test.\n- Never print secrets, even when they come from standard environment variables that this skill may use.\n- For Redis command or server semantics, treat the repository source as the truth and use [redis.io/commands](https://redis.io/commands) to confirm contract-sensitive details such as argument order, reply types, and version availability. Use runtime probing to validate or challenge the documented behavior, not to skip the documentation pass entirely. If you rely on the website rather than source, say so in the report.\n- For benchmark or comparison probes, make parity explicit before execution. Record what is held constant, what variable is under test, which reply-shape constraints keep the comparison fair, and any counters or timings that matter for interpreting latency or cost.\n- In `ioredis`, default to a light local loop for probe authoring: temporary `probe.ts` plus temporary `tsconfig.json`, `npx tsc --noEmit -p <tmp-tsconfig>`, then `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register <tmp-probe>`. Escalate to `npm run build` only when the runtime question is specifically about `built/`, emitted declarations, or packaged output.\n- In `ioredis`, do not treat a request for runtime verification, benchmarking, or comparison as permission to add a reusable example, benchmark harness, package script, or checked-in sample. Those repository changes require explicit user intent.\n- For probes that need a running Redis, remove setup ambiguity before attributing a negative result to client behavior:\n  - Confirm the server is reachable and note its mode (standalone, cluster, or sentinel) and RESP version before interpreting reply shapes.\n  - Treat RESP2 and RESP3 as separate cases, not interchangeable setup details, when the question is about reply shapes or push messages.\n  - Clear unsupported server-version or command options first so they do not invalidate the probe. Assume a Redis server with the correct version is running on the default host and port unless the task says otherwise; if sandbox access is blocked, ask for permission to access Redis instead of treating Redis as unavailable.\n\n## Workflow\n\n1. Restate the investigation target in operational terms. Name the runtime surface, the key uncertainty, and the highest-risk behaviors to test.\n2. For `ioredis`, declare the allowed write scope before you do any implementation work. For a normal disposable probe, that means a temporary directory only.\n3. Do a short preflight. Check the relevant code or docs first, decide whether the question needs local or live validation, and note any repo, baseline, or release boundary that matters.\n4. Create a validation matrix before executing probes. Cover both baseline behavior and the most relevant failure or drift cases. The matrix can live in a scratch note, a temporary file, or a structured header inside the probe script.\n5. For each case, choose an execution mode up front:\n   - `single-shot` for deterministic one-run checks.\n   - `repeat-N` for cache, retry, streaming, interruption, rate-limit, concurrency, or other run-to-run-sensitive behavior.\n   - `warm-up + repeat-N` when first-run cold-start effects could distort the result. Use these defaults unless the task clearly needs something else:\n   - Quick screen of a repeat-sensitive question: `repeat-3`.\n   - Decision-grade latency or release recommendation: `warm-up + repeat-10`.\n   - Costly live cases: start at `repeat-3`, then expand only if the answer remains unclear. If it is genuinely unclear whether extra runs are worth the time or cost, ask the user before expanding the probe.\n6. When the question is benchmark-like or comparative, run in phases. Start with a high-signal pilot matrix against a control, then expand only the surviving candidates or unresolved cases.\n7. If the question is about a suspected regression or behavior change, add at least one known-good control case such as `origin/master`, the latest release, or the same request without the suspected option.\n8. For comparative probes, define parity before execution. Record prompt or input shape, tool-choice setup, model-settings parity, state reuse rules, and any response-shape constraint that keeps the comparison fair. If materially different output length could bias the result, record usage or token notes too.\n9. If the question asks whether one option has the same intelligence or quality as another, decide whether the matrix supports only example-pattern parity or a broader quality claim. For broader claims, add at least one harder or more open-ended case. Otherwise say explicitly that the result is limited to the covered patterns.\n10. Plan state controls before execution when hidden state could affect the result. Record whether each case uses fresh or reused state, how cache reuse or cache busting is handled, what unique IDs isolate repeated runs, and how cleanup is verified.\n11. If any live case will read environment variables, list the exact variable names and purpose for each case, then ask the user for approval before execution. Keep the approval ask short and include destination, read-only versus mutating or costly risk, exact variable names, and cleanup or rollback if relevant.\n12. Build task-specific probe scripts in a temporary location. Keep the script small, observable, and easy to discard.\n13. If you are about to propose a checked-in script, example, benchmark, or package script for `ioredis`, stop and verify that the user explicitly asked for a reusable repository artifact. If not, keep the probe temporary.\n14. In `ioredis`, make the runtime context explicit:\n\n- Run TypeScript probes from the repository root with `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register <tmp-probe>` when practical.\n- For probe authoring, create both `probe.ts` and a sibling temporary `tsconfig.json` under `mktemp -d`, then run `npx tsc --noEmit -p <tmp-tsconfig>` before the first live execution.\n- Record the current commit, working directory, Node executable, Node version, and the package or source path you imported.\n- Avoid accidental imports from a different checkout or from `/tmp/node_modules`. If the probe needs repository code, import it from an absolute path resolved from `process.cwd()` and a repo-relative path.\n- Prefer current-branch `lib/` imports when the question is \"what does this branch do now?\" and prefer `built/` imports only when the question is specifically about packaged output after a build.\n- Do not run a repository-wide build just to typecheck a disposable probe. Reserve `npm run build` for `built/` probes or when emitted output is itself part of the question.\n\n15. Execute the matrix and capture evidence. Record request shape, setup, observation summary, unexpected or negative result, error details, timing, runtime context, approved environment-variable names, repeat counts, warm-up handling, variance when relevant, cleanup behavior, and for comparisons note what was held constant plus any response-shape or usage notes that affect interpretation.\n16. Update the matrix with actual outcomes, not guesses.\n17. Keep temporary artifacts until the final response is drafted. Then delete them unless the user asked to keep them or they are needed for follow-up. Benchmark and repeat-heavy probes often need follow-up, so keeping artifacts is normal when the result may be revisited. If deleted, retain and report a short run summary.\n18. Report findings first, with unexpected or negative findings first. Then summarize how the validation was performed and which cases were covered.\n19. If the probe isolates one clear defect, you may include a short implementation hypothesis or minimal repro direction. Do not expand into a larger next-step plan unless the user asked for it.\n\n## Validation Matrix\n\nUse a matrix that makes the news easy to scan. Start from the runtime question and the observation summary, not just from `expected` and `pass` or `fail`.\n\nUse a matrix with at least these columns:\n\n- `case_id`\n- `scenario`\n- `mode`\n- `question`\n- `setup`\n- `observation_summary`\n- `result_flag`\n- `evidence`\n\nAdd these columns when they materially improve the investigation:\n\n- `comparison_basis`\n- `variable_under_test`\n- `held_constant`\n- `output_constraint`\n- `status`\n- `confidence`\n- `state_setup`\n- `repeats`\n- `warm_up`\n- `variance`\n- `usage_note`\n- `risk_profile`\n- `env_vars`\n- `approval`\n- `control`\n\nTreat `result_flag` as a fast scan field such as `unexpected`, `negative`, `expected`, or `blocked`. Use `status` only when there is a credible comparison basis, baseline, or documented contract to compare against.\n\nAlways consider whether the matrix should include these categories:\n\n- Baseline success.\n- Control or baseline comparison when a regression is suspected.\n- Boundary input or parameter variation.\n- Invalid or unsupported input.\n- Missing or incorrect configuration.\n- Transient external failure such as timeout, network interruption, or rate limiting.\n- Retry, idempotence, or cleanup behavior.\n- Concurrency or overlapping operations when shared state or ordering may matter.\n- Open-ended quality or intelligence samples when the question is broader than pattern parity.\n\nOpen [validation-matrix.md](./references/validation-matrix.md) when you need a stronger prioritization model or a reusable case template.\n\n## Temporary Probe Scripts\n\nWrite one-off scripts in a temporary file or temporary directory such as one created by `mktemp -d`. Keep the script outside the repository by default, even when it imports code from the repository.\n\nFor `ioredis`, a disposable runtime probe should stay disposable. Do not add a package script, modify build config, or create a checked-in benchmark or example unless the user explicitly asks for a reusable repository artifact.\n\nFor `ioredis`, the default authoring loop should be:\n\n1. `tmpdir=$(mktemp -d)`\n2. Write `probe.ts` and `tsconfig.json` into `$tmpdir`\n3. From the repository root, run `npx tsc --noEmit -p \"$tmpdir/tsconfig.json\"`\n4. If the quick typecheck passes, run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register \"$tmpdir/probe.ts\"`\n5. Only run `npm run build` if the probe intentionally imports `built/` or validates packaged output\n\nUse a temporary `tsconfig.json` that extends the repository base settings but includes only the disposable probe, for example:\n\n```json\n{\n  \"extends\": \"/absolute/path/to/ioredis/tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"types\": [\"node\"],\n    \"typeRoots\": [\"/absolute/path/to/ioredis/node_modules/@types\"]\n  },\n  \"include\": [\"./probe.ts\"]\n}\n```\n\nIf the probe needs repository code:\n\n- Run it with the repository root as the working directory.\n- Use `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/probe.ts` from the repository root when practical.\n- Use `npx tsc --noEmit -p /tmp/probe-tsconfig.json` as the default quick typecheck step before executing the probe.\n- Import repository modules with an absolute path built from `process.cwd()` and a repo-relative path. Do not assume bare imports such as `ioredis` will resolve to the current checkout from `/tmp`.\n- Use `lib/` imports for current-branch behavior probes and `built/` imports for packaged-output probes.\n\nDesign the probe to maximize observability:\n\n- Print or log the exact scenario being exercised.\n- Capture runtime context such as git SHA, working directory, Node executable and version, relevant package versions, model or deployment name, endpoint or base URL alias, and any retry or tool options that materially affect behavior.\n- For live probes, record only the names of environment variables that were approved for use. Never print their values.\n- Capture structured outputs when possible.\n- Preserve raw error type, message, and status code.\n- For repeat-sensitive cases, capture the attempt index, warm-up status, and any stable identifiers that help compare runs.\n- For repeated or benchmark-style probes, write both raw results and a compact summary artifact when practical.\n- Keep branching minimal so each script answers a narrow question.\n\nBefore deleting the temporary script or directory, keep a short run summary of the script path, command used, runtime context, and whether the evidence was kept or deleted.\n\nOpen [typescript_probe.ts](./templates/typescript_probe.ts) when you want a lightweight disposable TypeScript probe scaffold. Open [repo-import-patterns.md](./references/repo-import-patterns.md) when you need to load current-branch workspace code from a temporary script.\n\n## Reporting\n\nReport in this order:\n\n1. Findings. Put unexpected or negative findings first. If there was no real news, say that explicitly.\n2. Validation approach. Summarize the code used, the runtime surface exercised, the execution modes, and the case matrix coverage.\n3. Case results. Include the matrix or a condensed version of it when the case count is large.\n4. Artifact status and brief run summary. State whether temporary artifacts were deleted or kept, and provide kept paths or the retained summary.\n5. Optional implementation note. Include this only when one clear defect was isolated and a short implementation direction would help.\n\nFor comparative probes, the report should also say what was held constant, what variable was under test, and whether the result supports only pattern parity or a broader quality claim.\n\nOpen [reporting-format.md](./references/reporting-format.md) for the recommended response template.\n\n## Resources\n\n- Open [validation-matrix.md](./references/validation-matrix.md) to design and prioritize the case matrix.\n- Open [error-cases.md](./references/error-cases.md) to expand common failure scenarios.\n- Open [redis-runtime-patterns.md](./references/redis-runtime-patterns.md) for recurring ioredis runtime probe patterns.\n- Open [repo-import-patterns.md](./references/repo-import-patterns.md) for repository-relative TypeScript import guidance.\n- Open [reporting-format.md](./references/reporting-format.md) for the final report structure.\n- Open [typescript_probe.ts](./templates/typescript_probe.ts) for a minimal disposable TypeScript probe scaffold.\n","frontmatter":{"name":"runtime-behavior-probe","description":"Plan and execute runtime-behavior investigations with temporary TypeScript probe scripts, validation matrices, state controls, and findings-first reports. Use only when the user explicitly invokes this skill to verify actual runtime behavior beyond normal code-level checks, especially to uncover edge cases, undocumented behavior, or common failure modes in local or live integrations. A baseline smoke check is fine as an entry point, but do not stop at happy-path confirmation."},"isInternal":false,"tokens":3725,"sizeBytes":18020}],"systemPromptSnippet":"<yakaai_skills repo=\"redis/ioredis\">\n<!-- File: AGENTS.md (Tokens: ~1490 | Category: root-instruction) -->\n# AGENTS.md\n\nThis file provides guidance to AI coding agents (Claude Code, Codex, Copilot, Cursor, Aider, etc.) when working with code in this repository.\n\n## Project Overview\n\nioredis is a full-featured Redis client for Node.js, written 100% in TypeScript. Source lives in `lib/`, compiles to CommonJS in `built/` (the published artifact), and supports standalone, Sentinel, and Cluster topologies.\n\n## Common Commands\n\n### Building\n\n```bash\nnpm run build          # Wipe built/ and compile TypeScript\nnode bin/index.js      # Regenerate lib/utils/RedisCommander.ts\n```\n\n### Linting and Formatting\n\n```bash\nnpm run lint           # Run ESLint over lib/\nnpm run format         # Format files with Prettier\nnpm run format-check   # Check formatting\n```\n\n### Testing\n\nFunctional and cluster tests require running Redis servers. Unit tests under `test/unit/` mock the network and do not need a server.\n\nTo start and stop local Redis test infrastructure:\n\n```bash\nnpm run docker:setup      # Start standalone Redis on 6379 and cluster nodes on 3000-3005\nnpm run docker:teardown   # Stop test Redis servers\n```\n\n```bash\nnpm test                  # Default non-cluster test: test:js then test:tsd\nnpm run test:js           # Mocha over test/helpers, test/unit, test/functional\nnpm run test:cluster      # Mocha over test/cluster\nnpm run test:tsd          # Build then run tsd against test/typing\nnpm run test:cov          # Test coverage\n\n# Run a single test file\nTS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/foo.ts\"\n\n# Run a single test by name\nTS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/foo.ts\" --grep \"partial test title\"\n```\n\n## Generated Code\n\n**Do not hand-edit**: `lib/utils/RedisCommander.ts` (generated), `built/` (build output), and `node_modules/`.\n\n`lib/utils/RedisCommander.ts` holds the typed signatures for every Redis command. This is what gives calls like `redis.set(...)` their types.\n\nRegenerate it with:\n\n```bash\nnode bin/index.js\n```\n\nGeneration uses `@ioredis/interface-generator` plus per-command config in `bin/`:\n\n- **`bin/template.ts`** — File skeleton; generated interface is spliced into the `////` marker.\n- **`bin/overrides.js`** — Hand-written signatures for commands the generator gets wrong, such as `hgetall` and `mset`.\n- **`bin/argumentTypes.js`**, **`bin/returnTypes.js`**, **`bin/sortArguments.js`**, **`bin/typeMaps.js`** — Argument and return type mapping and ordering.\n\nWhen adding command typing support, edit the `bin/` config and regenerate. Never patch `RedisCommander.ts` directly.\n\n## Architecture\n\n### Layered Design\n\n```text\nPublic API (`Redis`, `Cluster`, `Pipeline`, `Command`, options)\n  → Command facade (`Commander`, generated `RedisCommander` typings, Lua scripts)\n    → Command objects and queues (`Command`, offline queue, command queue, pipeline queue)\n      → Topology routing (standalone, Sentinel, Cluster slots, subscriber groups)\n        → Connection layer (`connectors/`, `redis/event_handler.ts`, retry and ready checks)\n          → RESP parsing and reply handling (`DataHandler`, `redis-parser`)\n```\n\n### Key Source Areas\n\n- **`lib/index.ts`** — Public export surface for the package. Changes here affect the published TypeScript declarations and user-facing API.\n- **`lib/Redis.ts`** — Main standalone and Sentinel client. Manages connection lifecycle (`wait → connecting → connect → ready → close → reconnecting → end`), offline queue behavior, reconnection strategy, and connector selection.\n- **`lib/utils/Commander.ts`** — Shared command facade for `Redis` and `Cluster`. Dynamically attaches builtin Redis commands, string and `Buffer` variants, autopipelining dispatch, direct `sendCommand`, and `defineCommand` Lua registration.\n- **`lib/Command.ts`** — Single Redis command representation. Handles argument transformation, reply transformation, promise/callback resolution, key-slot calculation, and subscriber/monitor-mode command flags.\n- **`lib/DataHandler.ts`** — Parser and reply dispatcher. Wraps `redis-parser`, consumes socket data, resolves queued commands, and routes Pub/Sub replies and monitor messages.\n- **`lib/connectors/`** — Network connector implementations. `StandaloneConnector` handles TCP/TLS sockets; `SentinelConnector/` resolves masters through Sentinel using `FailoverDetector` and `SentinelIterator`.\n- **`lib/cluster/`** — Cluster client, per-node connection pool, slot cache refresh, redirection handling for `MOVED` and `ASK`, retry scheduling, and cluster Pub/Sub through `ClusterSubscriber`, `ShardedSubscriber`, and `ClusterSubscriberGroup`.\n- **`lib/Pipeline.ts`** and **`lib/transaction.ts`** — Batched command execution. `pipeline()` is non-atomic batching; `multi()` adds MULTI/EXEC transaction behavior.\n- **`lib/autoPipelining.ts`** — Same-tick command batching. `notAllowedAutoPipelineCommands` lists commands that must bypass autopipelining, such as auth, subscribe, and multi.\n- **`lib/Script.ts`** — Lua script abstraction used by `defineCommand`, with `EVALSHA` execution and `EVAL` fallback.\n- **`lib/ScanStream.ts`** — Readable stream wrapper for `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`.\n- **`lib/tracing.ts`** — Command and connection tracing hooks with argument sanitization.\n\n### How Commands Execute\n\n1. User calls a method such as `redis.get()` or `cluster.set()`.\n2. `Commander` routes the call through autopipelining, pipeline/transaction handling, or direct `sendCommand`.\n3. A `Command` object is created with transformed arguments and callback/promise state.\n4. Standalone clients enqueue the command on one connection; Cluster clients choose a node by key slot and may retry on redirects.\n5. The command is written to the socket after connection readiness checks and offline queue handling.\n6. `redis-parser` parses the RESP reply from the socket.\n7. `DataHandler` resolves the matching queued command, applies reply transformers, and emits Pub/Sub or monitor events when relevant.\n\n## Commit Messages\n\nFollow [Conventional Commits](https://www.conventionalcommits.org/): `<type>: <subject>`.\n\nCommon types include `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, and `chore`.\n\nReleases are automated via semantic-release (`.releaserc.json`), so commit messages drive the changelog and version bump.\n\n<!-- File: .agents/skills/code-change-verification/SKILL.md (Tokens: ~876 | Category: anthropic-skill) -->\n---\nname: code-change-verification\ndescription: Verify ioredis code changes before handoff. Use when an agent changes or reviews runtime TypeScript, Redis command support, generated typings, tests, docs tied to behavior, build tooling, release-sensitive files, or any task that needs choosing and running the right local validation commands.\n---\n\n# Code Change Verification\n\nUse this skill to choose the smallest credible validation set for an ioredis change, run it when feasible, and report exactly what passed, failed, or was skipped.\n\n## Workflow\n\n1. Inspect the diff and changed files before choosing commands.\n   - Use `git diff --stat`, `git diff --name-only`, and targeted file reads.\n   - Do not stage, unstage, or commit unless the user explicitly asks.\n   - Treat `built/` and `lib/utils/RedisCommander.ts` as generated outputs; do not hand-edit them.\n\n2. Classify the change.\n   - Runtime code under `lib/`: run focused tests plus build when the change affects exported declarations or compiled output.\n   - Redis command typing or generated command support: inspect `bin/` config, regenerate with `node bin/index.js` if needed, and run tsd or targeted typing tests.\n   - Functional Redis behavior: run the smallest relevant Mocha files and assume a compatible Redis server is on default host/port. If sandboxed Redis access is blocked, ask for permission rather than assuming Redis is unavailable.\n   - Cluster behavior: use `npm run docker:setup` if infrastructure is needed, then targeted `test/cluster/**/*.ts` or `npm run test:cluster`.\n   - Docs-only changes: run `npm run format-check` only if formatting-sensitive files changed; otherwise inspect rendered Markdown manually.\n   - Build/tooling changes: run `npm run build` and the affected script directly.\n\n3. Prefer focused validation before broad validation.\n   - For self-contained pure unit files, run the test file alone first: `TS_NODE_TRANSPILE_ONLY=true NODE_ENV=test npx mocha --no-experimental-strip-types \"test/unit/<file>.ts\"`.\n   - Include `test/helpers/*.ts` only when the unit file relies on global hooks or helper setup.\n   - Functional command change: include `test/helpers/*.ts` and the specific `test/functional/...` file.\n   - Typing change: `npm run build` then `npx tsd --files test/typing/<file>.test-d.ts` when a focused file exists.\n   - Public API or cross-cutting behavior: escalate to `npm test` after focused tests pass.\n   - Formatting-only TypeScript edits: run `npm run lint` or `npm run format-check` as appropriate.\n\n4. Handle generated artifacts deliberately.\n   - If `bin/argumentTypes.js`, `bin/returnTypes.js`, `bin/overrides.js`, `bin/sortArguments.js`, `bin/typeMaps.js`, or `bin/template.ts` changes command declarations, regenerate `lib/utils/RedisCommander.ts` with `node bin/index.js`.\n   - If generated output changes unexpectedly, inspect the generator inputs before accepting it.\n   - Build output in `built/` is publish-facing but generated by `npm run build`; mention if it is intentionally not updated.\n\n5. Report results in handoff.\n   - List each command run and its result.\n   - For failures, include the failing test name or key error line and whether it appears related.\n   - For skipped commands, state the concrete reason, such as missing Redis server, blocked sandbox access, or out-of-scope broad suite.\n\n## Command Reference\n\n- `npm run build`: remove `built/` and compile TypeScript.\n- `npm run lint`: ESLint over `lib/`.\n- `npm run format-check`: Prettier check.\n- `npm run test:js`: non-cluster Mocha suite over helpers, unit, and functional tests.\n- `npm run test:cluster`: cluster Mocha suite.\n- `npm run test:tsd`: build and run all tsd tests.\n- `npm test`: `test:js` plus `test:tsd`.\n- `npm run docker:setup` / `npm run docker:teardown`: start/stop Redis test infrastructure.\n\n<!-- File: .agents/skills/docs-sync/references/doc-coverage-checklist.md (Tokens: ~1541 | Category: anthropic-skill) -->\n# ioredis Doc Coverage Checklist\n\nUse this checklist to scan the selected scope and validate that user-facing ioredis behavior is documented in the right place. In diff mode, limit the scan to the selected task scope: staged changes, unstaged changes, staged plus unstaged changes, or a branch comparison such as `git diff main...HEAD` for PR-oriented audits. In comprehensive mode, inventory the public surfaces listed below.\n\n## Public API inventory\n\n- Public exports from `lib/index.ts`: default `Redis`, named `Redis`, `Cluster`, exported classes, exported types, and compatibility exports.\n- Constructor and option types:\n  - `lib/redis/RedisOptions.ts`: `RedisOptions`, `CommonRedisOptions`, `RetryStrategy`, `ReconnectOnError`, and `DEFAULT_REDIS_OPTIONS`.\n  - `lib/cluster/ClusterOptions.ts`: `ClusterOptions`, `ClusterNodeRetryStrategy`, DNS/NAT helper types, and `DEFAULT_CLUSTER_OPTIONS`.\n  - `lib/connectors/StandaloneConnector.ts`: standalone TCP/TLS connection options.\n  - `lib/connectors/SentinelConnector/types.ts`: Sentinel connection options, failover behavior, and sentinel-specific limits.\n- Generated command API:\n  - `lib/utils/RedisCommander.ts` is generated and must not be hand-edited.\n  - `bin/overrides.js`, `bin/argumentTypes.js`, `bin/returnTypes.js`, `bin/sortArguments.js`, and `bin/typeMaps.js` define command signature and return documentation inputs.\n- Core classes and behavior surfaces: `lib/Redis.ts`, `lib/cluster/index.ts`, `lib/Command.ts`, `lib/Pipeline.ts`, `lib/transaction.ts`, `lib/ScanStream.ts`, `lib/DataHandler.ts`, `lib/autoPipelining.ts`, `lib/Script.ts`, and `lib/tracing.ts`.\n- User-facing examples and executable docs: `README.md`, `examples/`, and `test/typing/`.\n\n## Option JSDoc requirements\n\n- Every public option on `CommonRedisOptions`, `RedisOptions`-contributing connection types, and `ClusterOptions` should have clear JSDoc unless the option is intentionally internal.\n- JSDoc should include:\n  - What the option changes in user-visible behavior.\n  - Default value with `@default`, matching `DEFAULT_REDIS_OPTIONS` or `DEFAULT_CLUSTER_OPTIONS`.\n  - Accepted values when the TypeScript type is broad, such as callback return contracts or string roles.\n  - Topology limits, such as standalone-only, Sentinel-only, Cluster-only, subscriber-mode, or RESP mode constraints.\n  - Redis version requirements when relevant.\n- Keep JSDoc and defaults synchronized for options such as retry strategies, timeouts, offline queue behavior, ready checks, auto pipelining, client info, authentication, Sentinel discovery, Cluster redirections, SRV lookup, NAT mapping, and sharded subscribers.\n- When an option is deprecated, renamed, or compatibility-only, document that in JSDoc and remove stale README guidance if it no longer applies.\n\n## Documentation surfaces\n\n- `README.md`: main guide, examples, feature overview, constructor options, Cluster, Sentinel, Pub/Sub, pipelines, transactions, Lua scripts, streams/scans, TLS, reconnect behavior, and TypeScript usage.\n- `docs/`: generated TypeDoc output from `npm run docs`; update generated docs only as part of an intentional docs generation change.\n- TypeDoc source comments: public JSDoc in `lib/index.ts`, `lib/redis/RedisOptions.ts`, `lib/cluster/ClusterOptions.ts`, connector option types, tracing types, and public classes.\n- `examples/`: runnable examples that should compile and use current APIs.\n- `test/typing/`: tsd coverage for public TypeScript signatures, command typings, constructor options, and exported types.\n\n## Code-first pass\n\n- Start from code, not existing docs. Identify the changed public symbol, option, command signature, return type, default, error, event, or lifecycle behavior.\n- Map the behavior to the closest existing doc surface. Prefer updating an existing README section, JSDoc block, example, or typing test over creating a new document.\n- For command typing changes, update generator config in `bin/`, regenerate `lib/utils/RedisCommander.ts`, and consider `test/typing/commands.test-d.ts`.\n- For option changes, update the interface JSDoc, default object, README option guidance if present, and tsd coverage when the type surface matters.\n- For behavior changes in Cluster, Sentinel, Pub/Sub, pipelines, transactions, scan streams, reconnect logic, ready checks, timeouts, tracing, or data handling, check both README prose and public JSDoc.\n\n## Evidence capture\n\n- Record the file path and symbol or setting name, for example `lib/redis/RedisOptions.ts:CommonRedisOptions.commandTimeout`.\n- Record the default from `DEFAULT_REDIS_OPTIONS` or `DEFAULT_CLUSTER_OPTIONS` when documenting options.\n- Record the implementation behavior that proves the docs text, such as the method, event handler, retry branch, or command transformer.\n- Avoid large code dumps. A short path plus symbol and behavior note is enough.\n\n## Red flags\n\n- README option names, defaults, or examples differ from `RedisOptions`, `ClusterOptions`, connector option types, or default objects.\n- Public options exist without JSDoc, or JSDoc omits important default/behavior constraints.\n- Generated TypeDoc pages under `docs/` are stale relative to TypeScript source comments.\n- `lib/utils/RedisCommander.ts` was manually edited instead of regenerated from `bin/` config.\n- Command return types, Buffer variants, callbacks, Promise behavior, or pipeline/transaction behavior changed without typing or docs review.\n- Removed, renamed, or deprecated features remain documented as current behavior.\n- Examples rely on unsupported Redis versions, topology assumptions, or undocumented setup.\n\n## Structural changes\n\n- Propose README restructuring only when an existing section mixes quick-start usage with deep reference detail, or when Cluster/Sentinel/Pub/Sub/TypeScript material has no sensible home.\n- Keep quick-start examples short. Move advanced retry, timeout, topology, command typing, and failure-mode details into focused sections or JSDoc.\n- Cross-link related concepts instead of duplicating long explanations, especially for options shared between standalone Redis and Cluster `redisOptions`.\n\n## Diff mode guidance\n\n- Choose the diff source that matches the task:\n  - Staged work: `git diff --cached`.\n  - Unstaged work: `git diff`.\n  - All local in-progress work: inspect both `git diff --cached` and `git diff`.\n  - PR-oriented branch audit: `git diff main...HEAD` or the equivalent branch base.\n- Focus only on changed public behavior: new exports/options, modified defaults, removed features, renamed settings, new command signatures, changed reply transformations, or changed lifecycle behavior.\n- Document removals explicitly so stale README, examples, JSDoc, TypeDoc output, and typing tests can be pruned.\n\n## Patch guidance\n\n- Keep edits scoped and aligned to the existing README/JSDoc tone.\n- Do not hand-edit `lib/utils/RedisCommander.ts`; regenerate it with `node bin/index.js` after command typing config changes.\n- Leave translated or vendored docs untouched unless the task explicitly targets them.\n- For Markdown-only updates, inspect nearby formatting. For JSDoc/API changes, run `npm run docs` when generated docs must be refreshed.\n\n<!-- File: .agents/skills/docs-sync/SKILL.md (Tokens: ~935 | Category: anthropic-skill) -->\n---\nname: docs-sync\ndescription: Keep ioredis documentation synchronized with code behavior. Use when an agent changes public APIs, options, Redis command support, examples, generated typings, connection behavior, Cluster/Sentinel behavior, Pub/Sub, pipelines, transactions, scan streams, reconnect behavior, TypeScript usage, or release-facing behavior that may require README or docs updates.\n---\n\n# Docs Sync\n\nUse this skill to decide whether an ioredis change needs documentation, update the right docs, and keep examples aligned with tested behavior.\n\nFor broad documentation audits, option/API coverage checks, or unclear documentation scope, also read `references/doc-coverage-checklist.md` before deciding what to update.\n\n## Workflow\n\n1. Inspect the changed behavior.\n   - Read the diff and the surrounding implementation.\n   - Identify whether users must know a new capability, option, error case, event, command signature, return shape, or migration concern.\n   - Treat TypeScript declarations and public JSDoc as documentation when command signatures, constructor options, or exported types change.\n\n2. Find the documentation surface.\n   - `README.md`: primary user-facing guide, examples, feature overview, options, and common workflows.\n   - `lib/redis/RedisOptions.ts`: `RedisOptions`, `CommonRedisOptions`, option JSDoc, and `DEFAULT_REDIS_OPTIONS`.\n   - `lib/cluster/ClusterOptions.ts`: `ClusterOptions`, cluster option JSDoc, and `DEFAULT_CLUSTER_OPTIONS`.\n   - `lib/connectors/StandaloneConnector.ts` and `lib/connectors/SentinelConnector/types.ts`: connection option types that contribute to public constructor options.\n   - `docs/`: generated TypeDoc output from public source comments.\n   - `examples/`: runnable snippets that should match current API behavior.\n   - `lib/index.ts` and public TypeDoc comments: exported API documentation surface.\n   - `test/typing/`: executable documentation for TypeScript signatures.\n\n3. Update docs when the change affects users.\n   - Public option or constructor behavior: document option name, default, behavior, topology limitations, and Redis version constraints in JSDoc first; update README/examples when users need prose or usage guidance.\n   - Redis command support: update generator config in `bin/`, regenerate `lib/utils/RedisCommander.ts`, and document only if README/docs mention related command groups or if the change affects command typing, return mapping, or examples.\n   - Pub/Sub, sharded Pub/Sub, monitor, pipeline, transaction, Sentinel, Cluster, TLS, reconnect, or offline queue behavior: update the relevant README/docs section.\n   - New or changed public exports from `lib/index.ts`: update TypeDoc comments and typing tests when the exported type or class is part of the supported API.\n   - Breaking or compatibility-sensitive behavior: add explicit migration or caveat wording.\n   - Internal-only refactors with no behavioral/API impact: state that no docs update is needed and why.\n\n4. Keep examples honest.\n   - Prefer short examples that compile against the current public API.\n   - Avoid documenting behavior that is not covered by tests unless you also add or request coverage.\n   - If an example requires a Redis version, topology, or protocol mode, say so near the example.\n   - Use existing README style and terminology.\n\n5. Verify documentation changes.\n   - For TypeScript examples or declarations, run the focused tsd test or add one when appropriate.\n   - For API docs comments, run `npm run docs` when the change affects generated docs.\n   - For command typing changes, run `node bin/index.js` before validating generated typings.\n   - For Markdown-only edits, inspect nearby formatting and links; run `npm run format-check` only when relevant files are covered by Prettier.\n\n## Documentation Decision Checklist\n\n- Does the change alter public exports from `lib/index.ts`?\n- Does it add, remove, rename, or change JSDoc/defaults for `RedisOptions`, `CommonRedisOptions`, `ClusterOptions`, standalone connection options, or Sentinel connection options?\n- Does it add, remove, or change a Redis command method signature?\n- Does it change reply transformation, Buffer variants, callbacks, or Promise behavior?\n- Does it affect connection lifecycle, retries, ready checks, offline queue, or subscriber mode?\n- Does it affect Cluster routing, redirections, subscriber groups, Sentinel discovery, or TLS?\n- Does it add an option, event, error condition, or environment assumption?\n- Would a user need different code after this change?\n\nIf any answer is yes, update docs or explicitly explain why existing docs already cover it.\n\n<!-- File: .agents/skills/implement-command/SKILL.md (Tokens: ~1413 | Category: anthropic-skill) -->\n---\nname: implement-command\ndescription: Use when adding or updating Redis command support in ioredis, including command metadata checks, generator inputs under bin/, generated RedisCommander typings, return and argument overrides, functional command tests, optional tsd coverage, and validation.\n---\n\n# Implement Command\n\nUse this skill when adding a missing Redis command, correcting an existing command signature, changing command return types, or adding coverage for command-specific Buffer, callback, pipeline, or transformer behavior.\n\n## Command Support Map\n\n- `@ioredis/commands`: upstream command metadata consumed by the generator.\n- `bin/index.js`: generator entry point for `lib/utils/RedisCommander.ts`.\n- `bin/returnTypes.js`: command return type map. Most new commands need an entry here.\n- `bin/argumentTypes.js`: command-specific argument shape overrides when metadata or global mapping is insufficient.\n- `bin/typeMaps.js`: global Redis argument category to TypeScript type mapping.\n- `bin/overrides.js`: manual overloads for signatures the generator cannot express cleanly.\n- `bin/sortArguments.js`: argument reordering for commands whose generated order is wrong.\n- `lib/utils/RedisCommander.ts`: generated declarations. Regenerate it; do not hand-edit it.\n- `lib/Command.ts`: command argument and reply transformer registry. Touch only when transformer behavior is needed.\n- `test/functional/commands/<command>.ts`: runtime command coverage.\n- `test/functional/transformer.ts`: transformer runtime coverage.\n- `test/typing/commands.test-d.ts`: public command typing coverage.\n- `test/typing/transformers.test-d.ts`: transformer typing coverage.\n\n## Workflow\n\n1. Establish command scope.\n   - Normalize command keys to lowercase, matching `bin/returnTypes.js`.\n   - Resolve command aliases or subcommands before editing.\n   - Confirm the command exists in `@ioredis/commands`. If it is missing there, stop and report that the metadata package must be updated before ioredis can generate typed command support.\n   - Identify the minimum Redis server version needed and whether functional tests must be version-gated.\n\n2. Inspect current support.\n   - Search `lib/utils/RedisCommander.ts`, `bin/`, `test/functional/commands/`, and `test/typing/` for the command and related aliases.\n   - Inspect nearby command families before choosing types, for example hash expiration commands, sorted-set commands, stream commands, or pub/sub commands.\n   - Check existing argument and reply transformers before adding new ones.\n\n3. Update generator inputs.\n   - Prefer `bin/returnTypes.js` for return type corrections.\n   - Use a string return type for simple fixed replies.\n   - Use a function return type when replies depend on subcommands, options, or tokens.\n   - Reuse `hasToken` and `matchSubcommand` in `bin/returnTypes.js` when they fit.\n   - Use `bin/argumentTypes.js` only for command-specific argument overrides.\n   - Use `bin/typeMaps.js` only for broad metadata category fixes that should affect multiple commands.\n   - Use `bin/overrides.js` only when generated overloads cannot express the supported API cleanly.\n   - Keep command names lowercase in generator maps unless the surrounding file uses another established convention.\n\n4. Regenerate declarations.\n   - In this repo, use `node bin/index.js` unless `package.json` later adds an explicit generation script.\n   - Review the generated diff in `lib/utils/RedisCommander.ts`.\n   - Check the normal method, callback overload, pipeline/transaction shape, and Buffer variant when the command returns strings, arrays, nullable bulk replies, or transformed objects.\n   - If generation changes unrelated commands, inspect the generator input and do not accept surprising churn without an explanation.\n\n5. Add focused runtime coverage.\n   - Put command tests in `test/functional/commands/<lowercase-command>.ts`.\n   - Use `import Redis from \"../../../lib/Redis\";` and `import { expect } from \"chai\";`.\n   - Prefer `let redis: Redis`, `beforeEach(() => { redis = new Redis(); })`, and `afterEach(() => { redis.disconnect(); })`.\n   - For version-gated command tests under `test/functional/commands/`, import `isRedisVersionLowerThan` from `../../helpers/util`, and use `before(async function () { ... this.skip(); })`; use function syntax when calling `this.skip()`.\n   - Use unique keys such as `${command}_${caseName}_${Date.now()}`.\n   - Test the ioredis command surface: accepted argument shapes, option ordering, callback behavior, Buffer variants, and reply shape.\n   - Keep assertions focused on what ioredis sends and returns. Do not test Redis server internals beyond the smallest deterministic setup needed.\n   - Assert exact replies when stable; otherwise assert primitive type, nullable behavior, array/object shape, or Buffer conversion.\n\n6. Add typing coverage when useful.\n   - Add cases to `test/typing/commands.test-d.ts` when the command has nontrivial overloads, return types, Buffer variants, callback typing, or option-dependent replies.\n   - Cover `expectType<Promise<...>>(redis.command(...))`.\n   - Add Buffer variant expectations when the command has one.\n   - Add callback typing for nontrivial return types.\n   - Use `expectError` only for meaningful invalid signatures.\n   - Update `test/typing/transformers.test-d.ts` only when transformer APIs are affected.\n\n7. Consider documentation.\n   - Use the repo `docs-sync` skill when command support changes public signatures, return mapping, examples, or documented command behavior.\n   - Usually command support is documented through generated declarations and typing tests; update README/docs only when existing prose or examples cover the affected command family or users need version/topology caveats.\n\n8. Validate.\n   - Run `node bin/index.js` after generator input changes.\n   - Run the focused functional command test when Redis support is available, using the repo's Mocha pattern with `test/helpers/*.ts`.\n   - Run `npm run build` when generated declarations, public TypeScript, or generator output changed.\n   - If typing tests changed, run `npx tsd --files test/typing/commands.test-d.ts` after building.\n   - Use the repo `code-change-verification` skill before handoff to choose any additional validation.\n   - If Redis access is blocked by sandboxing, ask for permission to access the local Redis server rather than assuming it is unavailable.\n\n## Completion Report\n\nReport:\n\n- Commands added or updated.\n- Metadata/generator inputs changed.\n- Generated files changed.\n- Functional tests added or updated.\n- Typing tests added or updated.\n- Documentation decision.\n- Validation commands run and results.\n- Skipped validation with the concrete reason, including Redis version or local environment limits.\n\n<!-- File: .agents/skills/pr-draft-summary/SKILL.md (Tokens: ~1413 | Category: anthropic-skill) -->\n---\nname: pr-draft-summary\ndescription: Create the required PR-ready summary block, branch suggestion, title, and draft description for ioredis. Must be used before the final response whenever the actual task diff includes runtime code, tests, examples, build/test configuration, or docs with behavior impact, regardless of perceived change size. Skip only when no eligible files changed, every change is repo-meta or docs-only without behavior impact, the task is conversation-only, or the user explicitly opts out.\n---\n\n# PR Draft Summary\n\n## Purpose\n\nProduce a PR-ready summary after eligible work is complete: a concise change summary plus a PR-ready title and draft description for ioredis.\n\n## Close-out Gate\n\n1. Inspect the actual task diff before sending the final response.\n2. Run this skill when the diff includes runtime code, tests, examples, build/test configuration, or docs with behavior impact. Do not use perceived change size to skip an eligible change.\n3. Run it after any required verification and before sending the \"work complete\" response.\n4. Skip only when no eligible files changed, every change is repo-meta or docs-only without behavior impact, the task is conversation-only, or the user explicitly opts out.\n\n## Inputs to Collect Automatically (do not ask the user)\n\n- Current branch: `git rev-parse --abbrev-ref HEAD`.\n- Working tree: `git status -sb`.\n- Untracked files: `git ls-files --others --exclude-standard` (use with `git status -sb`; `--stat` omits them).\n- Changed files: `git diff --name-only` (unstaged) and `git diff --name-only --cached` (staged); sizes via `git diff --stat` and `git diff --stat --cached`.\n- Pull request base reference (prefer the canonical upstream branch; never use a feature branch's upstream as the PR base):\n  - `BASE_REF=upstream/main`; if it does not exist locally, use `origin/main`; if that does not exist locally, use `main`.\n  - `BASE_COMMIT=$(git merge-base \"$BASE_REF\" HEAD)`.\n- Committed branch diff: `git diff --name-only \"${BASE_COMMIT}..HEAD\"` and `git diff --stat \"${BASE_COMMIT}..HEAD\"`.\n- Commits ahead of the base fork point: `git log --oneline --no-merges ${BASE_COMMIT}..HEAD`.\n- Category signals for this repo: runtime (`lib/`, `bin/`, `examples/`, `benchmark/`), tests (`test/`), docs (`docs/`, `README.md`, `AGENTS.md`, `.agents/`, `.github/`), build/test config (`package.json`, `package-lock.json`, `tsconfig.json`, `.eslintrc*`, `.mocharc*`, `nyc.config.js`, `typedoc.json`).\n\n## Workflow\n\n1. Run the commands above without asking the user; compute `BASE_REF`/`BASE_COMMIT` first so later commands reuse them. Compare against `upstream/main`, `origin/main`, or `main`, not the current branch's upstream.\n2. Combine the committed branch diff with staged, unstaged, and untracked changes. If the combined diff is empty, reply briefly that no code changes were detected and skip emitting the PR block.\n3. Infer change type from the touched paths listed under \"Category signals\"; classify as feature, fix, refactor, or docs-with-impact, and flag backward-compatibility risk only when the diff changes released public APIs, client/command behavior, connection config, or the RESP wire handling. Judge that risk against the latest release tag, not unreleased branch-only churn.\n4. Summarize changes in 1–3 short sentences using the top five paths and stats from the committed, staged, and unstaged diffs. Explicitly call out untracked files because `--stat` does not include them. Use commit messages as supporting context, not as a substitute for inspecting the committed diff.\n5. Choose the lead verb for the description: feature → `adds`, bug fix → `fixes`, refactor/perf → `improves` or `updates`, docs-only → `updates`.\n6. Provide a specific topic branch for the contributor's work. Pull requests must not be prepared from `main` or a fork's `main`.\n   - If already off `main`, keep the current branch name and report it as the branch to use.\n   - If on `main`, propose `feat/<slug>`, `fix/<slug>`, or `docs/<slug>` based on the primary area (for example `docs/pr-draft-summary-guidance`) and show a `git checkout -b <branch>` command.\n7. If the current branch matches `issue-<number>` (digits only), keep that branch suggestion. When an issue number is present, reference `https://github.com/redis/ioredis/issues/<number>` and include an auto-closing line such as `This pull request resolves #<number>.` Do not block if the issue cannot be fetched.\n8. Draft the PR title and description using the template below. Use Conventional Commits prefixes for the title (`feat:`, `fix:`, `docs:`, `chore:`, etc.).\n9. Output only the block in \"Output Format\". Keep any surrounding status note minimal and in English. Do not include company-internal references (e.g. Jira/Confluence IDs) in the branch name, title, or description.\n\n## Output Format\n\nWhen closing out a task, add this concise Markdown block (English only) after any brief status note unless the task falls under the documented skip cases or the user says they do not want it.\n\n```\n# Pull Request Draft\n\n## Branch name suggestion\n\n<Either `Current branch: <existing-topic-branch>` when already off `main`, or `git checkout -b <new-topic-branch>` when currently on `main`. Never suggest using `main` as the pull request branch.>\n\n## Title\n\n<single-line imperative title, which can be a commit message; a Conventional Commits prefix such as feat:, fix:, or docs: is preferred>\n\n## Description\n\n<include what you changed plus a draft pull request title and description for your local changes; start the description with prose such as \"This pull request resolves/updates/adds ...\" using a verb that matches the change (you can use bullets later), explain the change background (for bugs, clearly describe the bug, symptoms, or repro; for features, what is needed and why), any behavior changes or considerations to be aware of, and you do not need to mention any tests you ran.>\n```\n\nKeep it tight—no redundant prose around the block, and avoid repeating details between `Changes` and the description. Tests do not need to be listed unless specifically requested.\n\n<!-- File: .agents/skills/runtime-behavior-probe/references/error-cases.md (Tokens: ~532 | Category: anthropic-skill) -->\n# Common Error Cases\n\nUse this reference to expand beyond the happy path. Favor error cases that a real user or operator is likely to hit.\n\n## Configuration Errors\n\nCheck whether the runtime behaves differently for:\n\n- Missing required environment variables.\n- Present but malformed secrets or identifiers.\n- Wrong endpoint or base URL.\n- Wrong model or deployment name.\n- Incompatible local dependency versions.\n\nLook for:\n\n- Error type and status code.\n- Whether the failure is immediate or delayed.\n- Whether the message is actionable.\n- Whether retrying without fixing configuration changes anything.\n\n## Input Errors\n\nProbe common bad-input patterns such as:\n\n- Missing required fields.\n- Wrong data type.\n- Unsupported enum or option value.\n- Empty but syntactically valid input.\n- Oversized input or too many items.\n- Mutually incompatible options.\n\nPrefer realistic invalid inputs over artificial nonsense. The point is to learn how the runtime fails in practice.\n\n## Transport and Availability Errors\n\nWhen networked services are involved, consider:\n\n- Connection failure.\n- Read timeout.\n- Server timeout or upstream gateway error.\n- Rate limit response.\n- Partial stream interruption.\n- Reusing a connection after a failure.\n\nCapture whether the client library retries automatically, whether it surfaces retry metadata, and whether the final exception preserves the original cause.\n\n## State and Repetition Errors\n\nMany surprising bugs appear only when an operation is repeated or interrupted:\n\n- Re-submit the same request.\n- Repeat after a timeout.\n- Retry after a partial tool call or partial stream.\n- Resume after local cleanup or process restart.\n- Repeat with slightly changed inputs while reusing shared state.\n\nObserve whether the operation is idempotent, duplicated, silently ignored, or left in a partial state.\n\n## Concurrency Errors\n\nWhen shared state, ordering, or isolation may matter, consider:\n\n- Two overlapping requests with the same logical input.\n- Parallel runs that reuse the same cache key, session, container, or temporary resource.\n- Concurrent retries, cancellation, or cleanup racing with active work.\n- Output or event streams from one run leaking into another.\n\nCapture whether the runtime serializes, rejects, duplicates, corrupts, or cross-contaminates the work.\n\n## Investigation Heuristics\n\nUse these heuristics to pick error cases quickly:\n\n- Ask which failure a real engineer would debug first in production.\n- Ask which failure is most expensive if it is misunderstood.\n- Ask which failure would be invisible from code review alone.\n- Ask which failure path is likely to differ across environments.\n\nIf the error behavior is already perfectly obvious from a local validator or type system, it is usually low priority for this skill.\n\n<!-- File: .agents/skills/runtime-behavior-probe/references/redis-runtime-patterns.md (Tokens: ~1946 | Category: anthropic-skill) -->\n# Redis Runtime Patterns\n\nUse this reference for recurring ioredis investigations so you do not have to rediscover the probe strategy each time. Treat the repository source as the truth for client behavior, and use [redis.io/commands](https://redis.io/commands) to confirm contract-sensitive details such as argument order, reply types, and version availability. If you rely on the website rather than source, say so in the report.\n\n## General Rules\n\n- Prefer small, focused probes over large harnesses. Keep one script focused on one uncertainty.\n- For comparative or benchmark-like questions, start with a pilot and expand only when the answer is still unclear.\n- Capture the request shape (command and arguments as sent) and the observed command result or emitted event payload.\n- Preserve raw error type, message, and any Redis error prefix such as `WRONGTYPE`, `MOVED`, `ASK`, `CROSSSLOT`, `NOSCRIPT`, or `LOADING`.\n- Record whether behavior differs between the first call and a repeated call, and across a reconnect.\n- When the question is about regression or contract drift, add a known-good control run before attributing the result to the change under investigation.\n- Keep comparison parity explicit. Record what was held constant, what variable changed, and whether reply-shape or encoding differences could bias the conclusion.\n- Record the runtime context that actually changes Redis client behavior: server mode (standalone, cluster, sentinel), RESP version (2 vs 3), server version, and whether a feature such as auto-pipelining or sharded pub/sub is in use.\n\n## Connection Environment Variables\n\nDo not read these variables automatically. Before a live probe uses any of them, tell the user the exact variable names you plan to read and why each one is needed, then wait for explicit approval. Never print their values:\n\n- `REDIS_URL`\n- `REDIS_PASSWORD`\n- `REDIS_TLS_CA`, `REDIS_TLS_CERT`, `REDIS_TLS_KEY` (and any other `REDIS_TLS_*` the probe needs)\n\nFor most local probes you do not need any of these. ioredis repository instructions assume a Redis server with the correct version is running on the default host and port. Prefer that local Redis server over a live remote service unless the question is specifically about the remote deployment.\n\nIf the task targets another integration, use that integration's expected default variable names under the same rule.\n\n## Environment False Signals\n\nBefore attributing a failure to the patch or client code under review, exclude source-selection and environment problems with a controlled comparison.\n\n- Confirm the commit, worktree, working directory, Node executable/version, and imported module path. A probe of stale `built`, another checkout, `/tmp/node_modules`, or an installed `ioredis` package does not prove current `lib` behavior.\n- Rebuild when emitted declarations, package exports, generated command typings, or `built` is the subject. Otherwise prefer current-source `lib/` imports so stale build output cannot create a false result.\n- Confirm a Redis server is actually running and reachable. A connection refused or timeout against a missing Docker/Redis container is an environment condition, not a client defect, until a controlled rerun against a known-good server ties it to the code.\n- Confirm the RESP version the client negotiated. A reply-shape surprise is often just RESP2 vs RESP3, not a bug.\n- Confirm server mode matches the probe assumptions. Running a cluster-only expectation against a standalone server, or the reverse, produces misleading routing and slot errors.\n- Run base and head controls with the same Node version, dependency graph, server mode, RESP version, environment-variable names, and command shape. Record intentional differences.\n- Treat sandbox denials, unavailable Docker infrastructure, expired remote sessions, authentication, quota, rate limits, service outages, and stale caches as environment conditions until a controlled rerun ties them to the patch.\n- Never print credentials, connection URLs with embedded passwords, or TLS key material. Change only the minimum in-scope environment or disposable state needed for the control and record variable names rather than values.\n\nIn the final report, distinguish code failures, unsupported configurations, environment blockers, and inconclusive probes. Do not collapse them into one failed-test count.\n\n## ioredis Probe Patterns\n\nStart from the uncertainty instead of from the full client surface. The patterns below cover the runtime questions that recur most often in ioredis.\n\n### RESP2 vs RESP3 reply shapes\n\nUse when the uncertainty is what a command returns at runtime.\n\n- Run the same command under RESP2 and RESP3 as separate cases when protocol differences are part of the uncertainty.\n- Capture the observed command result and whether the client returns plain objects, `Map`, arrays, `null`, buffers, strings, or numbers.\n- Watch precision-sensitive numeric replies and record the exact value.\n\n### Single-node vs cluster vs sentinel\n\nUse when key routing, slot ownership, or topology matters.\n\n- For cluster, capture which node served the command and whether a `MOVED` or `ASK` redirect occurred. Probe multi-key commands across keys in different slots to observe `CROSSSLOT` behavior and any client-side slot checks.\n- Use hash tags (`{tag}`) to force keys into the same slot when the probe needs a multi-key command to succeed.\n- For sentinel, capture master discovery and what happens on a simulated failover.\n- Keep mode constant within a case. A standalone control alongside a cluster case is a useful comparison, not a substitute.\n\n### Pub/sub and sharded pub/sub\n\nUse when delivery semantics or resubscription matter.\n\n- Capture subscribe confirmation, message delivery order, emitted event names, and whether messages are delivered to pattern (`PSUBSCRIBE`) and channel subscribers as expected.\n- For sharded pub/sub (`SSUBSCRIBE` and `SPUBLISH`) in cluster, capture which shard delivered the message.\n- Force a reconnect and observe whether the client resubscribes to channels and patterns automatically. This is a common drift point.\n\n### Reconnection, retry, and the offline command queue\n\nUse when the question is about resilience.\n\n- Simulate a dropped connection (stop or restart the container, or close the socket) and capture: whether commands issued while offline are queued, the order they flush in on reconnect, and whether the reconnect strategy backoff behaves as configured.\n- Distinguish commands rejected immediately from commands queued and later resolved or rejected.\n- Capture whether in-flight commands at disconnect are retried, rejected, or hang.\n\n### Pipelining and MULTI/EXEC transactions\n\nUse when batching or atomicity is under test.\n\n- For pipelining, confirm replies map back to the right commands in order, including when one command in the batch errors.\n- For `MULTI`/`EXEC`, capture queueing errors versus execution errors, behavior on `DISCARD`, and `WATCH` optimistic-locking aborts (`EXEC` returning `null`).\n\n### RESP3 push messages and subscribed connection behavior\n\nUse when push-message routing or subscribed connection behavior matters.\n\n- Requires RESP3 when the question depends on push-message behavior. Capture whether push replies are routed to events, whether regular commands are allowed while subscribed, and whether replies preserve expected buffer/string variants.\n- Probe RESP2 and RESP3 separately when subscribed-mode command behavior or push reply shape is part of the uncertainty.\n\n### Blocking commands and connection isolation\n\nUse for `BLPOP`, `BRPOP`, `XREAD BLOCK`, `WAIT`, and similar.\n\n- Capture whether the blocking command monopolizes a connection and whether the caller needs a separate Redis instance so other commands are not stalled.\n- Probe timeout behavior and what resolves when the block is satisfied by another client versus when it times out.\n\n### Auto-pipelining and command queues\n\nUse when same-tick batching, offline queue behavior, or command queue ordering is involved.\n\n- Capture which commands are batched, whether disabled commands bypass auto-pipelining, and whether reply order matches command order.\n- For reconnect-sensitive questions, distinguish offline queue entries, in-flight commands, and commands rejected because the connection state does not allow queuing.\n\n### SCAN iterators\n\nUse for `SCAN`, `HSCAN`, `SSCAN`, and `ZSCAN`.\n\n- Capture cursor progression, whether the async iterator terminates, and whether `COUNT` and `MATCH` behave as expected. Note that SCAN gives no count or completeness guarantees mid-iteration.\n\n### Large payloads and timeouts\n\nUse when size or latency is the concern.\n\n- Capture behavior with large values and large reply sets, and whether command-level or socket timeouts fire as configured.\n- For repeat-sensitive latency, use warm-up plus repeat-N and record medians, not a single sample.\n\n## What to Capture\n\nFor ioredis probes, try to record:\n\n- The command and arguments as sent, plus the observed result or emitted event payload.\n- The JavaScript value and its type, including buffer variants when relevant.\n- Server mode (standalone, cluster, or sentinel), negotiated RESP version, and server version.\n- Whether fields are absent, `null`, empty, or transformed by the client.\n- Raw error type, message, and any Redis error prefix for failures.\n- Reconnect and retry behavior, offline-queue flush order, and resubscription on reconnect when relevant.\n- For cluster, which node served the command and any redirect.\n- Which environment-variable names were approved for the probe when a live or credentialed server was required.\n\nDo not spend time rediscovering static documentation unless the runtime result seems to contradict what you expected. The value of this skill is in the observed behavior.\n\n<!-- File: .agents/skills/runtime-behavior-probe/references/repo-import-patterns.md (Tokens: ~934 | Category: anthropic-skill) -->\n# Repository Import Patterns\n\nUse this reference when a temporary probe script outside the repository needs to load code from the current branch.\n\n## Why This Exists\n\nWhen you run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/probe.ts` from the repository root, `ts-node` itself comes from this repository, but the probe file still lives under `/tmp`. Bare imports such as `ioredis` can resolve as if the script were its own package. That is often not what you want for \"what does the current branch do right now?\" investigations.\n\nThe safe default is to build an absolute path from `process.cwd()`, which should be the repository root, and a repository-relative path.\n\n## Default Rule\n\n- Use `lib/` imports when the question is about current-branch behavior.\n- Use `built/` imports when the question is about packaged output after a build.\n- Avoid bare package imports from `/tmp` unless the probe is explicitly testing published package resolution rather than branch-local source behavior.\n\n## Quick Typecheck Loop\n\nFor disposable probes in `ioredis`, the default loop should stay outside the repository and avoid a full package build:\n\n1. Create a temporary directory with `mktemp -d`.\n2. Write `probe.ts` there.\n3. Write a sibling `tsconfig.json` that extends the repository's `tsconfig.json`.\n4. From the repository root, run `npx tsc --noEmit -p /tmp/.../tsconfig.json`.\n5. If that passes, run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/.../probe.ts`.\n\nExample temporary `tsconfig.json`:\n\n```json\n{\n  \"extends\": \"/absolute/path/to/ioredis/tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"types\": [\"node\"],\n    \"typeRoots\": [\"/absolute/path/to/ioredis/node_modules/@types\"]\n  },\n  \"include\": [\"./probe.ts\"]\n}\n```\n\nThis keeps TypeScript module resolution and strictness close to the repository defaults while limiting the check surface to the disposable probe file.\n\nDo not convert this default loop into a checked-in benchmark, example, or package script unless the user explicitly asks for a reusable repository artifact.\n\n## Recommended Helper\n\nThe disposable TypeScript scaffold exposes:\n\n    const module = await importRepoModule(\"lib/index.ts\");\n\nInternally, the helper should be equivalent to:\n\n    import { createRequire } from \"module\";\n    import { resolve } from \"path\";\n\n    const repoRequire = createRequire(resolve(process.cwd(), \"package.json\"));\n\n    async function importRepoModule(repoRelativePath: string) {\n      const absolutePath = resolve(process.cwd(), repoRelativePath);\n      return Promise.resolve(repoRequire(absolutePath));\n    }\n\nThis keeps the import anchored to the current checkout instead of the temporary script location.\n\n## Choosing `lib/` Versus `built/`\n\nUse `lib/` when:\n\n- You are validating a bug fix or regression on the current branch.\n- You want to know how the repository behaves before packaging.\n- The question is about implementation details or internal helper behavior.\n\nUse `built/` when:\n\n- The question is specifically about what consumers load after `npm run build`.\n- You need to validate export maps or emitted `.js` and `.d.ts` output.\n- The bug only reproduces in generated output.\n\nIf the probe uses `built/`, record whether you ran a fresh build first. A stale `built/` directory can create false positives or false negatives.\n\nDo not run `npm run build` only to typecheck or execute a `lib/`-based disposable probe. The fast path is temp `tsconfig` plus `npx tsc --noEmit`, then `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register`.\n\n## Simple Smoke Targets\n\nWhen you only need to prove the helper works, start with a simple target that has minimal side effects, for example:\n\n- `lib/index.ts`\n- `lib/Redis.ts`\n- `lib/Command.ts`\n- another file with obvious exported symbols and no environment requirement\n\nIf a chosen file pulls in more of the repo than expected, switch to a simpler target rather than weakening the import guidance.\n\n## What To Record\n\nWhen a probe imports repo code, report:\n\n- The repo-relative path you imported.\n- Whether it came from `lib/` or `built/`.\n- The repository root used by `process.cwd()`.\n- Any prerequisite step such as `npm run build`.\n\n<!-- File: .agents/skills/runtime-behavior-probe/references/reporting-format.md (Tokens: ~1024 | Category: anthropic-skill) -->\n# Reporting Format\n\nLead with findings, not process. The user asked for investigation results, so the answer should start with the most important observed behaviors. Put the real news first.\n\n## Recommended Order\n\n1. Findings.\n2. Validation approach.\n3. Case matrix or condensed case summary.\n4. Artifact status and brief run summary.\n5. Optional implementation note.\n\n## Findings Section\n\nMake each finding answer one user-relevant question. Good findings usually include:\n\n- What was observed.\n- Why it matters.\n- The condition under which it happens.\n- What was held constant when the finding comes from a comparison probe.\n- `scope`: The boundary of the finding, such as commit, model, Node version, live versus local, or repeat mode.\n- `confidence`: `high`, `medium`, or `low`.\n\nAvoid burying the main result under setup details.\n\nPut `unexpected` or `negative` findings first. If there were no unexpected or negative findings in the executed cases, say that explicitly before the rest of the findings section.\n\nIf the probe was comparative, say whether the result supports:\n\n- Pattern parity only.\n- A broader quality claim.\n\nDo not imply a broader quality equivalence than the executed cases justify.\n\n## Validation Approach Section\n\nSummarize:\n\n- The runtime surface you exercised.\n- The shape of the probe code, in overview only.\n- Which categories of cases you covered.\n- Which execution modes you used, including repeat counts or warm-up handling when relevant.\n- Whether live credentials or external services were used.\n- Any important state controls such as fresh state, cache reuse, cache busting, unique IDs, or cleanup verification.\n- For comparison probes, what was held constant, what was varied, and whether output-shape or usage differences could still influence the conclusion.\n- Whether the usual docs path or an official-docs fallback was used for contract-sensitive checks.\n\nKeep this concise. The user needs enough detail to trust the result, not a line-by-line replay of the script.\n\n## Case Summary\n\nInclude either the full matrix or a condensed summary. At minimum, show:\n\n- Which scenarios were executed.\n- Whether the run was a quick pilot, an expanded matrix, or both.\n- Which ones produced `unexpected` or `negative` results.\n- Which ones passed or failed when a real comparison basis existed.\n- Which cases were blocked.\n- Where the supporting evidence lived, or that it was deleted.\n\nIf the matrix is large, show the highest-value cases in the main response and keep the rest as a compact appendix or note.\n\n## Artifact Status And Brief Run Summary\n\nState one of these explicitly:\n\n- Temporary artifacts were kept until the final response was drafted, then deleted after validation.\n- Temporary artifacts were kept at `<path>` because the user asked to keep them.\n- Temporary artifacts were kept at `<path>` because they are needed for follow-up analysis.\n\nEven if artifacts were deleted, retain a short run summary such as:\n\n- Probe command or runner shape.\n- Runtime context summary such as commit, Node executable, Node version, or model.\n- Artifact path and final status.\n\nFor benchmark or repeat-heavy probes, keeping artifacts for follow-up is often the right default even when the immediate report is done.\n\n## Optional Implementation Note\n\nInclude this only when one clear defect was isolated and a short implementation hypothesis or minimal repro direction would help. Keep it brief. Do not turn the report into a broader next-step plan unless the user asked for that.\n\n## Compact Template\n\nUse this outline when you need a fast structure:\n\n    Findings:\n    - <finding 1>\n      held constant: <prompt/tool/state settings kept the same, if comparative>\n      scope: <commit/model/node/live-local/repeat-mode>\n      confidence: <high|medium|low>\n    - <finding 2>\n      held constant: <prompt/tool/state settings kept the same, if comparative>\n      scope: <commit/model/node/live-local/repeat-mode>\n      confidence: <high|medium|low>\n\n    Validation approach:\n    - Surface: <what was exercised>\n    - Probe code: <brief overview>\n    - Coverage: <success, edge, error, repeat-sensitive, and quality categories>\n    - Execution modes: <single-shot|repeat-N|warm-up + repeat-N>\n    - Comparison parity: <what was held constant and what varied, if comparative>\n    - Docs source: <MCP or official-docs fallback, if relevant>\n\n    Case summary:\n    | case_id | scenario | result_flag | status | note |\n    | --- | --- | --- | --- | --- |\n    | S1 | ... | expected | pass | ... |\n    | E1 | ... | negative | fail | ... |\n\n    Artifact status and brief run summary:\n    - Temporary artifacts were kept until the final response was drafted, then deleted.\n    - Summary: <command/runtime-context/artifact-status summary>\n\n    Optional implementation note:\n    - <brief hypothesis or minimal repro direction>\n\nAdjust the format to the task, but preserve the ordering.\n\n<!-- File: .agents/skills/runtime-behavior-probe/references/validation-matrix.md (Tokens: ~1874 | Category: anthropic-skill) -->\n# Validation Matrix\n\nUse the matrix to decide what to probe before writing scripts. The goal is not exhaustive combinatorics; the goal is high-value coverage that is visible, explainable, and likely to reveal runtime surprises. The matrix should make the real news easy to scan.\n\n## Minimum Columns\n\nUse these columns unless the task clearly needs more:\n\n- `case_id`: Stable identifier such as `S1`, `E3`, or `R2`.\n- `scenario`: Short description of the behavior under test.\n- `mode`: `single-shot`, `repeat-N`, or `warm-up + repeat-N`.\n- `question`: The concrete runtime uncertainty this case is answering.\n- `setup`: Inputs, environment, or preconditions required for the case.\n- `observation_summary`: A compact summary of what actually happened.\n- `result_flag`: `unexpected`, `negative`, `expected`, or `blocked`.\n- `evidence`: Path, log reference, or `deleted`.\n\nAdd these columns when they materially improve the investigation:\n\n- `comparison_basis`: The baseline, docs, or prior behavior you are comparing against.\n- `variable_under_test`: The single factor that is intentionally changing in a comparison case.\n- `held_constant`: Prompt shape, tool setup, model settings, or state rules that were intentionally kept the same.\n- `output_constraint`: Any schema, length, or response-shape constraint used to keep the comparison fair.\n- `status`: Use `pass`, `fail`, `unexpected-pass`, `unexpected-fail`, or `blocked` only when there is a credible comparison basis or control.\n- `confidence`: `high`, `medium`, or `low`.\n- `state_setup`: Fresh or reused state, cache strategy, unique IDs, and cleanup checks.\n- `repeats`: Number of measured runs.\n- `warm_up`: Whether a warm-up run was used and why.\n- `variance`: Any useful spread or instability note across repeated runs.\n- `usage_note`: Token, usage, or output-length note when it materially affects interpretation.\n- `control`: Known-good comparison point for regression or behavior-change questions.\n- `risk_profile`: `read-only`, `mutating`, or `costly` for live probes.\n- `env_vars`: Exact environment-variable names the case plans to read.\n- `approval`: `not-needed`, `pending`, or `approved` for cases that need user permission before execution.\n\nUse `result_flag` as the fast scan field. It is what makes unexpected or negative findings jump out before the reader studies the full report.\n\nUse `status` only when you have a real comparison basis. If the case is exploratory and there is no trustworthy baseline, prefer a strong `observation_summary` plus `result_flag` and `confidence` instead of pretending the result is a clean pass or fail.\n\n## Choosing Execution Mode\n\nPick an execution mode before you run the case:\n\n- Use `single-shot` for deterministic, one-run checks.\n- Use `repeat-N` automatically when the question involves cache behavior, retries, streaming, interruptions, rate limiting, concurrency, or other run-to-run-sensitive behavior.\n- Use `warm-up + repeat-N` when the first run is likely to include cold-start effects such as container provisioning, import caches, or prompt-cache population.\n\nUse these defaults unless the task clearly needs something else:\n\n- `repeat-3` for a quick screen of a repeat-sensitive question.\n- `warm-up + repeat-10` for decision-grade latency comparisons or release-facing recommendations.\n- For costly live probes, start at `repeat-3`, then expand only if the answer is still unclear.\n\nIf it is genuinely unclear whether extra runs are worth the time or cost, ask the user before expanding the probe.\n\n## Phase The Matrix\n\nWhen the question is comparative or benchmark-like, do not jump straight to the largest matrix.\n\nStart with a pilot:\n\n- One control.\n- One or two highest-signal success cases.\n- The smallest repeat count that can disqualify a weak candidate quickly.\n\nExpand only when:\n\n- The candidate survives the pilot.\n- The results are close enough that more samples matter.\n- A major runtime surface is still uncovered.\n- The user explicitly wants decision-grade evidence.\n\n## Coverage Categories\n\nTry to cover at least one case from each relevant category:\n\n- `success`: Normal behavior that should work.\n- `control`: Known-good comparison such as `origin/master`, the latest release, or the same request without the suspected option.\n- `boundary`: Size, count, or parameter limits near a plausible edge.\n- `invalid`: Bad inputs or unsupported combinations.\n- `misconfig`: Missing key, wrong endpoint, bad permissions, or incompatible local setup.\n- `transient`: Timeout, temporary server issue, network breakage, or rate limiting.\n- `recovery`: Retry behavior, partial completion, duplicate submission, or cleanup.\n- `concurrency`: Overlapping operations when shared state, ordering, or isolation may matter.\n- `quality`: A harder or more open-ended sample when the user is asking about model intelligence, not just workflow parity.\n\nIf time is limited, prioritize categories in this order:\n\n1. Known-good control when the question implies regression or drift.\n2. Highest-risk success case.\n3. Most plausible user-facing failure.\n4. Most likely edge case with ambiguous behavior.\n5. Cleanup or retry semantics.\n6. Lower-probability extremes.\n\n## Matrix Template\n\nUse this compact template:\n\n    | case_id | scenario | mode | question | setup | state_setup | variable_under_test | held_constant | comparison_basis | observation_summary | result_flag | status | evidence |\n    | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |\n    | K1 | Known-good control | single-shot | Does the baseline still show the expected behavior? | Same probe against baseline target | Fresh state | none | current probe shape | `origin/master` or latest release | pending | pending | pending | pending |\n    | S1 | Baseline success | single-shot | What does the normal success path look like at runtime? | Valid config and representative input | Fresh state | none | representative input and setup | current docs or local expectation | pending | pending | pending | pending |\n    | R1 | Cache or retry behavior | warm-up + repeat-N | Does behavior change after the first run or across retries? | Same request repeated under controlled settings | Cache key or retry setup recorded | reuse versus fresh state | prompt shape and tool setup | same request without reuse, or docs if available | pending | pending | pending | pending |\n    | C1 | Model comparison pilot | warm-up + repeat-N | Does candidate B preserve the covered behavior while improving latency? | Same scenario across two models | Fresh state and stable IDs | model name | prompt shape, tool choice, and model settings parity | control model in the same probe | pending | pending | pending | pending |\n    | E1 | Invalid input | single-shot | How does the runtime reject a realistic bad input? | Missing required field | Fresh state | invalid field value | same request with valid field | same request with valid field | pending | pending | pending | pending |\n    | X1 | Concurrent overlap | repeat-N | Do overlapping runs interfere with each other? | Two or more overlapping operations | Unique IDs plus cleanup verification | overlap timing | same logical input | same request serialized, if available | pending | pending | pending | pending |\n\n## Recording Results\n\nKeep `question` unchanged after execution. Put the actual behavior in `observation_summary`, then mark the scan-friendly `result_flag`.\n\nUse these `result_flag` values consistently:\n\n- `unexpected`: The result diverged from the best current understanding in a surprising way.\n- `negative`: The result exposed a user-relevant failure, risk, or sharp edge.\n- `expected`: The result matched the current understanding and did not reveal new risk.\n- `blocked`: The case did not produce a trustworthy observation.\n\nOnly fill `status` when there is a credible comparison basis. Otherwise use `observation_summary`, `result_flag`, and `confidence` to communicate what was learned without over-claiming certainty.\n\nFor comparison cases, use `observation_summary` and the final report to say whether the evidence supports pattern parity only or a broader quality claim.\n\nIf a case reveals a new branch of behavior, add a follow-up case instead of overloading the original one.\n\n## Evidence Discipline\n\nTreat a case as incomplete when:\n\n- The observed output omits the key result you were testing.\n- The script mixed multiple questions and the result is ambiguous.\n- Hidden state, cache behavior, or previous runs may have influenced the result and were not controlled or documented.\n- The question is whether behavior changed, but the case has no credible control or baseline to compare against.\n- The case plans to read environment variables, but the exact variable names were not approved by the user before execution.\n- The case was repeat-sensitive, but it ran only once without a clear rationale.\n\nWhen this happens, narrow the probe and rerun. A smaller script with a cleaner result is better than a more complicated script that is hard to trust.\n\n<!-- File: .agents/skills/runtime-behavior-probe/SKILL.md (Tokens: ~3725 | Category: anthropic-skill) -->\n---\nname: runtime-behavior-probe\ndescription: Plan and execute runtime-behavior investigations with temporary TypeScript probe scripts, validation matrices, state controls, and findings-first reports. Use only when the user explicitly invokes this skill to verify actual runtime behavior beyond normal code-level checks, especially to uncover edge cases, undocumented behavior, or common failure modes in local or live integrations. A baseline smoke check is fine as an entry point, but do not stop at happy-path confirmation.\n---\n\n# Runtime Behavior Probe\n\n## Overview\n\nUse this skill to investigate real runtime behavior, not to restate code or documentation. Start by planning the investigation, then execute a case matrix, record observed behavior, and report both the findings and the method used to obtain them.\n\n## Core Rules\n\n- Treat this skill as manual-only. Do not rely on implicit invocation.\n- For `ioredis`, treat this skill as a disposable-probe workflow, not a repository implementation workflow.\n- Unless the user explicitly asks for a reusable repository artifact, the allowed write scope is limited to:\n  - a temporary directory used for probe scripts or artifacts\n  - `.agents/skills/runtime-behavior-probe/**` when the user is editing this skill itself\n- For disposable probes in `ioredis`, do not modify `examples/**`, `lib/**`, `test/**`, any `package.json`, `README.md`, build config, or generated files unless the user explicitly asks for a reusable repository artifact or implementation change.\n- If your draft plan would touch a disallowed path, stop and rewrite the plan before editing anything.\n- A baseline success or smoke case is often the right entry point, but do not stop there when the real question involves edge cases, drift, or failure behavior.\n- Plan before running anything. Write the case matrix first, then fill it in with observed results. The matrix can live in a scratch note, a temporary file, or the probe script header.\n- Default to local or read-only probes. Consider a live service only when it is clearly relevant, then apply the lightweight gates below before you run it.\n- Size the probe to the decision. Start with the smallest matrix that can disqualify or validate the current hypothesis, then expand only when uncertainty remains.\n- Before a live probe, apply three lightweight gates:\n  - Destination gate. Use only a live destination that is clearly allowed for the task.\n  - Intent gate. Run the live probe only when the user explicitly wants runtime verification on that integration, or explicitly approves it after you propose the probe.\n  - Data gate. If the probe will read environment variables, mutate remote state, incur material cost, or exercise non-public or user data, name the exact variable names or data class and get explicit approval first.\n- Classify each case as read-only, mutating, or costly before execution. For mutating or costly cases, or for any live case that will read environment variables, define cleanup or rollback before running the probe.\n- Use temporary files or a temporary directory for one-off probe scripts.\n- In `ioredis`, use disposable probe files outside git-tracked paths by default. Do not add one-off probes, harnesses, benchmarks, or examples under `examples/`, `lib/`, `test/`, or other repository directories unless the user explicitly asks for a checked-in artifact.\n- Keep temporary artifacts until the final response is drafted. Then delete them by default unless the user asked to keep them or they are needed for follow-up. Even when artifacts are deleted, keep a short run summary of the command shape, runtime context, and artifact status in the report.\n- Before executing a live probe that will read environment variables, tell the user the exact variable names you plan to use and why, then wait for explicit approval. Examples include `REDIS_URL`, `REDIS_PASSWORD`, and other expected default names for the system under test.\n- Never print secrets, even when they come from standard environment variables that this skill may use.\n- For Redis command or server semantics, treat the repository source as the truth and use [redis.io/commands](https://redis.io/commands) to confirm contract-sensitive details such as argument order, reply types, and version availability. Use runtime probing to validate or challenge the documented behavior, not to skip the documentation pass entirely. If you rely on the website rather than source, say so in the report.\n- For benchmark or comparison probes, make parity explicit before execution. Record what is held constant, what variable is under test, which reply-shape constraints keep the comparison fair, and any counters or timings that matter for interpreting latency or cost.\n- In `ioredis`, default to a light local loop for probe authoring: temporary `probe.ts` plus temporary `tsconfig.json`, `npx tsc --noEmit -p <tmp-tsconfig>`, then `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register <tmp-probe>`. Escalate to `npm run build` only when the runtime question is specifically about `built/`, emitted declarations, or packaged output.\n- In `ioredis`, do not treat a request for runtime verification, benchmarking, or comparison as permission to add a reusable example, benchmark harness, package script, or checked-in sample. Those repository changes require explicit user intent.\n- For probes that need a running Redis, remove setup ambiguity before attributing a negative result to client behavior:\n  - Confirm the server is reachable and note its mode (standalone, cluster, or sentinel) and RESP version before interpreting reply shapes.\n  - Treat RESP2 and RESP3 as separate cases, not interchangeable setup details, when the question is about reply shapes or push messages.\n  - Clear unsupported server-version or command options first so they do not invalidate the probe. Assume a Redis server with the correct version is running on the default host and port unless the task says otherwise; if sandbox access is blocked, ask for permission to access Redis instead of treating Redis as unavailable.\n\n## Workflow\n\n1. Restate the investigation target in operational terms. Name the runtime surface, the key uncertainty, and the highest-risk behaviors to test.\n2. For `ioredis`, declare the allowed write scope before you do any implementation work. For a normal disposable probe, that means a temporary directory only.\n3. Do a short preflight. Check the relevant code or docs first, decide whether the question needs local or live validation, and note any repo, baseline, or release boundary that matters.\n4. Create a validation matrix before executing probes. Cover both baseline behavior and the most relevant failure or drift cases. The matrix can live in a scratch note, a temporary file, or a structured header inside the probe script.\n5. For each case, choose an execution mode up front:\n   - `single-shot` for deterministic one-run checks.\n   - `repeat-N` for cache, retry, streaming, interruption, rate-limit, concurrency, or other run-to-run-sensitive behavior.\n   - `warm-up + repeat-N` when first-run cold-start effects could distort the result. Use these defaults unless the task clearly needs something else:\n   - Quick screen of a repeat-sensitive question: `repeat-3`.\n   - Decision-grade latency or release recommendation: `warm-up + repeat-10`.\n   - Costly live cases: start at `repeat-3`, then expand only if the answer remains unclear. If it is genuinely unclear whether extra runs are worth the time or cost, ask the user before expanding the probe.\n6. When the question is benchmark-like or comparative, run in phases. Start with a high-signal pilot matrix against a control, then expand only the surviving candidates or unresolved cases.\n7. If the question is about a suspected regression or behavior change, add at least one known-good control case such as `origin/master`, the latest release, or the same request without the suspected option.\n8. For comparative probes, define parity before execution. Record prompt or input shape, tool-choice setup, model-settings parity, state reuse rules, and any response-shape constraint that keeps the comparison fair. If materially different output length could bias the result, record usage or token notes too.\n9. If the question asks whether one option has the same intelligence or quality as another, decide whether the matrix supports only example-pattern parity or a broader quality claim. For broader claims, add at least one harder or more open-ended case. Otherwise say explicitly that the result is limited to the covered patterns.\n10. Plan state controls before execution when hidden state could affect the result. Record whether each case uses fresh or reused state, how cache reuse or cache busting is handled, what unique IDs isolate repeated runs, and how cleanup is verified.\n11. If any live case will read environment variables, list the exact variable names and purpose for each case, then ask the user for approval before execution. Keep the approval ask short and include destination, read-only versus mutating or costly risk, exact variable names, and cleanup or rollback if relevant.\n12. Build task-specific probe scripts in a temporary location. Keep the script small, observable, and easy to discard.\n13. If you are about to propose a checked-in script, example, benchmark, or package script for `ioredis`, stop and verify that the user explicitly asked for a reusable repository artifact. If not, keep the probe temporary.\n14. In `ioredis`, make the runtime context explicit:\n\n- Run TypeScript probes from the repository root with `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register <tmp-probe>` when practical.\n- For probe authoring, create both `probe.ts` and a sibling temporary `tsconfig.json` under `mktemp -d`, then run `npx tsc --noEmit -p <tmp-tsconfig>` before the first live execution.\n- Record the current commit, working directory, Node executable, Node version, and the package or source path you imported.\n- Avoid accidental imports from a different checkout or from `/tmp/node_modules`. If the probe needs repository code, import it from an absolute path resolved from `process.cwd()` and a repo-relative path.\n- Prefer current-branch `lib/` imports when the question is \"what does this branch do now?\" and prefer `built/` imports only when the question is specifically about packaged output after a build.\n- Do not run a repository-wide build just to typecheck a disposable probe. Reserve `npm run build` for `built/` probes or when emitted output is itself part of the question.\n\n15. Execute the matrix and capture evidence. Record request shape, setup, observation summary, unexpected or negative result, error details, timing, runtime context, approved environment-variable names, repeat counts, warm-up handling, variance when relevant, cleanup behavior, and for comparisons note what was held constant plus any response-shape or usage notes that affect interpretation.\n16. Update the matrix with actual outcomes, not guesses.\n17. Keep temporary artifacts until the final response is drafted. Then delete them unless the user asked to keep them or they are needed for follow-up. Benchmark and repeat-heavy probes often need follow-up, so keeping artifacts is normal when the result may be revisited. If deleted, retain and report a short run summary.\n18. Report findings first, with unexpected or negative findings first. Then summarize how the validation was performed and which cases were covered.\n19. If the probe isolates one clear defect, you may include a short implementation hypothesis or minimal repro direction. Do not expand into a larger next-step plan unless the user asked for it.\n\n## Validation Matrix\n\nUse a matrix that makes the news easy to scan. Start from the runtime question and the observation summary, not just from `expected` and `pass` or `fail`.\n\nUse a matrix with at least these columns:\n\n- `case_id`\n- `scenario`\n- `mode`\n- `question`\n- `setup`\n- `observation_summary`\n- `result_flag`\n- `evidence`\n\nAdd these columns when they materially improve the investigation:\n\n- `comparison_basis`\n- `variable_under_test`\n- `held_constant`\n- `output_constraint`\n- `status`\n- `confidence`\n- `state_setup`\n- `repeats`\n- `warm_up`\n- `variance`\n- `usage_note`\n- `risk_profile`\n- `env_vars`\n- `approval`\n- `control`\n\nTreat `result_flag` as a fast scan field such as `unexpected`, `negative`, `expected`, or `blocked`. Use `status` only when there is a credible comparison basis, baseline, or documented contract to compare against.\n\nAlways consider whether the matrix should include these categories:\n\n- Baseline success.\n- Control or baseline comparison when a regression is suspected.\n- Boundary input or parameter variation.\n- Invalid or unsupported input.\n- Missing or incorrect configuration.\n- Transient external failure such as timeout, network interruption, or rate limiting.\n- Retry, idempotence, or cleanup behavior.\n- Concurrency or overlapping operations when shared state or ordering may matter.\n- Open-ended quality or intelligence samples when the question is broader than pattern parity.\n\nOpen [validation-matrix.md](./references/validation-matrix.md) when you need a stronger prioritization model or a reusable case template.\n\n## Temporary Probe Scripts\n\nWrite one-off scripts in a temporary file or temporary directory such as one created by `mktemp -d`. Keep the script outside the repository by default, even when it imports code from the repository.\n\nFor `ioredis`, a disposable runtime probe should stay disposable. Do not add a package script, modify build config, or create a checked-in benchmark or example unless the user explicitly asks for a reusable repository artifact.\n\nFor `ioredis`, the default authoring loop should be:\n\n1. `tmpdir=$(mktemp -d)`\n2. Write `probe.ts` and `tsconfig.json` into `$tmpdir`\n3. From the repository root, run `npx tsc --noEmit -p \"$tmpdir/tsconfig.json\"`\n4. If the quick typecheck passes, run `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register \"$tmpdir/probe.ts\"`\n5. Only run `npm run build` if the probe intentionally imports `built/` or validates packaged output\n\nUse a temporary `tsconfig.json` that extends the repository base settings but includes only the disposable probe, for example:\n\n```json\n{\n  \"extends\": \"/absolute/path/to/ioredis/tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"types\": [\"node\"],\n    \"typeRoots\": [\"/absolute/path/to/ioredis/node_modules/@types\"]\n  },\n  \"include\": [\"./probe.ts\"]\n}\n```\n\nIf the probe needs repository code:\n\n- Run it with the repository root as the working directory.\n- Use `TS_NODE_TRANSPILE_ONLY=true node -r ts-node/register /tmp/probe.ts` from the repository root when practical.\n- Use `npx tsc --noEmit -p /tmp/probe-tsconfig.json` as the default quick typecheck step before executing the probe.\n- Import repository modules with an absolute path built from `process.cwd()` and a repo-relative path. Do not assume bare imports such as `ioredis` will resolve to the current checkout from `/tmp`.\n- Use `lib/` imports for current-branch behavior probes and `built/` imports for packaged-output probes.\n\nDesign the probe to maximize observability:\n\n- Print or log the exact scenario being exercised.\n- Capture runtime context such as git SHA, working directory, Node executable and version, relevant package versions, model or deployment name, endpoint or base URL alias, and any retry or tool options that materially affect behavior.\n- For live probes, record only the names of environment variables that were approved for use. Never print their values.\n- Capture structured outputs when possible.\n- Preserve raw error type, message, and status code.\n- For repeat-sensitive cases, capture the attempt index, warm-up status, and any stable identifiers that help compare runs.\n- For repeated or benchmark-style probes, write both raw results and a compact summary artifact when practical.\n- Keep branching minimal so each script answers a narrow question.\n\nBefore deleting the temporary script or directory, keep a short run summary of the script path, command used, runtime context, and whether the evidence was kept or deleted.\n\nOpen [typescript_probe.ts](./templates/typescript_probe.ts) when you want a lightweight disposable TypeScript probe scaffold. Open [repo-import-patterns.md](./references/repo-import-patterns.md) when you need to load current-branch workspace code from a temporary script.\n\n## Reporting\n\nReport in this order:\n\n1. Findings. Put unexpected or negative findings first. If there was no real news, say that explicitly.\n2. Validation approach. Summarize the code used, the runtime surface exercised, the execution modes, and the case matrix coverage.\n3. Case results. Include the matrix or a condensed version of it when the case count is large.\n4. Artifact status and brief run summary. State whether temporary artifacts were deleted or kept, and provide kept paths or the retained summary.\n5. Optional implementation note. Include this only when one clear defect was isolated and a short implementation direction would help.\n\nFor comparative probes, the report should also say what was held constant, what variable was under test, and whether the result supports only pattern parity or a broader quality claim.\n\nOpen [reporting-format.md](./references/reporting-format.md) for the recommended response template.\n\n## Resources\n\n- Open [validation-matrix.md](./references/validation-matrix.md) to design and prioritize the case matrix.\n- Open [error-cases.md](./references/error-cases.md) to expand common failure scenarios.\n- Open [redis-runtime-patterns.md](./references/redis-runtime-patterns.md) for recurring ioredis runtime probe patterns.\n- Open [repo-import-patterns.md](./references/repo-import-patterns.md) for repository-relative TypeScript import guidance.\n- Open [reporting-format.md](./references/reporting-format.md) for the final report structure.\n- Open [typescript_probe.ts](./templates/typescript_probe.ts) for a minimal disposable TypeScript probe scaffold.\n</yakaai_skills>"}