[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-algolia-api-clients-review":3,"mdc--wo9x4d-key":37,"related-repo-algolia-api-clients-review":1461,"related-org-algolia-api-clients-review":1472},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":28,"repoUrl":29,"updatedAt":30,"license":31,"forks":28,"topics":32,"repo":33,"sourceUrl":29,"mdContent":36},"api-clients-review","review API client pull requests","Review a PR (current branch or a given PR number) against the custom checklist plus a general review (correctness, conventions, performance, test coverage, security)",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"algolia","Algolia","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Falgolia.png",[12,16,19,22,25],{"name":13,"slug":14,"type":15},"Security","security","tag",{"name":17,"slug":18,"type":15},"Performance","performance",{"name":20,"slug":21,"type":15},"Code Review","code-review",{"name":23,"slug":24,"type":15},"API Development","api-development",{"name":26,"slug":27,"type":15},"Testing","testing",0,"https:\u002F\u002Fgithub.com\u002Falgolia\u002Fapi-clients-review","2026-08-27T13:31:47.364521",null,[],{"repoUrl":29,"stars":28,"forks":28,"topics":34,"description":35},[],"PR review checklist skill for coding agents, installable via npx skills","---\nname: api-clients-review\ndescription: Review a PR (current branch or a given PR number) against the custom checklist plus a general review (correctness, conventions, performance, test coverage, security)\nargument-hint: \"[pr number]\"\n---\n\n# Claude PR review checklist\n\nYou are reviewing a pull request in two passes: the custom checklist below, then a general review pass. Within the checklist pass, stay strictly within the six rules. Do not propose stylistic or speculative changes outside this list, do not rewrite code that already meets the standard, and do not pad the report with generic praise.\n\nRead the full PR diff first, then read enough surrounding files to judge each finding in context before flagging anything.\n\n## 0. Resolve the review target\n\nThe review target is `$ARGUMENTS`.\n\n- If it is non-empty, the first token is the pull request number or URL (strip any backticks and a leading `#`); anything after it is additional instructions from the user.\n- If it is empty, review the current branch's PR. If the current branch has no PR, run `gh pr list` to show the open pull requests, then ask the user which one to review (`\u002Fapi-clients-review \u003Cnumber>`).\n\nWhen the target is an explicit PR number or URL, the review runs in **remote mode**: the PR's diff is the only review scope — local working-tree changes are out of scope. When you need surrounding code, Read the files in this checkout if it matches the PR's branch; otherwise run `git fetch origin \u003Chead-branch>` and read via `git show origin\u002F\u003Chead-branch>:\u003Cpath>` (preferred when reading several files), or fetch file contents via `gh`.\n\nWhen the target is the current branch's PR, the review runs in **local mode** and also covers unpushed changes, as described below.\n\n## Progress checklist\n\nTrack progress by printing the checklist in your response as you work. Use the emoji markers below — **never** use `- [ ]` \u002F `- [x]` markdown checkboxes.\n\n- ⏳ Read repo review instructions (.github\u002Fclaude-review-instructions.md) — skip if the file does not exist\n- ⏳ Resolve review target (argument or current branch)\n- ⏳ Read full PR diff\n- ⏳ Apply review rules (test correctness, dead\u002Fobsolete surface, template output, config mutation, documentation quality, cross-language consistency)\n- ⏳ General review pass (correctness, conventions, performance, test coverage, security)\n- ⏳ Save review\n\nReplace the `⏳` with `✅` as each item completes.\n\n## 1. Identify what changed\n\nIf the repository has `.github\u002Fclaude-review-instructions.md`, read it first and apply its instructions on top of this checklist. If it does not exist, mark the progress item done and continue — its absence is normal.\n\nRun `gh pr view \u003Cnumber> --json title,body,author,baseRefName,headRefName,state,additions,deletions,changedFiles,labels` to get the PR context (omit `\u003Cnumber>` in local mode to use the current branch's PR).\n\nRun `gh pr diff \u003Cnumber>` to get the pushed diff (in local mode, `gh pr diff` or `git diff origin\u002F\u003Cbase>...HEAD`).\n\n**Local mode only — also collect local unpushed changes:** run `git diff HEAD` (unstaged) and `git diff --cached` (staged) to capture any changes that exist locally but haven't been pushed yet. Merge these with the pushed diff — if a file appears in both, the local version takes precedence (it is the more recent state). In remote mode, skip this entirely: local working-tree changes are out of scope.\n\n**Collect PR comments:** run `gh pr view \u003Cnumber> --json comments,reviews,reviewRequests` to fetch all existing review comments and inline threads. Then run `gh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{number}\u002Fcomments` to get inline review thread comments. Use these as context: still flag every issue caught by the checklist rules, but annotate findings that reviewers have already raised with *(raised by @reviewer — unresolved)* so the author knows they are independently confirmed. Only suppress a finding if it was raised AND already fixed in a subsequent commit.\n\n**Skip generated files in both diffs.** A file is considered generated if it matches any of these patterns:\n- `tests\u002Foutput\u002F**\u002Fgenerated\u002F**`\n- `clients\u002F**\u002F*Client.cs` (auto-generated client classes, not hand-authored ones)\n- Any file whose first few lines contain a `\u002F\u002F \u003Cauto-generated>`, `\u002F\u002F Code generated`, or similar machine-generated header comment.\nDo **not** review or flag findings in generated files. Do **not** flag missing regeneration — if a template changed but its generated output was not updated, that is expected and intentional.\n\nSources under `clients\u002F\u003Clang>\u002F` that are materialized from `templates\u002F` but committed by hand in the PR are in scope — review them as production code; only skip files matching the patterns above.\n\nCategorize the remaining changed files: tests (CTS vs unit), production code, public API surface, documentation. Note the languages touched.\n\nIf there are no non-generated changes, stop and report \"No changes to review.\"\n\n## 2. Apply the checklist\n\n### Rule 1 — Test correctness\n\nTests must actually exercise the behavior they claim to assert. This applies inside the Common Test Suite (CTS) **and** outside it.\n\nCTS-specific (must run deterministically across every supported language with no manual setup). Flag any test added or modified within the CTS that:\n\n- Requires manual setup — running a local server, seeding a database, copying a fixture by hand, or any step a human has to perform before CI can run.\n- Depends on a real network call, a live API key, or any external state that isn't part of the CTS harness.\n- Hardcodes credentials, environment-specific URLs, machine-local paths, timestamps, or non-deterministic values (`Date.now()`, `Math.random()`, etc.).\n- Is intentionally skipped, gated behind a `manual`\u002F`local` flag, or otherwise unable to run unattended in CI.\n\nGeneral test correctness (CTS or not). Flag any test where:\n\n- Pass criteria are asymmetric — the assertion only fires under specific conditions, so the test passes vacuously if those conditions don't hold (e.g., `if (ex is X) { Assert.X(...) }` with no fallback for the no-exception or wrong-exception cases).\n- Exceptions are caught and swallowed without re-asserting — the test passes if no exception is thrown OR if the wrong exception is thrown.\n- Mocks or fixtures no longer match the code path, so the assertion runs against stale data and would pass even if the production code were broken.\n\n### Rule 2 — No dead or obsolete surface area\n\nFlag any newly added public method, exported function, class, type, or API endpoint that is not invoked by tests, snippets, or other production code in the same PR. New public surface must have a real caller and a non-trivial implementation. Specifically flag:\n\n- Methods whose body is empty, returns a constant placeholder, or throws \"not implemented\".\n- New exports that no other file imports.\n- API endpoints that are declared but unrouted, or routed but never called.\n- Parameters that are accepted but never read.\n- Newly added methods or exports that carry a deprecation annotation — if no pre-existing callers exist in the codebase, there is nothing to migrate; flag as dead surface added to immediately retire.\n- Public methods that accept an object or nil at a boundary but would crash with an unguided internal error (NoMethodError, NullPointerException, AttributeError, etc.) on nil rather than raising a clean error at the call site. Use Grep to check whether nil is guarded before it reaches internal code.\n- Public APIs that silently coerce unvalidated input (e.g., unknown hash keys silently dropped, unexpected types silently cast) where a caller mistake would be invisible at the call site.\n- Newly added wrapper types (classes\u002Fstructs named `Options`, `Config`, `Settings`, etc.) that are only ever used as a property of exactly one other type — grep to confirm there is only one consumer. If so, flag: the fields should either be flattened into the containing type (preferred when the language has object-initializer or named-argument support) or the wrapper renamed to include the containing type's name in its own name (e.g. `TransformationOptions` not `ClientOptions`), so the scope is unambiguous. A generic name on a single-use wrapper type misleads callers and clashes with similarly named primitives in other languages.\n\nAdditionally, flag breaking changes to existing public API:\n\n- **Dart named parameters**: adding a new optional named parameter to an existing method is NOT a breaking change (callers use names, not positions). However, **removing** an existing named parameter IS a breaking change even if it was dead\u002Funused — existing callers who pass it by name will get a compile error. The correct approach is to deprecate it first (`@Deprecated`), not remove it outright. Flag any removal of a named parameter from an existing public method.\n- **Parameter ordering**: new parameters must be added after all pre-existing parameters. Inserting a new parameter before an existing one displaces it and is a style violation — flag it. Check the surrounding methods in the same file to learn the project's ordering convention (e.g. in this repo's Dart helpers, `requestOptions` is always last).\n- **Type widening to nullable**: changing a public field or property from a non-nullable type to its nullable equivalent (e.g. `Duration` → `Duration?`, `String` → `String?`, `int` → `int?`, `T` → `T?`) is a breaking change in any language with null-safety (Dart, Swift, Kotlin). Existing callers that assign the field to a non-nullable variable, or call methods directly on it without a null check, will get a compile error. Flag any such change and verify it is intentional — if it is, the PR description must explain why and what callers need to update.\n\nAdditionally, flag obsolete API still in use:\n\n- Methods marked `[Obsolete]` \u002F `@Deprecated` \u002F `@deprecated` that are still called by code in the same PR — including generated CTS, snippets, and examples. The deprecation isn't complete until callers migrate.\n- Public surface removed (or renamed) in this PR but still referenced by code that wasn't updated.\n- Deprecated methods whose body was changed from the pre-existing implementation. A deprecation shim must preserve the original behavior exactly — it exists so that existing callers are not silently broken while they migrate. Flag any deprecated wrapper that: (a) changes observable behavior compared to the pre-PR implementation (different defaults, different side effects, forwarded arguments now ignored), or (b) silently drops parameters that had real effects in the old code (e.g., a logger factory that previously controlled logging now being ignored). The `@deprecated` \u002F `[Obsolete]` message may document the difference, but that doesn't make the silent regression acceptable — the old code path should be preserved in the shim body. The one permitted improvement: a dropped parameter may fall back to a reasonable stored default rather than null (e.g. `factory ?? _loggerFactory`) as long as the net behavior for callers who did pass a value is unchanged.\n\nUse `Grep` to confirm zero callers (for new-but-unused) or to find the callers (for obsolete-but-called) before flagging.\n\n### Rule 3 — Template output correctness\n\nFor any change to a code-generation template (Mustache, Jinja, ERB, etc.), verify that the generated output would still compile. Specifically flag:\n\n- Imports or `require`\u002F`use` statements added to a template that have no corresponding usage of the imported symbol in the same template body — they will produce unused-import compile errors in every generated file.\n- Imports or `require`\u002F`use` statements that are not gated by the same conditional block (`{{#isSearchClient}}`, `{% if %}`, etc.) as the only code that uses them — they will produce unused-import errors in generated files where that condition is false.\n- Symbol references in a template that were removed or renamed elsewhere in the same PR without updating the template — they will produce undefined-symbol errors in generated output.\n\nBefore flagging, grep the template body for any usage of the imported symbol to confirm it is genuinely absent.\n\n### Rule 4 — Config mutation correctness\n\nFor any code (template or hand-authored) that applies user-supplied overrides to a freshly constructed config or options object, verify that collection properties are merged rather than replaced. Specifically flag:\n\n- Assignments of the form `config.Headers = userHeaders` (or equivalent in any language) where the constructor already populates that collection with required defaults (auth headers, user-agent, etc.) — the assignment silently wipes the defaults, so requests go out missing credentials or required metadata.\n- The correct pattern is to iterate over the user-supplied entries and set them individually (`foreach (var kvp in userHeaders) config.Headers[kvp.Key] = kvp.Value`), so pre-initialized keys survive alongside the caller's additions.\n\nBefore flagging, check what the constructor puts into the collection (read the base class if needed) to confirm there are pre-initialized entries that would be lost.\n\n### Rule 5 — Documentation quality\n\nDocumentation must match the surrounding language's style **and** accurately describe the code it documents. Flag deviations on either axis.\n\n**Consistency** — read neighboring files in the same package\u002Fmodule first to learn the convention, then flag deviations. Do not impose an external standard — match what's already there.\n\n- JavaScript\u002FTypeScript — JSDoc with the tag set used elsewhere in the same module.\n- Python — docstrings in the same flavor (Google, NumPy, or reST) as the surrounding module.\n- Java\u002FKotlin — Javadoc\u002FKDoc with the same tag set used by neighboring classes.\n- Go — sentence-style comments starting with the identifier name, ending with a period.\n- Ruby — YARD or RDoc consistent with the surrounding files.\n- C#\u002FSwift\u002FPHP\u002FDart\u002FScala — match neighboring files. For C# specifically: every public member documented elsewhere with `\u003Csummary>` should have one; methods with `\u003Cparam>` tags on their neighbors should document each parameter.\n\n**Correctness** — the doc text must agree with the code it describes. Flag:\n\n- Wrong subject — doc refers to \"the parent X\" when the symbol IS X (copy-paste artifact from another file).\n- Stale references — `\u003Csee cref=\"...\">`, `@see`, `@link` pointing to renamed or removed symbols.\n- Parameter docs that don't match the actual parameter list (missing, extra, or wrong-named).\n- Return-value docs that don't match the actual return type.\n\nFlag missing docs only on **public** API surface where the surrounding code documents its public surface.\n\n### Rule 6 — Cross-language consistency\n\nWhen a PR adds or changes a feature in one language, find the same feature in the other languages (Python, Java, JavaScript, Scala, Go, Ruby, PHP, C#, Kotlin, Swift, Dart) and compare. Use grep to find equivalent files or templates. This rule is **the most important one** — a divergence that looks innocuous in isolation can be a silent breaking change or an API that callers from other SDKs won't recognise.\n\n**How to check**: grep for the feature name (method, class, config key) in other language client directories and helper templates. Read the corresponding implementation before judging.\n\nFlag any divergence in the following categories:\n\n- **Breaking change** — the new implementation removes, renames, or changes the signature of something that exists in other languages (e.g. a required parameter becomes optional, a method is split, a config key changes name). Even if the change is unintentional, callers porting code from another SDK will be silently surprised.\n- **Design choice** — the new implementation makes a structural decision that differs from the established pattern without a language-idiomatic reason. Examples: storing configuration on the config object vs. on the client; using a factory method vs. a constructor; using an optional parameter vs. a named options object. If other languages converged on a design, the new language should match unless the language's idioms actively prevent it.\n- **Idiomatic choice** — flag the *opposite* too: when the PR copies a pattern verbatim from another language but the target language has a strongly preferred idiom (e.g., using a class where the language would use a struct, ignoring nil-safety conventions, not using named parameters where the language requires them). The implementation should feel native, not like a translation.\n- **Correctness gap** — the new implementation is missing behaviour that all other languages implement (e.g., error handling for an edge case, a retry path, a header that other clients set, a fallback that other SDKs document). Check error messages: if every other language raises with the same string, the new one should too so that callers can detect errors uniformly.\n- **Completeness gap** — the new implementation adds only a subset of the methods or configuration options that other languages expose for this feature. Flag any method or option present in two or more other languages that is absent here without an explicit reason.\n\nDo **not** flag differences that are explained by the target language's type system or standard library constraints (e.g., Dart needing `async`\u002F`await` where Java uses sync APIs, Go returning errors by value). Do flag differences that have no language-idiomatic explanation.\n\n## 3. General review pass\n\nAfter the checklist, analyze the changes as a whole and provide a thorough review that includes:\n\n- An overview of what the PR does\n- Analysis of code quality and style\n- Specific suggestions for improvements\n- Any potential issues or risks\n\nKeep this pass concise but thorough. Focus on:\n\n- Code correctness\n- Following project conventions\n- Performance implications\n- Test coverage\n- Security considerations\n\nFindings from this pass that are concrete and actionable go into the report's Blocking or Suggestions sections, tagged `(general)` to distinguish them from checklist findings. The overview goes into the report's Overview section. Do not let this pass duplicate checklist findings or drift into stylistic rewrites of code that already meets the standard.\n\n## 4. Produce the report\n\nThe report must match this template **verbatim** — same headings, same bullet format, same fallback line if no findings. Do not add sections, prefaces, or summaries that aren't in the template. Use `file:line` references for every finding.\n\nThe first line of the report MUST be the HTML marker exactly as shown — it is kept so any tooling that consumes the file can find and replace its output.\n\n```\n\u003C!-- type: api-clients-review -->\n## PR Review\n\n### Overview\n\u003Ctwo to four sentences on what the PR does>\n\n### Blocking\n- `\u003Cfile>:\u003Cline>` — \u003Cone-line description>. \u003Cwhy this fails the rule>.\n…\n\n### Suggestions\n- `\u003Cfile>:\u003Cline>` — \u003Cone-line description>.\n…\n\n### Looks good\n\u003Cone or two sentences on what's solid>\n```\n\nIf a single section has no findings, its body is exactly one line — `No blocking findings.` for Blocking, `No suggestions.` for Suggestions — do not omit the section.\n\nIf no findings under any rule or the general pass, the body is exactly:\n\n```\n\u003C!-- type: api-clients-review -->\n## PR Review\n\n### Overview\n\u003Ctwo to four sentences on what the PR does>\n\nNo issues found under the review checklist.\n```\n\n## 5. Save the report\n\nSave the report to both `\u002Ftmp\u002Fapi-clients-review-{pr-number}.md` and `api-clients-review-{pr-number}.md` at the repository root — do **not** post it as a GitHub PR comment. Print the full report text in your response so the user can read it directly.\n",{"data":38,"body":40},{"name":4,"description":6,"argument-hint":39},"[pr number]",{"type":41,"children":42},"root",[43,52,58,63,70,84,123,159,171,177,205,238,259,265,278,299,326,352,385,395,452,473,478,483,489,496,508,513,567,572,598,604,609,690,695,809,814,874,887,893,898,958,963,969,974,1003,1008,1014,1025,1035,1084,1094,1139,1151,1157,1169,1179,1184,1244,1270,1276,1281,1304,1309,1337,1350,1356,1376,1381,1393,1414,1419,1428,1434],{"type":44,"tag":45,"props":46,"children":48},"element","h1",{"id":47},"claude-pr-review-checklist",[49],{"type":50,"value":51},"text","Claude PR review checklist",{"type":44,"tag":53,"props":54,"children":55},"p",{},[56],{"type":50,"value":57},"You are reviewing a pull request in two passes: the custom checklist below, then a general review pass. Within the checklist pass, stay strictly within the six rules. Do not propose stylistic or speculative changes outside this list, do not rewrite code that already meets the standard, and do not pad the report with generic praise.",{"type":44,"tag":53,"props":59,"children":60},{},[61],{"type":50,"value":62},"Read the full PR diff first, then read enough surrounding files to judge each finding in context before flagging anything.",{"type":44,"tag":64,"props":65,"children":67},"h2",{"id":66},"_0-resolve-the-review-target",[68],{"type":50,"value":69},"0. Resolve the review target",{"type":44,"tag":53,"props":71,"children":72},{},[73,75,82],{"type":50,"value":74},"The review target is ",{"type":44,"tag":76,"props":77,"children":79},"code",{"className":78},[],[80],{"type":50,"value":81},"$ARGUMENTS",{"type":50,"value":83},".",{"type":44,"tag":85,"props":86,"children":87},"ul",{},[88,102],{"type":44,"tag":89,"props":90,"children":91},"li",{},[92,94,100],{"type":50,"value":93},"If it is non-empty, the first token is the pull request number or URL (strip any backticks and a leading ",{"type":44,"tag":76,"props":95,"children":97},{"className":96},[],[98],{"type":50,"value":99},"#",{"type":50,"value":101},"); anything after it is additional instructions from the user.",{"type":44,"tag":89,"props":103,"children":104},{},[105,107,113,115,121],{"type":50,"value":106},"If it is empty, review the current branch's PR. If the current branch has no PR, run ",{"type":44,"tag":76,"props":108,"children":110},{"className":109},[],[111],{"type":50,"value":112},"gh pr list",{"type":50,"value":114}," to show the open pull requests, then ask the user which one to review (",{"type":44,"tag":76,"props":116,"children":118},{"className":117},[],[119],{"type":50,"value":120},"\u002Fapi-clients-review \u003Cnumber>",{"type":50,"value":122},").",{"type":44,"tag":53,"props":124,"children":125},{},[126,128,134,136,142,144,150,152,158],{"type":50,"value":127},"When the target is an explicit PR number or URL, the review runs in ",{"type":44,"tag":129,"props":130,"children":131},"strong",{},[132],{"type":50,"value":133},"remote mode",{"type":50,"value":135},": the PR's diff is the only review scope — local working-tree changes are out of scope. When you need surrounding code, Read the files in this checkout if it matches the PR's branch; otherwise run ",{"type":44,"tag":76,"props":137,"children":139},{"className":138},[],[140],{"type":50,"value":141},"git fetch origin \u003Chead-branch>",{"type":50,"value":143}," and read via ",{"type":44,"tag":76,"props":145,"children":147},{"className":146},[],[148],{"type":50,"value":149},"git show origin\u002F\u003Chead-branch>:\u003Cpath>",{"type":50,"value":151}," (preferred when reading several files), or fetch file contents via ",{"type":44,"tag":76,"props":153,"children":155},{"className":154},[],[156],{"type":50,"value":157},"gh",{"type":50,"value":83},{"type":44,"tag":53,"props":160,"children":161},{},[162,164,169],{"type":50,"value":163},"When the target is the current branch's PR, the review runs in ",{"type":44,"tag":129,"props":165,"children":166},{},[167],{"type":50,"value":168},"local mode",{"type":50,"value":170}," and also covers unpushed changes, as described below.",{"type":44,"tag":64,"props":172,"children":174},{"id":173},"progress-checklist",[175],{"type":50,"value":176},"Progress checklist",{"type":44,"tag":53,"props":178,"children":179},{},[180,182,187,189,195,197,203],{"type":50,"value":181},"Track progress by printing the checklist in your response as you work. Use the emoji markers below — ",{"type":44,"tag":129,"props":183,"children":184},{},[185],{"type":50,"value":186},"never",{"type":50,"value":188}," use ",{"type":44,"tag":76,"props":190,"children":192},{"className":191},[],[193],{"type":50,"value":194},"- [ ]",{"type":50,"value":196}," \u002F ",{"type":44,"tag":76,"props":198,"children":200},{"className":199},[],[201],{"type":50,"value":202},"- [x]",{"type":50,"value":204}," markdown checkboxes.",{"type":44,"tag":85,"props":206,"children":207},{},[208,213,218,223,228,233],{"type":44,"tag":89,"props":209,"children":210},{},[211],{"type":50,"value":212},"⏳ Read repo review instructions (.github\u002Fclaude-review-instructions.md) — skip if the file does not exist",{"type":44,"tag":89,"props":214,"children":215},{},[216],{"type":50,"value":217},"⏳ Resolve review target (argument or current branch)",{"type":44,"tag":89,"props":219,"children":220},{},[221],{"type":50,"value":222},"⏳ Read full PR diff",{"type":44,"tag":89,"props":224,"children":225},{},[226],{"type":50,"value":227},"⏳ Apply review rules (test correctness, dead\u002Fobsolete surface, template output, config mutation, documentation quality, cross-language consistency)",{"type":44,"tag":89,"props":229,"children":230},{},[231],{"type":50,"value":232},"⏳ General review pass (correctness, conventions, performance, test coverage, security)",{"type":44,"tag":89,"props":234,"children":235},{},[236],{"type":50,"value":237},"⏳ Save review",{"type":44,"tag":53,"props":239,"children":240},{},[241,243,249,251,257],{"type":50,"value":242},"Replace the ",{"type":44,"tag":76,"props":244,"children":246},{"className":245},[],[247],{"type":50,"value":248},"⏳",{"type":50,"value":250}," with ",{"type":44,"tag":76,"props":252,"children":254},{"className":253},[],[255],{"type":50,"value":256},"✅",{"type":50,"value":258}," as each item completes.",{"type":44,"tag":64,"props":260,"children":262},{"id":261},"_1-identify-what-changed",[263],{"type":50,"value":264},"1. Identify what changed",{"type":44,"tag":53,"props":266,"children":267},{},[268,270,276],{"type":50,"value":269},"If the repository has ",{"type":44,"tag":76,"props":271,"children":273},{"className":272},[],[274],{"type":50,"value":275},".github\u002Fclaude-review-instructions.md",{"type":50,"value":277},", read it first and apply its instructions on top of this checklist. If it does not exist, mark the progress item done and continue — its absence is normal.",{"type":44,"tag":53,"props":279,"children":280},{},[281,283,289,291,297],{"type":50,"value":282},"Run ",{"type":44,"tag":76,"props":284,"children":286},{"className":285},[],[287],{"type":50,"value":288},"gh pr view \u003Cnumber> --json title,body,author,baseRefName,headRefName,state,additions,deletions,changedFiles,labels",{"type":50,"value":290}," to get the PR context (omit ",{"type":44,"tag":76,"props":292,"children":294},{"className":293},[],[295],{"type":50,"value":296},"\u003Cnumber>",{"type":50,"value":298}," in local mode to use the current branch's PR).",{"type":44,"tag":53,"props":300,"children":301},{},[302,303,309,311,317,319,325],{"type":50,"value":282},{"type":44,"tag":76,"props":304,"children":306},{"className":305},[],[307],{"type":50,"value":308},"gh pr diff \u003Cnumber>",{"type":50,"value":310}," to get the pushed diff (in local mode, ",{"type":44,"tag":76,"props":312,"children":314},{"className":313},[],[315],{"type":50,"value":316},"gh pr diff",{"type":50,"value":318}," or ",{"type":44,"tag":76,"props":320,"children":322},{"className":321},[],[323],{"type":50,"value":324},"git diff origin\u002F\u003Cbase>...HEAD",{"type":50,"value":122},{"type":44,"tag":53,"props":327,"children":328},{},[329,334,336,342,344,350],{"type":44,"tag":129,"props":330,"children":331},{},[332],{"type":50,"value":333},"Local mode only — also collect local unpushed changes:",{"type":50,"value":335}," run ",{"type":44,"tag":76,"props":337,"children":339},{"className":338},[],[340],{"type":50,"value":341},"git diff HEAD",{"type":50,"value":343}," (unstaged) and ",{"type":44,"tag":76,"props":345,"children":347},{"className":346},[],[348],{"type":50,"value":349},"git diff --cached",{"type":50,"value":351}," (staged) to capture any changes that exist locally but haven't been pushed yet. Merge these with the pushed diff — if a file appears in both, the local version takes precedence (it is the more recent state). In remote mode, skip this entirely: local working-tree changes are out of scope.",{"type":44,"tag":53,"props":353,"children":354},{},[355,360,361,367,369,375,377,383],{"type":44,"tag":129,"props":356,"children":357},{},[358],{"type":50,"value":359},"Collect PR comments:",{"type":50,"value":335},{"type":44,"tag":76,"props":362,"children":364},{"className":363},[],[365],{"type":50,"value":366},"gh pr view \u003Cnumber> --json comments,reviews,reviewRequests",{"type":50,"value":368}," to fetch all existing review comments and inline threads. Then run ",{"type":44,"tag":76,"props":370,"children":372},{"className":371},[],[373],{"type":50,"value":374},"gh api repos\u002F{owner}\u002F{repo}\u002Fpulls\u002F{number}\u002Fcomments",{"type":50,"value":376}," to get inline review thread comments. Use these as context: still flag every issue caught by the checklist rules, but annotate findings that reviewers have already raised with ",{"type":44,"tag":378,"props":379,"children":380},"em",{},[381],{"type":50,"value":382},"(raised by @reviewer — unresolved)",{"type":50,"value":384}," so the author knows they are independently confirmed. Only suppress a finding if it was raised AND already fixed in a subsequent commit.",{"type":44,"tag":53,"props":386,"children":387},{},[388,393],{"type":44,"tag":129,"props":389,"children":390},{},[391],{"type":50,"value":392},"Skip generated files in both diffs.",{"type":50,"value":394}," A file is considered generated if it matches any of these patterns:",{"type":44,"tag":85,"props":396,"children":397},{},[398,407,418],{"type":44,"tag":89,"props":399,"children":400},{},[401],{"type":44,"tag":76,"props":402,"children":404},{"className":403},[],[405],{"type":50,"value":406},"tests\u002Foutput\u002F**\u002Fgenerated\u002F**",{"type":44,"tag":89,"props":408,"children":409},{},[410,416],{"type":44,"tag":76,"props":411,"children":413},{"className":412},[],[414],{"type":50,"value":415},"clients\u002F**\u002F*Client.cs",{"type":50,"value":417}," (auto-generated client classes, not hand-authored ones)",{"type":44,"tag":89,"props":419,"children":420},{},[421,423,429,431,437,439,444,446,450],{"type":50,"value":422},"Any file whose first few lines contain a ",{"type":44,"tag":76,"props":424,"children":426},{"className":425},[],[427],{"type":50,"value":428},"\u002F\u002F \u003Cauto-generated>",{"type":50,"value":430},", ",{"type":44,"tag":76,"props":432,"children":434},{"className":433},[],[435],{"type":50,"value":436},"\u002F\u002F Code generated",{"type":50,"value":438},", or similar machine-generated header comment.\nDo ",{"type":44,"tag":129,"props":440,"children":441},{},[442],{"type":50,"value":443},"not",{"type":50,"value":445}," review or flag findings in generated files. Do ",{"type":44,"tag":129,"props":447,"children":448},{},[449],{"type":50,"value":443},{"type":50,"value":451}," flag missing regeneration — if a template changed but its generated output was not updated, that is expected and intentional.",{"type":44,"tag":53,"props":453,"children":454},{},[455,457,463,465,471],{"type":50,"value":456},"Sources under ",{"type":44,"tag":76,"props":458,"children":460},{"className":459},[],[461],{"type":50,"value":462},"clients\u002F\u003Clang>\u002F",{"type":50,"value":464}," that are materialized from ",{"type":44,"tag":76,"props":466,"children":468},{"className":467},[],[469],{"type":50,"value":470},"templates\u002F",{"type":50,"value":472}," but committed by hand in the PR are in scope — review them as production code; only skip files matching the patterns above.",{"type":44,"tag":53,"props":474,"children":475},{},[476],{"type":50,"value":477},"Categorize the remaining changed files: tests (CTS vs unit), production code, public API surface, documentation. Note the languages touched.",{"type":44,"tag":53,"props":479,"children":480},{},[481],{"type":50,"value":482},"If there are no non-generated changes, stop and report \"No changes to review.\"",{"type":44,"tag":64,"props":484,"children":486},{"id":485},"_2-apply-the-checklist",[487],{"type":50,"value":488},"2. Apply the checklist",{"type":44,"tag":490,"props":491,"children":493},"h3",{"id":492},"rule-1-test-correctness",[494],{"type":50,"value":495},"Rule 1 — Test correctness",{"type":44,"tag":53,"props":497,"children":498},{},[499,501,506],{"type":50,"value":500},"Tests must actually exercise the behavior they claim to assert. This applies inside the Common Test Suite (CTS) ",{"type":44,"tag":129,"props":502,"children":503},{},[504],{"type":50,"value":505},"and",{"type":50,"value":507}," outside it.",{"type":44,"tag":53,"props":509,"children":510},{},[511],{"type":50,"value":512},"CTS-specific (must run deterministically across every supported language with no manual setup). Flag any test added or modified within the CTS that:",{"type":44,"tag":85,"props":514,"children":515},{},[516,521,526,546],{"type":44,"tag":89,"props":517,"children":518},{},[519],{"type":50,"value":520},"Requires manual setup — running a local server, seeding a database, copying a fixture by hand, or any step a human has to perform before CI can run.",{"type":44,"tag":89,"props":522,"children":523},{},[524],{"type":50,"value":525},"Depends on a real network call, a live API key, or any external state that isn't part of the CTS harness.",{"type":44,"tag":89,"props":527,"children":528},{},[529,531,537,538,544],{"type":50,"value":530},"Hardcodes credentials, environment-specific URLs, machine-local paths, timestamps, or non-deterministic values (",{"type":44,"tag":76,"props":532,"children":534},{"className":533},[],[535],{"type":50,"value":536},"Date.now()",{"type":50,"value":430},{"type":44,"tag":76,"props":539,"children":541},{"className":540},[],[542],{"type":50,"value":543},"Math.random()",{"type":50,"value":545},", etc.).",{"type":44,"tag":89,"props":547,"children":548},{},[549,551,557,559,565],{"type":50,"value":550},"Is intentionally skipped, gated behind a ",{"type":44,"tag":76,"props":552,"children":554},{"className":553},[],[555],{"type":50,"value":556},"manual",{"type":50,"value":558},"\u002F",{"type":44,"tag":76,"props":560,"children":562},{"className":561},[],[563],{"type":50,"value":564},"local",{"type":50,"value":566}," flag, or otherwise unable to run unattended in CI.",{"type":44,"tag":53,"props":568,"children":569},{},[570],{"type":50,"value":571},"General test correctness (CTS or not). Flag any test where:",{"type":44,"tag":85,"props":573,"children":574},{},[575,588,593],{"type":44,"tag":89,"props":576,"children":577},{},[578,580,586],{"type":50,"value":579},"Pass criteria are asymmetric — the assertion only fires under specific conditions, so the test passes vacuously if those conditions don't hold (e.g., ",{"type":44,"tag":76,"props":581,"children":583},{"className":582},[],[584],{"type":50,"value":585},"if (ex is X) { Assert.X(...) }",{"type":50,"value":587}," with no fallback for the no-exception or wrong-exception cases).",{"type":44,"tag":89,"props":589,"children":590},{},[591],{"type":50,"value":592},"Exceptions are caught and swallowed without re-asserting — the test passes if no exception is thrown OR if the wrong exception is thrown.",{"type":44,"tag":89,"props":594,"children":595},{},[596],{"type":50,"value":597},"Mocks or fixtures no longer match the code path, so the assertion runs against stale data and would pass even if the production code were broken.",{"type":44,"tag":490,"props":599,"children":601},{"id":600},"rule-2-no-dead-or-obsolete-surface-area",[602],{"type":50,"value":603},"Rule 2 — No dead or obsolete surface area",{"type":44,"tag":53,"props":605,"children":606},{},[607],{"type":50,"value":608},"Flag any newly added public method, exported function, class, type, or API endpoint that is not invoked by tests, snippets, or other production code in the same PR. New public surface must have a real caller and a non-trivial implementation. Specifically flag:",{"type":44,"tag":85,"props":610,"children":611},{},[612,617,622,627,632,637,642,647],{"type":44,"tag":89,"props":613,"children":614},{},[615],{"type":50,"value":616},"Methods whose body is empty, returns a constant placeholder, or throws \"not implemented\".",{"type":44,"tag":89,"props":618,"children":619},{},[620],{"type":50,"value":621},"New exports that no other file imports.",{"type":44,"tag":89,"props":623,"children":624},{},[625],{"type":50,"value":626},"API endpoints that are declared but unrouted, or routed but never called.",{"type":44,"tag":89,"props":628,"children":629},{},[630],{"type":50,"value":631},"Parameters that are accepted but never read.",{"type":44,"tag":89,"props":633,"children":634},{},[635],{"type":50,"value":636},"Newly added methods or exports that carry a deprecation annotation — if no pre-existing callers exist in the codebase, there is nothing to migrate; flag as dead surface added to immediately retire.",{"type":44,"tag":89,"props":638,"children":639},{},[640],{"type":50,"value":641},"Public methods that accept an object or nil at a boundary but would crash with an unguided internal error (NoMethodError, NullPointerException, AttributeError, etc.) on nil rather than raising a clean error at the call site. Use Grep to check whether nil is guarded before it reaches internal code.",{"type":44,"tag":89,"props":643,"children":644},{},[645],{"type":50,"value":646},"Public APIs that silently coerce unvalidated input (e.g., unknown hash keys silently dropped, unexpected types silently cast) where a caller mistake would be invisible at the call site.",{"type":44,"tag":89,"props":648,"children":649},{},[650,652,658,659,665,666,672,674,680,682,688],{"type":50,"value":651},"Newly added wrapper types (classes\u002Fstructs named ",{"type":44,"tag":76,"props":653,"children":655},{"className":654},[],[656],{"type":50,"value":657},"Options",{"type":50,"value":430},{"type":44,"tag":76,"props":660,"children":662},{"className":661},[],[663],{"type":50,"value":664},"Config",{"type":50,"value":430},{"type":44,"tag":76,"props":667,"children":669},{"className":668},[],[670],{"type":50,"value":671},"Settings",{"type":50,"value":673},", etc.) that are only ever used as a property of exactly one other type — grep to confirm there is only one consumer. If so, flag: the fields should either be flattened into the containing type (preferred when the language has object-initializer or named-argument support) or the wrapper renamed to include the containing type's name in its own name (e.g. ",{"type":44,"tag":76,"props":675,"children":677},{"className":676},[],[678],{"type":50,"value":679},"TransformationOptions",{"type":50,"value":681}," not ",{"type":44,"tag":76,"props":683,"children":685},{"className":684},[],[686],{"type":50,"value":687},"ClientOptions",{"type":50,"value":689},"), so the scope is unambiguous. A generic name on a single-use wrapper type misleads callers and clashes with similarly named primitives in other languages.",{"type":44,"tag":53,"props":691,"children":692},{},[693],{"type":50,"value":694},"Additionally, flag breaking changes to existing public API:",{"type":44,"tag":85,"props":696,"children":697},{},[698,723,741],{"type":44,"tag":89,"props":699,"children":700},{},[701,706,708,713,715,721],{"type":44,"tag":129,"props":702,"children":703},{},[704],{"type":50,"value":705},"Dart named parameters",{"type":50,"value":707},": adding a new optional named parameter to an existing method is NOT a breaking change (callers use names, not positions). However, ",{"type":44,"tag":129,"props":709,"children":710},{},[711],{"type":50,"value":712},"removing",{"type":50,"value":714}," an existing named parameter IS a breaking change even if it was dead\u002Funused — existing callers who pass it by name will get a compile error. The correct approach is to deprecate it first (",{"type":44,"tag":76,"props":716,"children":718},{"className":717},[],[719],{"type":50,"value":720},"@Deprecated",{"type":50,"value":722},"), not remove it outright. Flag any removal of a named parameter from an existing public method.",{"type":44,"tag":89,"props":724,"children":725},{},[726,731,733,739],{"type":44,"tag":129,"props":727,"children":728},{},[729],{"type":50,"value":730},"Parameter ordering",{"type":50,"value":732},": new parameters must be added after all pre-existing parameters. Inserting a new parameter before an existing one displaces it and is a style violation — flag it. Check the surrounding methods in the same file to learn the project's ordering convention (e.g. in this repo's Dart helpers, ",{"type":44,"tag":76,"props":734,"children":736},{"className":735},[],[737],{"type":50,"value":738},"requestOptions",{"type":50,"value":740}," is always last).",{"type":44,"tag":89,"props":742,"children":743},{},[744,749,751,757,759,765,766,772,773,779,780,786,787,793,794,800,801,807],{"type":44,"tag":129,"props":745,"children":746},{},[747],{"type":50,"value":748},"Type widening to nullable",{"type":50,"value":750},": changing a public field or property from a non-nullable type to its nullable equivalent (e.g. ",{"type":44,"tag":76,"props":752,"children":754},{"className":753},[],[755],{"type":50,"value":756},"Duration",{"type":50,"value":758}," → ",{"type":44,"tag":76,"props":760,"children":762},{"className":761},[],[763],{"type":50,"value":764},"Duration?",{"type":50,"value":430},{"type":44,"tag":76,"props":767,"children":769},{"className":768},[],[770],{"type":50,"value":771},"String",{"type":50,"value":758},{"type":44,"tag":76,"props":774,"children":776},{"className":775},[],[777],{"type":50,"value":778},"String?",{"type":50,"value":430},{"type":44,"tag":76,"props":781,"children":783},{"className":782},[],[784],{"type":50,"value":785},"int",{"type":50,"value":758},{"type":44,"tag":76,"props":788,"children":790},{"className":789},[],[791],{"type":50,"value":792},"int?",{"type":50,"value":430},{"type":44,"tag":76,"props":795,"children":797},{"className":796},[],[798],{"type":50,"value":799},"T",{"type":50,"value":758},{"type":44,"tag":76,"props":802,"children":804},{"className":803},[],[805],{"type":50,"value":806},"T?",{"type":50,"value":808},") is a breaking change in any language with null-safety (Dart, Swift, Kotlin). Existing callers that assign the field to a non-nullable variable, or call methods directly on it without a null check, will get a compile error. Flag any such change and verify it is intentional — if it is, the PR description must explain why and what callers need to update.",{"type":44,"tag":53,"props":810,"children":811},{},[812],{"type":50,"value":813},"Additionally, flag obsolete API still in use:",{"type":44,"tag":85,"props":815,"children":816},{},[817,843,848],{"type":44,"tag":89,"props":818,"children":819},{},[820,822,828,829,834,835,841],{"type":50,"value":821},"Methods marked ",{"type":44,"tag":76,"props":823,"children":825},{"className":824},[],[826],{"type":50,"value":827},"[Obsolete]",{"type":50,"value":196},{"type":44,"tag":76,"props":830,"children":832},{"className":831},[],[833],{"type":50,"value":720},{"type":50,"value":196},{"type":44,"tag":76,"props":836,"children":838},{"className":837},[],[839],{"type":50,"value":840},"@deprecated",{"type":50,"value":842}," that are still called by code in the same PR — including generated CTS, snippets, and examples. The deprecation isn't complete until callers migrate.",{"type":44,"tag":89,"props":844,"children":845},{},[846],{"type":50,"value":847},"Public surface removed (or renamed) in this PR but still referenced by code that wasn't updated.",{"type":44,"tag":89,"props":849,"children":850},{},[851,853,858,859,864,866,872],{"type":50,"value":852},"Deprecated methods whose body was changed from the pre-existing implementation. A deprecation shim must preserve the original behavior exactly — it exists so that existing callers are not silently broken while they migrate. Flag any deprecated wrapper that: (a) changes observable behavior compared to the pre-PR implementation (different defaults, different side effects, forwarded arguments now ignored), or (b) silently drops parameters that had real effects in the old code (e.g., a logger factory that previously controlled logging now being ignored). The ",{"type":44,"tag":76,"props":854,"children":856},{"className":855},[],[857],{"type":50,"value":840},{"type":50,"value":196},{"type":44,"tag":76,"props":860,"children":862},{"className":861},[],[863],{"type":50,"value":827},{"type":50,"value":865}," message may document the difference, but that doesn't make the silent regression acceptable — the old code path should be preserved in the shim body. The one permitted improvement: a dropped parameter may fall back to a reasonable stored default rather than null (e.g. ",{"type":44,"tag":76,"props":867,"children":869},{"className":868},[],[870],{"type":50,"value":871},"factory ?? _loggerFactory",{"type":50,"value":873},") as long as the net behavior for callers who did pass a value is unchanged.",{"type":44,"tag":53,"props":875,"children":876},{},[877,879,885],{"type":50,"value":878},"Use ",{"type":44,"tag":76,"props":880,"children":882},{"className":881},[],[883],{"type":50,"value":884},"Grep",{"type":50,"value":886}," to confirm zero callers (for new-but-unused) or to find the callers (for obsolete-but-called) before flagging.",{"type":44,"tag":490,"props":888,"children":890},{"id":889},"rule-3-template-output-correctness",[891],{"type":50,"value":892},"Rule 3 — Template output correctness",{"type":44,"tag":53,"props":894,"children":895},{},[896],{"type":50,"value":897},"For any change to a code-generation template (Mustache, Jinja, ERB, etc.), verify that the generated output would still compile. Specifically flag:",{"type":44,"tag":85,"props":899,"children":900},{},[901,921,953],{"type":44,"tag":89,"props":902,"children":903},{},[904,906,912,913,919],{"type":50,"value":905},"Imports or ",{"type":44,"tag":76,"props":907,"children":909},{"className":908},[],[910],{"type":50,"value":911},"require",{"type":50,"value":558},{"type":44,"tag":76,"props":914,"children":916},{"className":915},[],[917],{"type":50,"value":918},"use",{"type":50,"value":920}," statements added to a template that have no corresponding usage of the imported symbol in the same template body — they will produce unused-import compile errors in every generated file.",{"type":44,"tag":89,"props":922,"children":923},{},[924,925,930,931,936,938,944,945,951],{"type":50,"value":905},{"type":44,"tag":76,"props":926,"children":928},{"className":927},[],[929],{"type":50,"value":911},{"type":50,"value":558},{"type":44,"tag":76,"props":932,"children":934},{"className":933},[],[935],{"type":50,"value":918},{"type":50,"value":937}," statements that are not gated by the same conditional block (",{"type":44,"tag":76,"props":939,"children":941},{"className":940},[],[942],{"type":50,"value":943},"{{#isSearchClient}}",{"type":50,"value":430},{"type":44,"tag":76,"props":946,"children":948},{"className":947},[],[949],{"type":50,"value":950},"{% if %}",{"type":50,"value":952},", etc.) as the only code that uses them — they will produce unused-import errors in generated files where that condition is false.",{"type":44,"tag":89,"props":954,"children":955},{},[956],{"type":50,"value":957},"Symbol references in a template that were removed or renamed elsewhere in the same PR without updating the template — they will produce undefined-symbol errors in generated output.",{"type":44,"tag":53,"props":959,"children":960},{},[961],{"type":50,"value":962},"Before flagging, grep the template body for any usage of the imported symbol to confirm it is genuinely absent.",{"type":44,"tag":490,"props":964,"children":966},{"id":965},"rule-4-config-mutation-correctness",[967],{"type":50,"value":968},"Rule 4 — Config mutation correctness",{"type":44,"tag":53,"props":970,"children":971},{},[972],{"type":50,"value":973},"For any code (template or hand-authored) that applies user-supplied overrides to a freshly constructed config or options object, verify that collection properties are merged rather than replaced. Specifically flag:",{"type":44,"tag":85,"props":975,"children":976},{},[977,990],{"type":44,"tag":89,"props":978,"children":979},{},[980,982,988],{"type":50,"value":981},"Assignments of the form ",{"type":44,"tag":76,"props":983,"children":985},{"className":984},[],[986],{"type":50,"value":987},"config.Headers = userHeaders",{"type":50,"value":989}," (or equivalent in any language) where the constructor already populates that collection with required defaults (auth headers, user-agent, etc.) — the assignment silently wipes the defaults, so requests go out missing credentials or required metadata.",{"type":44,"tag":89,"props":991,"children":992},{},[993,995,1001],{"type":50,"value":994},"The correct pattern is to iterate over the user-supplied entries and set them individually (",{"type":44,"tag":76,"props":996,"children":998},{"className":997},[],[999],{"type":50,"value":1000},"foreach (var kvp in userHeaders) config.Headers[kvp.Key] = kvp.Value",{"type":50,"value":1002},"), so pre-initialized keys survive alongside the caller's additions.",{"type":44,"tag":53,"props":1004,"children":1005},{},[1006],{"type":50,"value":1007},"Before flagging, check what the constructor puts into the collection (read the base class if needed) to confirm there are pre-initialized entries that would be lost.",{"type":44,"tag":490,"props":1009,"children":1011},{"id":1010},"rule-5-documentation-quality",[1012],{"type":50,"value":1013},"Rule 5 — Documentation quality",{"type":44,"tag":53,"props":1015,"children":1016},{},[1017,1019,1023],{"type":50,"value":1018},"Documentation must match the surrounding language's style ",{"type":44,"tag":129,"props":1020,"children":1021},{},[1022],{"type":50,"value":505},{"type":50,"value":1024}," accurately describe the code it documents. Flag deviations on either axis.",{"type":44,"tag":53,"props":1026,"children":1027},{},[1028,1033],{"type":44,"tag":129,"props":1029,"children":1030},{},[1031],{"type":50,"value":1032},"Consistency",{"type":50,"value":1034}," — read neighboring files in the same package\u002Fmodule first to learn the convention, then flag deviations. Do not impose an external standard — match what's already there.",{"type":44,"tag":85,"props":1036,"children":1037},{},[1038,1043,1048,1053,1058,1063],{"type":44,"tag":89,"props":1039,"children":1040},{},[1041],{"type":50,"value":1042},"JavaScript\u002FTypeScript — JSDoc with the tag set used elsewhere in the same module.",{"type":44,"tag":89,"props":1044,"children":1045},{},[1046],{"type":50,"value":1047},"Python — docstrings in the same flavor (Google, NumPy, or reST) as the surrounding module.",{"type":44,"tag":89,"props":1049,"children":1050},{},[1051],{"type":50,"value":1052},"Java\u002FKotlin — Javadoc\u002FKDoc with the same tag set used by neighboring classes.",{"type":44,"tag":89,"props":1054,"children":1055},{},[1056],{"type":50,"value":1057},"Go — sentence-style comments starting with the identifier name, ending with a period.",{"type":44,"tag":89,"props":1059,"children":1060},{},[1061],{"type":50,"value":1062},"Ruby — YARD or RDoc consistent with the surrounding files.",{"type":44,"tag":89,"props":1064,"children":1065},{},[1066,1068,1074,1076,1082],{"type":50,"value":1067},"C#\u002FSwift\u002FPHP\u002FDart\u002FScala — match neighboring files. For C# specifically: every public member documented elsewhere with ",{"type":44,"tag":76,"props":1069,"children":1071},{"className":1070},[],[1072],{"type":50,"value":1073},"\u003Csummary>",{"type":50,"value":1075}," should have one; methods with ",{"type":44,"tag":76,"props":1077,"children":1079},{"className":1078},[],[1080],{"type":50,"value":1081},"\u003Cparam>",{"type":50,"value":1083}," tags on their neighbors should document each parameter.",{"type":44,"tag":53,"props":1085,"children":1086},{},[1087,1092],{"type":44,"tag":129,"props":1088,"children":1089},{},[1090],{"type":50,"value":1091},"Correctness",{"type":50,"value":1093}," — the doc text must agree with the code it describes. Flag:",{"type":44,"tag":85,"props":1095,"children":1096},{},[1097,1102,1129,1134],{"type":44,"tag":89,"props":1098,"children":1099},{},[1100],{"type":50,"value":1101},"Wrong subject — doc refers to \"the parent X\" when the symbol IS X (copy-paste artifact from another file).",{"type":44,"tag":89,"props":1103,"children":1104},{},[1105,1107,1113,1114,1120,1121,1127],{"type":50,"value":1106},"Stale references — ",{"type":44,"tag":76,"props":1108,"children":1110},{"className":1109},[],[1111],{"type":50,"value":1112},"\u003Csee cref=\"...\">",{"type":50,"value":430},{"type":44,"tag":76,"props":1115,"children":1117},{"className":1116},[],[1118],{"type":50,"value":1119},"@see",{"type":50,"value":430},{"type":44,"tag":76,"props":1122,"children":1124},{"className":1123},[],[1125],{"type":50,"value":1126},"@link",{"type":50,"value":1128}," pointing to renamed or removed symbols.",{"type":44,"tag":89,"props":1130,"children":1131},{},[1132],{"type":50,"value":1133},"Parameter docs that don't match the actual parameter list (missing, extra, or wrong-named).",{"type":44,"tag":89,"props":1135,"children":1136},{},[1137],{"type":50,"value":1138},"Return-value docs that don't match the actual return type.",{"type":44,"tag":53,"props":1140,"children":1141},{},[1142,1144,1149],{"type":50,"value":1143},"Flag missing docs only on ",{"type":44,"tag":129,"props":1145,"children":1146},{},[1147],{"type":50,"value":1148},"public",{"type":50,"value":1150}," API surface where the surrounding code documents its public surface.",{"type":44,"tag":490,"props":1152,"children":1154},{"id":1153},"rule-6-cross-language-consistency",[1155],{"type":50,"value":1156},"Rule 6 — Cross-language consistency",{"type":44,"tag":53,"props":1158,"children":1159},{},[1160,1162,1167],{"type":50,"value":1161},"When a PR adds or changes a feature in one language, find the same feature in the other languages (Python, Java, JavaScript, Scala, Go, Ruby, PHP, C#, Kotlin, Swift, Dart) and compare. Use grep to find equivalent files or templates. This rule is ",{"type":44,"tag":129,"props":1163,"children":1164},{},[1165],{"type":50,"value":1166},"the most important one",{"type":50,"value":1168}," — a divergence that looks innocuous in isolation can be a silent breaking change or an API that callers from other SDKs won't recognise.",{"type":44,"tag":53,"props":1170,"children":1171},{},[1172,1177],{"type":44,"tag":129,"props":1173,"children":1174},{},[1175],{"type":50,"value":1176},"How to check",{"type":50,"value":1178},": grep for the feature name (method, class, config key) in other language client directories and helper templates. Read the corresponding implementation before judging.",{"type":44,"tag":53,"props":1180,"children":1181},{},[1182],{"type":50,"value":1183},"Flag any divergence in the following categories:",{"type":44,"tag":85,"props":1185,"children":1186},{},[1187,1197,1207,1224,1234],{"type":44,"tag":89,"props":1188,"children":1189},{},[1190,1195],{"type":44,"tag":129,"props":1191,"children":1192},{},[1193],{"type":50,"value":1194},"Breaking change",{"type":50,"value":1196}," — the new implementation removes, renames, or changes the signature of something that exists in other languages (e.g. a required parameter becomes optional, a method is split, a config key changes name). Even if the change is unintentional, callers porting code from another SDK will be silently surprised.",{"type":44,"tag":89,"props":1198,"children":1199},{},[1200,1205],{"type":44,"tag":129,"props":1201,"children":1202},{},[1203],{"type":50,"value":1204},"Design choice",{"type":50,"value":1206}," — the new implementation makes a structural decision that differs from the established pattern without a language-idiomatic reason. Examples: storing configuration on the config object vs. on the client; using a factory method vs. a constructor; using an optional parameter vs. a named options object. If other languages converged on a design, the new language should match unless the language's idioms actively prevent it.",{"type":44,"tag":89,"props":1208,"children":1209},{},[1210,1215,1217,1222],{"type":44,"tag":129,"props":1211,"children":1212},{},[1213],{"type":50,"value":1214},"Idiomatic choice",{"type":50,"value":1216}," — flag the ",{"type":44,"tag":378,"props":1218,"children":1219},{},[1220],{"type":50,"value":1221},"opposite",{"type":50,"value":1223}," too: when the PR copies a pattern verbatim from another language but the target language has a strongly preferred idiom (e.g., using a class where the language would use a struct, ignoring nil-safety conventions, not using named parameters where the language requires them). The implementation should feel native, not like a translation.",{"type":44,"tag":89,"props":1225,"children":1226},{},[1227,1232],{"type":44,"tag":129,"props":1228,"children":1229},{},[1230],{"type":50,"value":1231},"Correctness gap",{"type":50,"value":1233}," — the new implementation is missing behaviour that all other languages implement (e.g., error handling for an edge case, a retry path, a header that other clients set, a fallback that other SDKs document). Check error messages: if every other language raises with the same string, the new one should too so that callers can detect errors uniformly.",{"type":44,"tag":89,"props":1235,"children":1236},{},[1237,1242],{"type":44,"tag":129,"props":1238,"children":1239},{},[1240],{"type":50,"value":1241},"Completeness gap",{"type":50,"value":1243}," — the new implementation adds only a subset of the methods or configuration options that other languages expose for this feature. Flag any method or option present in two or more other languages that is absent here without an explicit reason.",{"type":44,"tag":53,"props":1245,"children":1246},{},[1247,1249,1253,1255,1261,1262,1268],{"type":50,"value":1248},"Do ",{"type":44,"tag":129,"props":1250,"children":1251},{},[1252],{"type":50,"value":443},{"type":50,"value":1254}," flag differences that are explained by the target language's type system or standard library constraints (e.g., Dart needing ",{"type":44,"tag":76,"props":1256,"children":1258},{"className":1257},[],[1259],{"type":50,"value":1260},"async",{"type":50,"value":558},{"type":44,"tag":76,"props":1263,"children":1265},{"className":1264},[],[1266],{"type":50,"value":1267},"await",{"type":50,"value":1269}," where Java uses sync APIs, Go returning errors by value). Do flag differences that have no language-idiomatic explanation.",{"type":44,"tag":64,"props":1271,"children":1273},{"id":1272},"_3-general-review-pass",[1274],{"type":50,"value":1275},"3. General review pass",{"type":44,"tag":53,"props":1277,"children":1278},{},[1279],{"type":50,"value":1280},"After the checklist, analyze the changes as a whole and provide a thorough review that includes:",{"type":44,"tag":85,"props":1282,"children":1283},{},[1284,1289,1294,1299],{"type":44,"tag":89,"props":1285,"children":1286},{},[1287],{"type":50,"value":1288},"An overview of what the PR does",{"type":44,"tag":89,"props":1290,"children":1291},{},[1292],{"type":50,"value":1293},"Analysis of code quality and style",{"type":44,"tag":89,"props":1295,"children":1296},{},[1297],{"type":50,"value":1298},"Specific suggestions for improvements",{"type":44,"tag":89,"props":1300,"children":1301},{},[1302],{"type":50,"value":1303},"Any potential issues or risks",{"type":44,"tag":53,"props":1305,"children":1306},{},[1307],{"type":50,"value":1308},"Keep this pass concise but thorough. Focus on:",{"type":44,"tag":85,"props":1310,"children":1311},{},[1312,1317,1322,1327,1332],{"type":44,"tag":89,"props":1313,"children":1314},{},[1315],{"type":50,"value":1316},"Code correctness",{"type":44,"tag":89,"props":1318,"children":1319},{},[1320],{"type":50,"value":1321},"Following project conventions",{"type":44,"tag":89,"props":1323,"children":1324},{},[1325],{"type":50,"value":1326},"Performance implications",{"type":44,"tag":89,"props":1328,"children":1329},{},[1330],{"type":50,"value":1331},"Test coverage",{"type":44,"tag":89,"props":1333,"children":1334},{},[1335],{"type":50,"value":1336},"Security considerations",{"type":44,"tag":53,"props":1338,"children":1339},{},[1340,1342,1348],{"type":50,"value":1341},"Findings from this pass that are concrete and actionable go into the report's Blocking or Suggestions sections, tagged ",{"type":44,"tag":76,"props":1343,"children":1345},{"className":1344},[],[1346],{"type":50,"value":1347},"(general)",{"type":50,"value":1349}," to distinguish them from checklist findings. The overview goes into the report's Overview section. Do not let this pass duplicate checklist findings or drift into stylistic rewrites of code that already meets the standard.",{"type":44,"tag":64,"props":1351,"children":1353},{"id":1352},"_4-produce-the-report",[1354],{"type":50,"value":1355},"4. Produce the report",{"type":44,"tag":53,"props":1357,"children":1358},{},[1359,1361,1366,1368,1374],{"type":50,"value":1360},"The report must match this template ",{"type":44,"tag":129,"props":1362,"children":1363},{},[1364],{"type":50,"value":1365},"verbatim",{"type":50,"value":1367}," — same headings, same bullet format, same fallback line if no findings. Do not add sections, prefaces, or summaries that aren't in the template. Use ",{"type":44,"tag":76,"props":1369,"children":1371},{"className":1370},[],[1372],{"type":50,"value":1373},"file:line",{"type":50,"value":1375}," references for every finding.",{"type":44,"tag":53,"props":1377,"children":1378},{},[1379],{"type":50,"value":1380},"The first line of the report MUST be the HTML marker exactly as shown — it is kept so any tooling that consumes the file can find and replace its output.",{"type":44,"tag":1382,"props":1383,"children":1387},"pre",{"className":1384,"code":1386,"language":50},[1385],"language-text","\u003C!-- type: api-clients-review -->\n## PR Review\n\n### Overview\n\u003Ctwo to four sentences on what the PR does>\n\n### Blocking\n- `\u003Cfile>:\u003Cline>` — \u003Cone-line description>. \u003Cwhy this fails the rule>.\n…\n\n### Suggestions\n- `\u003Cfile>:\u003Cline>` — \u003Cone-line description>.\n…\n\n### Looks good\n\u003Cone or two sentences on what's solid>\n",[1388],{"type":44,"tag":76,"props":1389,"children":1391},{"__ignoreMap":1390},"",[1392],{"type":50,"value":1386},{"type":44,"tag":53,"props":1394,"children":1395},{},[1396,1398,1404,1406,1412],{"type":50,"value":1397},"If a single section has no findings, its body is exactly one line — ",{"type":44,"tag":76,"props":1399,"children":1401},{"className":1400},[],[1402],{"type":50,"value":1403},"No blocking findings.",{"type":50,"value":1405}," for Blocking, ",{"type":44,"tag":76,"props":1407,"children":1409},{"className":1408},[],[1410],{"type":50,"value":1411},"No suggestions.",{"type":50,"value":1413}," for Suggestions — do not omit the section.",{"type":44,"tag":53,"props":1415,"children":1416},{},[1417],{"type":50,"value":1418},"If no findings under any rule or the general pass, the body is exactly:",{"type":44,"tag":1382,"props":1420,"children":1423},{"className":1421,"code":1422,"language":50},[1385],"\u003C!-- type: api-clients-review -->\n## PR Review\n\n### Overview\n\u003Ctwo to four sentences on what the PR does>\n\nNo issues found under the review checklist.\n",[1424],{"type":44,"tag":76,"props":1425,"children":1426},{"__ignoreMap":1390},[1427],{"type":50,"value":1422},{"type":44,"tag":64,"props":1429,"children":1431},{"id":1430},"_5-save-the-report",[1432],{"type":50,"value":1433},"5. Save the report",{"type":44,"tag":53,"props":1435,"children":1436},{},[1437,1439,1445,1447,1453,1455,1459],{"type":50,"value":1438},"Save the report to both ",{"type":44,"tag":76,"props":1440,"children":1442},{"className":1441},[],[1443],{"type":50,"value":1444},"\u002Ftmp\u002Fapi-clients-review-{pr-number}.md",{"type":50,"value":1446}," and ",{"type":44,"tag":76,"props":1448,"children":1450},{"className":1449},[],[1451],{"type":50,"value":1452},"api-clients-review-{pr-number}.md",{"type":50,"value":1454}," at the repository root — do ",{"type":44,"tag":129,"props":1456,"children":1457},{},[1458],{"type":50,"value":443},{"type":50,"value":1460}," post it as a GitHub PR comment. Print the full report text in your response so the user can read it directly.",{"items":1462,"total":1471},[1463],{"slug":4,"name":4,"fn":5,"description":6,"org":1464,"tags":1465,"stars":28,"repoUrl":29,"updatedAt":30},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1466,1467,1468,1469,1470],{"name":23,"slug":24,"type":15},{"name":20,"slug":21,"type":15},{"name":17,"slug":18,"type":15},{"name":13,"slug":14,"type":15},{"name":26,"slug":27,"type":15},1,{"items":1473,"total":1652},[1474,1493,1512,1525,1540,1554,1567,1579,1597,1608,1619,1641],{"slug":1475,"name":1475,"fn":1476,"description":1477,"org":1478,"tags":1479,"stars":1490,"repoUrl":1491,"updatedAt":1492},"algolia-docsearch-mcp","search developer documentation with Algolia","Use this skill when the user asks about public developer documentation, SDKs, APIs, libraries, frameworks, setup, configuration, or code examples. Fetch current docs from Algolia DocSearch MCP and cite source URLs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1480,1481,1484,1487],{"name":9,"slug":8,"type":15},{"name":1482,"slug":1483,"type":15},"Documentation","documentation",{"name":1485,"slug":1486,"type":15},"MCP","mcp",{"name":1488,"slug":1489,"type":15},"Search","search",4365,"https:\u002F\u002Fgithub.com\u002Falgolia\u002Fdocsearch","2026-08-01T06:06:11.572314",{"slug":1494,"name":1494,"fn":1495,"description":1496,"org":1497,"tags":1498,"stars":1509,"repoUrl":1510,"updatedAt":1511},"algobot-cli","build conversational AI with Algolia","Use for anything AI\u002Fagent\u002Fconversational built on Algolia: algobot CLI, Agent Studio, RAG systems, conversational product discovery, genAI content generation from search results (carousels, descriptions, headers), chatbots or recommendation agents using Algolia as retrieval, config-as-code workflows, multi-environment deploy (dev\u002Fstaging\u002Fprod), memory and personalization, MCP tool integrations, conversation history \u002F GDPR retention, or adding a chat widget alongside InstantSearch. Trigger on: \"algobot\", \"Agent Studio\", \"RAG with Algolia\", \"conversational experience\", \"AI agent\" + Algolia, \"genAI carousel\", \"chat widget\", or building AI features on top of Algolia search. Do NOT use for raw index ops (records, synonyms, settings) — use algolia-cli. Do NOT use for pure frontend search UI (InstantSearch, autocomplete) with no AI\u002Fagent layer.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1499,1502,1505,1508],{"name":1500,"slug":1501,"type":15},"Agents","agents",{"name":1503,"slug":1504,"type":15},"Automation","automation",{"name":1506,"slug":1507,"type":15},"LLM","llm",{"name":1488,"slug":1489,"type":15},11,"https:\u002F\u002Fgithub.com\u002Falgolia\u002Fskills","2026-08-27T13:05:45.216732",{"slug":1513,"name":1513,"fn":1514,"description":1515,"org":1516,"tags":1517,"stars":1509,"repoUrl":1510,"updatedAt":1524},"algolia-agent-studio","build conversational agents with Algolia Agent Studio","Product-specific Algolia Agent Studio implementation, validation, and optimization guidance. Use when planning, building, integrating, or auditing Agent Studio agents, AI-powered conversational experiences, LLM provider setup, Algolia Search tools, client-side tools, MCP tools, memory, prompting, conversations, turn context, caching, analytics, feedback, authentication, approved domains, guardrails, or tool security. Do NOT use for live Agent Studio configuration, dry runs, publish\u002Fdeploy actions, or config-as-code operations; use the official algobot-cli skill instead. Do NOT use for generic non-Algolia RAG or chatbot architecture unless Agent Studio is the target product.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1518,1519,1522,1523],{"name":1500,"slug":1501,"type":15},{"name":1520,"slug":1521,"type":15},"AI","ai",{"name":9,"slug":8,"type":15},{"name":1488,"slug":1489,"type":15},"2026-08-01T06:06:28.033767",{"slug":1526,"name":1526,"fn":1527,"description":1528,"org":1529,"tags":1530,"stars":1509,"repoUrl":1510,"updatedAt":1539},"algolia-autocomplete","build Algolia autocomplete and query suggestions","Build and review Algolia Autocomplete and query suggestion experiences. Use when planning or implementing typeahead, query suggestions, recent searches, popular searches, federated autocomplete panels, product\u002Fcontent suggestions, detached mobile mode, plugins, keyboard navigation, insights events, or Autocomplete integration with InstantSearch. For net-new search or ecommerce builds, start with algolia-discovery-planning, which loads algolia-search-implementation so source strategy, data contract, and event taxonomy decisions are visible before autocomplete is marked ready. Do NOT use for full search results pages, browse pages, filters, pagination, or current refinements; use algolia-instantsearch-ui instead. Do NOT use for choosing between Algolia UI libraries; use algolia-ui-libraries. Do NOT use as the source of truth for current Autocomplete package APIs; use the official instantsearch skill and current docs alongside this customer-readiness skill.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1531,1532,1535,1536],{"name":9,"slug":8,"type":15},{"name":1533,"slug":1534,"type":15},"Frontend","frontend",{"name":1488,"slug":1489,"type":15},{"name":1537,"slug":1538,"type":15},"UI Components","ui-components","2026-08-01T06:06:29.968123",{"slug":1541,"name":1541,"fn":1542,"description":1543,"org":1544,"tags":1545,"stars":1509,"repoUrl":1510,"updatedAt":1553},"algolia-cli","manage Algolia indices and accounts","Use this skill whenever a user wants to execute operations against Algolia indices or accounts — deleting records, copying\u002Fmigrating indices, backing up data, importing\u002Fexporting records, managing API keys, editing synonyms, configuring rules, changing settings like facets, clearing indices, or automating Algolia in CI\u002FCD pipelines. The key signal is that the user wants to *act on* their Algolia data or configuration (server-side \u002F backend \u002F admin operations), regardless of whether they mention \"CLI\" or \"command line.\" If someone names a specific Algolia index and wants to change, move, query, or manage it, use this skill. Do NOT use for frontend search UI work (InstantSearch, React components, autocomplete widgets), Algolia dashboard GUI questions, or evaluating Algolia vs. other providers.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1546,1549,1552],{"name":1547,"slug":1548,"type":15},"CLI","cli",{"name":1550,"slug":1551,"type":15},"Data Engineering","data-engineering",{"name":1488,"slug":1489,"type":15},"2026-07-12T08:27:35.085246",{"slug":1555,"name":1555,"fn":1556,"description":1557,"org":1558,"tags":1559,"stars":1509,"repoUrl":1510,"updatedAt":1566},"algolia-crawler","crawl websites into Algolia indices","Use this skill whenever a user wants to crawl one or more web pages or a whole site and turn them into an Algolia index using the Algolia CLI — especially for RAG, AI search, semantic search, or Agent Studio retrieval. Triggers: \"index my website\u002Fdocs with Algolia\", \"set up the Algolia Crawler\", \"crawl this page for RAG\", \"scrape my site into Algolia\", \"build a knowledge base for my AI agent from these URLs\", writing or debugging a crawler recordExtractor, or handling JavaScript-rendered pages that won't index. It guides ingestion end-to-end with `algolia crawler` commands: inspect the page, write a RAG-optimized recordExtractor, validate with `algolia crawler test` BEFORE indexing, apply index settings explicitly, then reindex. Do NOT use for building the chatbot\u002Fagent layer itself (use algobot-cli), raw record\u002Fsynonym\u002Fsettings ops on an existing index (use algolia-cli), frontend search UI (use instantsearch), or read-only search\u002Fanalytics (use algolia-mcp).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1560,1561,1562,1563],{"name":1503,"slug":1504,"type":15},{"name":1550,"slug":1551,"type":15},{"name":1488,"slug":1489,"type":15},{"name":1564,"slug":1565,"type":15},"Web Scraping","web-scraping","2026-08-27T13:05:46.021245",{"slug":1568,"name":1568,"fn":1569,"description":1570,"org":1571,"tags":1572,"stars":1509,"repoUrl":1510,"updatedAt":1578},"algolia-data-modeling","design Algolia data models and indices","Algolia data modeling and indexing guidance. Use before or alongside indexing records or building Algolia search UI for net-new search, browse, autocomplete, ecommerce, personalization, Dynamic Re-Ranking, recommendations, or analytics-aware implementations. Makes record shape, objectID, display fields, facets, ranking fields, and event attribution explicit decisions. Use for records, variants, SKUs, indices, replicas, searchable and faceting attributes, denormalization, merchandising fields, timestamps, inventory, event attribution, indexing pipelines, partial updates, secured data, multi-language or multi-region strategies, and migrations. Do NOT use for live imports, exports, record mutations, settings changes, or account actions; use algolia-cli or algolia-mcp. Do NOT use for frontend UI implementation; use algolia-instantsearch-ui, algolia-autocomplete, algolia-ui-libraries, or the official instantsearch skill.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1573,1574,1577],{"name":9,"slug":8,"type":15},{"name":1575,"slug":1576,"type":15},"Data Modeling","data-modeling",{"name":1488,"slug":1489,"type":15},"2026-08-01T06:06:01.500756",{"slug":1580,"name":1580,"fn":1581,"description":1582,"org":1583,"tags":1584,"stars":1509,"repoUrl":1510,"updatedAt":1596},"algolia-discovery-planning","plan and audit Algolia search implementations","START HERE for any non-trivial Algolia work — building, adding, migrating, redesigning, auditing, or configuring search, browse, autocomplete, indexing, relevance, recommendations, personalization, merchandising, events, or analytics. Invoke this FIRST even when the task already seems scoped or the user names one specific feature (e.g. \"add InstantSearch\", \"build a storefront search\"): its job is to map the request to the full Algolia implementation lifecycle and load every companion skill each in-scope phase needs (algolia-search-implementation, algolia-data-modeling, algolia-index-configuration, algolia-ui-libraries, algolia-instantsearch-ui, algolia-autocomplete, algolia-events-insights, algolia-neuralsearch, algolia-agent-studio, algolia-release-qa) rather than jumping straight into a single skill. This skill plans and orchestrates; the focused companion skills and the official Algolia skills execute. Do NOT use for live account inspection or write actions; use algolia-mcp or algolia-cli for those.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1585,1586,1589,1592,1595],{"name":9,"slug":8,"type":15},{"name":1587,"slug":1588,"type":15},"Analytics","analytics",{"name":1590,"slug":1591,"type":15},"Configuration","configuration",{"name":1593,"slug":1594,"type":15},"Personalization","personalization",{"name":1488,"slug":1489,"type":15},"2026-08-01T06:06:03.021452",{"slug":1598,"name":1598,"fn":1599,"description":1600,"org":1601,"tags":1602,"stars":1509,"repoUrl":1510,"updatedAt":1607},"algolia-events-insights","instrument Algolia events for analytics","Algolia event instrumentation guidance for Insights, analytics, personalization, Dynamic Re-Ranking, Recommend, and merchandising feedback loops. Use for search, autocomplete, browse, ecommerce, personalization, recommendations, or analytics instrumentation. Makes event decisions explicit before an Algolia UI is considered ready. Use when implementing or auditing clickedObjectIDsAfterSearch, convertedObjectIDsAfterSearch, viewedObjectIDs, addedToCartObjectIDsAfterSearch, purchasedObjectIDsAfterSearch, userToken, queryID, eventName, eventSubtype, or frontend\u002Fbackend event pipelines. Do NOT use for live analytics retrieval, top-query inspection, or account-aware diagnostics; use algolia-mcp. Do NOT use for framework-specific InstantSearch or Autocomplete APIs; use the official instantsearch skill alongside this planning and validation skill.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1603,1604,1605,1606],{"name":9,"slug":8,"type":15},{"name":1587,"slug":1588,"type":15},{"name":1593,"slug":1594,"type":15},{"name":1488,"slug":1489,"type":15},"2026-08-01T06:06:02.009712",{"slug":1609,"name":1609,"fn":1610,"description":1611,"org":1612,"tags":1613,"stars":1509,"repoUrl":1510,"updatedAt":1618},"algolia-index-configuration","configure Algolia index settings and relevance","Algolia index settings and relevance configuration guidance. Use when configuring searchableAttributes, attributesForFaceting, customRanking, ranking, replicas, virtual replicas, rules, synonyms, typo tolerance, distinct, filters, optional filters, merchandising, browse\u002Fcategory relevance, or A\u002FB-testable relevance changes. Do NOT use for live settings writes, backups, copies, or operational account tasks; use algolia-cli or algolia-mcp instead. Do NOT use for record-shape or variant strategy; use algolia-data-modeling instead.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1614,1615,1616,1617],{"name":9,"slug":8,"type":15},{"name":1590,"slug":1591,"type":15},{"name":1575,"slug":1576,"type":15},{"name":1488,"slug":1489,"type":15},"2026-08-01T06:06:34.19163",{"slug":1620,"name":1620,"fn":1621,"description":1622,"org":1623,"tags":1624,"stars":1509,"repoUrl":1510,"updatedAt":1640},"algolia-instantsearch-ui","build Algolia InstantSearch frontend experiences","Build and review Algolia InstantSearch experiences in JavaScript, React, Vue, Angular (via InstantSearch.js; Angular InstantSearch is deprecated), or compatible frontend stacks. Use when planning or reviewing search results pages, browse\u002Fcategory pages, routing, widgets, filters, facets, sort-by, pagination, infinite hits, current refinements, insights middleware, SSR, or UI-state synchronization. For net-new search UI builds, start with algolia-discovery-planning, which loads algolia-search-implementation so data contract and event taxonomy decisions are visible before UI is marked ready. Do NOT use for autocomplete\u002Ftypeahead experiences before the user commits to a results page; use algolia-autocomplete instead. Do NOT use for choosing between Algolia UI libraries; use algolia-ui-libraries. Do NOT use as the source of truth for current framework APIs or code-level implementation details; use the official instantsearch skill and current docs alongside this customer-readiness skill.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1625,1626,1629,1630,1633,1636,1637],{"name":9,"slug":8,"type":15},{"name":1627,"slug":1628,"type":15},"Angular","angular",{"name":1533,"slug":1534,"type":15},{"name":1631,"slug":1632,"type":15},"JavaScript","javascript",{"name":1634,"slug":1635,"type":15},"React","react",{"name":1488,"slug":1489,"type":15},{"name":1638,"slug":1639,"type":15},"Vue","vue","2026-08-01T06:06:33.66513",{"slug":1642,"name":1642,"fn":1643,"description":1644,"org":1645,"tags":1646,"stars":1509,"repoUrl":1510,"updatedAt":1651},"algolia-mcp","search Algolia indices and retrieve analytics","Search Algolia indices via the Algolia MCP server, retrieve analytics (top searches, no-result rates, click positions, user counts), and get product recommendations (bought-together, related, trending). Triggers on search, indexing, analytics, Algolia, recommendations, MCP.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[1647,1648,1649,1650],{"name":1587,"slug":1588,"type":15},{"name":23,"slug":24,"type":15},{"name":1485,"slug":1486,"type":15},{"name":1488,"slug":1489,"type":15},"2026-07-12T08:27:36.376387",20]