{"owner":"apache","repo":"pulsar","hasSkills":true,"totalSkillsCount":6,"totalTokensCount":7983,"categories":["root-instruction","project-spec","claude-rule","copilot-instructions"],"hasMcp":false,"mcpConfig":null,"found":["microbench/AGENTS.md","ARCHITECTURE.md","AGENTS.md","microbench/CLAUDE.md","CLAUDE.md",".github/copilot-instructions.md"],"skills":{"microbench/AGENTS.md":"# Agent guide for the microbenchmarks\n\nSupplemental guidance for AI coding assistants working on the JMH microbenchmarks, on top of the repository's\n[`AGENTS.md`](../AGENTS.md). [`README.md`](README.md) describes building, running and profiling the benchmarks; read\nit before running or writing one.\n\n- Run the benchmarks a question needs, selected with a pattern, rather than all of them.\n- Treat results from other platforms as provisional until they are confirmed on Linux x86_64, as the README explains.\n- A benchmark measures a single class or method. The effect of a change on a running cluster is what\n  [the Pulsar Performance Testing Framework](../tests/performance/AGENTS.md) measures.\n","ARCHITECTURE.md":"# Architecture\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive (brokers, storage,\nnetworking).\n\nThe authoritative documentation lives at <https://pulsar.apache.org> — see the\n[Architecture Overview](https://pulsar.apache.org/docs/4.2.x/concepts-architecture-overview/) for the\nconceptual model. For a deeper, generated architecture description see\n[DeepWiki](https://deepwiki.com/apache/pulsar); coding agents can install the\n[DeepWiki MCP](https://docs.devin.ai/work-with-devin/deepwiki-mcp) for richer coverage of Pulsar's\narchitecture. This file is a map of the repository for contributors (and AI coding agents) who need to\nfind their way around the modules quickly.\n\n## Big picture\n\nPulsar separates a **stateless serving layer** (brokers) from **durable storage** (Apache\nBookKeeper) and a **metadata store** (Oxia / ZooKeeper). The Gradle modules layer\naccordingly:\n\n- **`pulsar-client-api`, `pulsar-client-admin-api`** — public, backward-compatible interfaces only.\n  `pulsar-client-api-v5` / `pulsar-client-v5` are the newer V5 client API (PIP-466/468).\n  Applications using either v4 or v5 can use [`pulsar-client-v5-all`](pulsar-client-v5-all/README.md)\n  for the unshaded client and admin together, or `pulsar-client-v5-shaded` for the combined shaded jar.\n- **`pulsar-client` (`:pulsar-client-original`)** — the Java client implementation\n  (producer/consumer/reader, connection pooling). `pulsar-client-admin` implements the admin REST\n  client.\n- **`pulsar-common`** — wire protocol and shared types. Protobuf / lightproto messages are\n  **generated** into `generated-lightproto/` / `generated-sources/` (excluded from checkstyle and\n  spotless).\n- **`pulsar-metadata`** — pluggable metadata store abstraction (Oxia / ZooKeeper, plus RocksDB and memory)\n  used by broker and bookkeeper.\n- **`managed-ledger`** — the storage abstraction over **Apache BookKeeper**: append-only ledgers +\n  cursors that track consumer/subscription positions. This is the durability layer the broker reads\n  and writes through.\n- **`pulsar-broker`** — the server. `PulsarService` is the composition root wiring everything\n  together; `BrokerService` manages topics, subscriptions, and client connections. Entry points:\n  `PulsarBrokerStarter` (broker), `PulsarStandalone` / `PulsarStandaloneStarter` (all-in-one),\n  `PulsarClusterMetadataSetup` (cluster init).\n- **`pulsar-proxy`** — optional proxy/gateway in front of brokers.\n- **`pulsar-functions/*`** — serverless compute (Functions): `proto`, `api-java`, `instance`,\n  `runtime`, `worker`, `localrun`.\n- **`pulsar-io/*`** — connector framework core only; most built-in connectors were moved to the\n  separate `pulsar-connectors` repo (PIP-465).\n- **`pulsar-transaction/*`** — transaction coordinator and common types.\n- **`tiered-storage/*`, `offloaders/`** — offload ledger data to cloud/filesystem storage.\n- **`pulsar-websocket`** — WebSocket-to-Pulsar bridge. **`pulsar-client-tools`** — the\n  `pulsar-admin` / `pulsar-client` CLIs.\n- **Shaded / distribution** — `pulsar-client-shaded`, `pulsar-client-all`,\n  `pulsar-client-admin-shaded` produce relocated fat jars; `distribution/*` assembles\n  server/shell/offloader tarballs.\n\n## Pulsar Improvement Proposals (`pip/`)\n\nThe **`pip/`** directory holds **Pulsar Improvement Proposals** (`pip-<N>.md`) — the design\ndocuments for significant changes, referenced as `PIP-<N>` throughout commit messages and code (e.g.\nPIP-463 = Maven→Gradle migration, PIP-465 = IO connectors moved out, PIP-466/468 = V5 client).\n`pip/README.md` describes the process and `pip/TEMPLATE.md` is the proposal template. Consult the\nrelevant PIP for the rationale behind a non-trivial feature or architectural decision. A PIP **number\nis reserved by the first `dev@pulsar.apache.org` thread that uses it** — start the discussion to claim\nthe next free number.\n\n## Concurrency model (a known gap)\n\nPulsar does **not** have a clearly established, documented concurrency model, which makes it hard to\nevaluate whether a given piece of code is correct by construction. (Contrast Netty, which has a clear\nrule: all handling on the IO thread is non-blocking, which by extension means avoiding synchronization\nand locks on that path.) Pulsar does not strictly follow such a rule; modern JVMs and hardware\noptimize `synchronized` code well enough that this has not blocked high performance, but it does make\nreasoning about correctness harder than it needs to be.\n\nConventions that **should** be documented (and largely are not yet):\n\n- which work belongs on the network-connection **event loop** vs. other threads;\n- how the various **thread pools** are intended to be used, and what kind of work belongs on each;\n- how threads are expected to **hand off state** to each other;\n- when a `CompletableFuture`'s **completion thread should be switched** to another thread, and which one;\n- **concurrency limits** for asynchronous tasks;\n- preferring the **single-writer principle** to avoid concurrent state mutation.\n\nUntil such a model is written down, follow the surrounding code's conventions and the Java-Memory-Model\nrules in [`CODING.md`](CODING.md#concurrency). Once a model is defined, it becomes far more tractable to\n\"lift and shift\" existing code toward it and enforce the rules consistently rather than having each\ncontributor rediscover the conventions case by case.\n\n## Backpressure\n\nClosely tied to the concurrency model is **backpressure** — how the system avoids accepting more work\nthan it can handle, particularly with respect to memory. The memory side is described in\n[PIP-442 \"Existing Broker Memory Management\"](pip/pip-442.md#existing-broker-memory-management). Broader\nbackpressure (beyond memory) is not yet documented and would benefit from being defined alongside the\nconcurrency model.\n\n## Build infrastructure\n\nApache Pulsar uses a **Gradle** build (migrated from Maven via PIP-463; some older tooling and docs\nelsewhere still reference Maven). The wrapper `./gradlew` requires **JDK 21, 25 or 26** (server bytecode\ntargets Java 21; client/API bytecode targets Java 17). See\n[`CONTRIBUTING.md` → Building](CONTRIBUTING.md#building) for the build and lint commands.\n\n- `settings.gradle.kts` — all modules, organized in dependency tiers (Tier 0 has no internal deps,\n  higher tiers build on lower ones).\n- `build-logic/conventions/` — convention plugins (`pulsar.java-conventions`,\n  `pulsar.code-quality-conventions`, `pulsar.shadow-conventions`, etc.) applied by modules. Shared\n  compile/test/dependency config lives here — edit it here rather than duplicating across modules.\n- `gradle/libs.versions.toml` — version catalog (single source of truth for dependency versions;\n  referenced as `libs.*` in build scripts).\n- `pulsar-dependencies` — enforced platform (BOM) pinning all dependency versions; applied to every\n  module.\n\nThe build enables both the **configuration cache** (`org.gradle.configuration-cache=true`) and\n**configure-on-demand** (`org.gradle.configureondemand=true`).\n\n### Module name vs. directory name gotcha\n\nSeveral Gradle project paths do **not** match their directory because the Maven artifactId is\npreserved. Most importantly:\n\n- Directory `pulsar-client/` → project **`:pulsar-client-original`**\n- Directory `pulsar-client-admin/` → project **`:pulsar-client-admin-original`**\n- Directory `pulsar-functions/localrun/` → project `:pulsar-functions:pulsar-functions-local-runner-original`\n\nAlways use the Gradle project path (left of any `--tests`), e.g. `./gradlew :pulsar-client-original:test`.\nCheck `settings.gradle.kts` when a path is ambiguous.\n\n### Java compatibility boundaries\n\n`pulsar.java-conventions` defaults main sources to Java 21 and explicitly lists the Java 17 client\nand public API dependency closure. This includes both client generations, admin/auth/crypto clients,\nTLS/HTTP SPIs, shared common/package APIs, and the Functions/IO interfaces. Functions implementations,\nbrokers, and other server components target Java 21. Client CLI tools also remain Java 17 compatible.\n`pulsarJavaVersion` and `pulsarClientJavaVersion` control these targets (defaults 21 and 17).\nTest sources default to `pulsarJavaVersion` so client tests can use server fixtures; the dedicated\nconsumer tests use `pulsarClientJavaVersion` for compilation and their runtime toolchain.\nThe bytecode check and published JVM metadata follow the configured client target.\n\nWhen adding a client dependency, keep its full compile/runtime closure Java 17 compatible. JVM\nvariant attributes reject Java 21 project dependencies; `verifyClientJavaCompatibility` also checks\nclass-file versions of dependencies without Gradle metadata and the final shaded client jars.\nMulti-release jars are checked using the entries selected by Java 17. This verifies bytecode, not\nall possible reflective or JDK API usage in third-party libraries; the Java 17 consumer tests provide\nruntime coverage. Do not mark a server implementation as Java 17 just to bypass a dependency error.\n\nThe client fastutil minimizer reads CLI classes as build-only reachability roots. Its published jar has no\ntransitive project dependencies and is checked as Java 17.\n`buildtools` and `testmocks` also stay Java 17 so the consumer compatibility tests can load them.\n\n### Changing the build\n\nWhen editing `build-logic/`, `settings.gradle.kts`, a module `build.gradle.kts`, `gradle.properties`,\n`gradle/libs.versions.toml`, or the `pulsar-dependencies` platform:\n\n- **Edit shared config in `build-logic/conventions/`**, not per-module.\n- **Versions come from `gradle/libs.versions.toml`** (`libs.*` / `pulsar-dependencies`) — never\n  hardcode a version in a build script.\n- **Keep tasks configuration-cache and configure-on-demand compatible** (both are enabled): no reading\n  of mutable state at execution time and no `Project` access in task actions — use `Provider` / value\n  sources, and verify with `--configuration-cache`. Tasks reached by the common flows (`assemble`,\n  `test`, `integrationTest`, `rat` / `spotlessCheck` / `checkstyle*`, `checkBinaryLicense`, `docker*`)\n  must be compatible; one-off tooling tasks not part of those flows (e.g. `verifyTestGroups`, ad-hoc\n  report tasks) may be exempt. When a third-party plugin is incompatible and cannot be fixed locally,\n  opt its tasks out with `notCompatibleWithConfigurationCache(\"<reason>\")` (see\n  `tests/pulsar-client-native-image/build.gradle.kts` for the GraalVM native-build-tools case) so the\n  build degrades to running without the cache instead of failing.\n- **Published modules must not depend on internal modules** at compile/runtime scope — the artifact\n  would be unresolvable from Maven Central. A module is published only when it applies\n  `pulsar.public-java-library-conventions`.\n- **After a dependency change**, run `./gradlew checkBinaryLicense` and update the distribution\n  `LICENSE`/`NOTICE`; justify any genuinely new dependency (see\n  [`CODING.md` → Dependencies](CODING.md#dependencies)).\n- **Follow the [Gradle best practices](https://docs.gradle.org/current/userguide/best_practices_index.html)**\n  — AI agents should read the\n  [AsciiDoc source](https://github.com/gradle/gradle/blob/master/platforms/documentation/docs/src/docs/userguide/best-practices/best_practices_index.adoc),\n  which is plain text and cheaper to parse than the rendered HTML.\n\nBefore finishing a build change, confirm the affected task and `./gradlew help` run clean with\n`--configuration-cache`, and that `assemble` and `quickCheck` (license headers + checkstyle across\nall modules) pass (plus `checkBinaryLicense` if a dependency changed).\n","AGENTS.md":"# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n","microbench/CLAUDE.md":"# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n","CLAUDE.md":"# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n",".github/copilot-instructions.md":"../AGENTS.md"},"files":{"microbench/AGENTS.md":"# Agent guide for the microbenchmarks\n\nSupplemental guidance for AI coding assistants working on the JMH microbenchmarks, on top of the repository's\n[`AGENTS.md`](../AGENTS.md). [`README.md`](README.md) describes building, running and profiling the benchmarks; read\nit before running or writing one.\n\n- Run the benchmarks a question needs, selected with a pattern, rather than all of them.\n- Treat results from other platforms as provisional until they are confirmed on Linux x86_64, as the README explains.\n- A benchmark measures a single class or method. The effect of a change on a running cluster is what\n  [the Pulsar Performance Testing Framework](../tests/performance/AGENTS.md) measures.\n","ARCHITECTURE.md":"# Architecture\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive (brokers, storage,\nnetworking).\n\nThe authoritative documentation lives at <https://pulsar.apache.org> — see the\n[Architecture Overview](https://pulsar.apache.org/docs/4.2.x/concepts-architecture-overview/) for the\nconceptual model. For a deeper, generated architecture description see\n[DeepWiki](https://deepwiki.com/apache/pulsar); coding agents can install the\n[DeepWiki MCP](https://docs.devin.ai/work-with-devin/deepwiki-mcp) for richer coverage of Pulsar's\narchitecture. This file is a map of the repository for contributors (and AI coding agents) who need to\nfind their way around the modules quickly.\n\n## Big picture\n\nPulsar separates a **stateless serving layer** (brokers) from **durable storage** (Apache\nBookKeeper) and a **metadata store** (Oxia / ZooKeeper). The Gradle modules layer\naccordingly:\n\n- **`pulsar-client-api`, `pulsar-client-admin-api`** — public, backward-compatible interfaces only.\n  `pulsar-client-api-v5` / `pulsar-client-v5` are the newer V5 client API (PIP-466/468).\n  Applications using either v4 or v5 can use [`pulsar-client-v5-all`](pulsar-client-v5-all/README.md)\n  for the unshaded client and admin together, or `pulsar-client-v5-shaded` for the combined shaded jar.\n- **`pulsar-client` (`:pulsar-client-original`)** — the Java client implementation\n  (producer/consumer/reader, connection pooling). `pulsar-client-admin` implements the admin REST\n  client.\n- **`pulsar-common`** — wire protocol and shared types. Protobuf / lightproto messages are\n  **generated** into `generated-lightproto/` / `generated-sources/` (excluded from checkstyle and\n  spotless).\n- **`pulsar-metadata`** — pluggable metadata store abstraction (Oxia / ZooKeeper, plus RocksDB and memory)\n  used by broker and bookkeeper.\n- **`managed-ledger`** — the storage abstraction over **Apache BookKeeper**: append-only ledgers +\n  cursors that track consumer/subscription positions. This is the durability layer the broker reads\n  and writes through.\n- **`pulsar-broker`** — the server. `PulsarService` is the composition root wiring everything\n  together; `BrokerService` manages topics, subscriptions, and client connections. Entry points:\n  `PulsarBrokerStarter` (broker), `PulsarStandalone` / `PulsarStandaloneStarter` (all-in-one),\n  `PulsarClusterMetadataSetup` (cluster init).\n- **`pulsar-proxy`** — optional proxy/gateway in front of brokers.\n- **`pulsar-functions/*`** — serverless compute (Functions): `proto`, `api-java`, `instance`,\n  `runtime`, `worker`, `localrun`.\n- **`pulsar-io/*`** — connector framework core only; most built-in connectors were moved to the\n  separate `pulsar-connectors` repo (PIP-465).\n- **`pulsar-transaction/*`** — transaction coordinator and common types.\n- **`tiered-storage/*`, `offloaders/`** — offload ledger data to cloud/filesystem storage.\n- **`pulsar-websocket`** — WebSocket-to-Pulsar bridge. **`pulsar-client-tools`** — the\n  `pulsar-admin` / `pulsar-client` CLIs.\n- **Shaded / distribution** — `pulsar-client-shaded`, `pulsar-client-all`,\n  `pulsar-client-admin-shaded` produce relocated fat jars; `distribution/*` assembles\n  server/shell/offloader tarballs.\n\n## Pulsar Improvement Proposals (`pip/`)\n\nThe **`pip/`** directory holds **Pulsar Improvement Proposals** (`pip-<N>.md`) — the design\ndocuments for significant changes, referenced as `PIP-<N>` throughout commit messages and code (e.g.\nPIP-463 = Maven→Gradle migration, PIP-465 = IO connectors moved out, PIP-466/468 = V5 client).\n`pip/README.md` describes the process and `pip/TEMPLATE.md` is the proposal template. Consult the\nrelevant PIP for the rationale behind a non-trivial feature or architectural decision. A PIP **number\nis reserved by the first `dev@pulsar.apache.org` thread that uses it** — start the discussion to claim\nthe next free number.\n\n## Concurrency model (a known gap)\n\nPulsar does **not** have a clearly established, documented concurrency model, which makes it hard to\nevaluate whether a given piece of code is correct by construction. (Contrast Netty, which has a clear\nrule: all handling on the IO thread is non-blocking, which by extension means avoiding synchronization\nand locks on that path.) Pulsar does not strictly follow such a rule; modern JVMs and hardware\noptimize `synchronized` code well enough that this has not blocked high performance, but it does make\nreasoning about correctness harder than it needs to be.\n\nConventions that **should** be documented (and largely are not yet):\n\n- which work belongs on the network-connection **event loop** vs. other threads;\n- how the various **thread pools** are intended to be used, and what kind of work belongs on each;\n- how threads are expected to **hand off state** to each other;\n- when a `CompletableFuture`'s **completion thread should be switched** to another thread, and which one;\n- **concurrency limits** for asynchronous tasks;\n- preferring the **single-writer principle** to avoid concurrent state mutation.\n\nUntil such a model is written down, follow the surrounding code's conventions and the Java-Memory-Model\nrules in [`CODING.md`](CODING.md#concurrency). Once a model is defined, it becomes far more tractable to\n\"lift and shift\" existing code toward it and enforce the rules consistently rather than having each\ncontributor rediscover the conventions case by case.\n\n## Backpressure\n\nClosely tied to the concurrency model is **backpressure** — how the system avoids accepting more work\nthan it can handle, particularly with respect to memory. The memory side is described in\n[PIP-442 \"Existing Broker Memory Management\"](pip/pip-442.md#existing-broker-memory-management). Broader\nbackpressure (beyond memory) is not yet documented and would benefit from being defined alongside the\nconcurrency model.\n\n## Build infrastructure\n\nApache Pulsar uses a **Gradle** build (migrated from Maven via PIP-463; some older tooling and docs\nelsewhere still reference Maven). The wrapper `./gradlew` requires **JDK 21, 25 or 26** (server bytecode\ntargets Java 21; client/API bytecode targets Java 17). See\n[`CONTRIBUTING.md` → Building](CONTRIBUTING.md#building) for the build and lint commands.\n\n- `settings.gradle.kts` — all modules, organized in dependency tiers (Tier 0 has no internal deps,\n  higher tiers build on lower ones).\n- `build-logic/conventions/` — convention plugins (`pulsar.java-conventions`,\n  `pulsar.code-quality-conventions`, `pulsar.shadow-conventions`, etc.) applied by modules. Shared\n  compile/test/dependency config lives here — edit it here rather than duplicating across modules.\n- `gradle/libs.versions.toml` — version catalog (single source of truth for dependency versions;\n  referenced as `libs.*` in build scripts).\n- `pulsar-dependencies` — enforced platform (BOM) pinning all dependency versions; applied to every\n  module.\n\nThe build enables both the **configuration cache** (`org.gradle.configuration-cache=true`) and\n**configure-on-demand** (`org.gradle.configureondemand=true`).\n\n### Module name vs. directory name gotcha\n\nSeveral Gradle project paths do **not** match their directory because the Maven artifactId is\npreserved. Most importantly:\n\n- Directory `pulsar-client/` → project **`:pulsar-client-original`**\n- Directory `pulsar-client-admin/` → project **`:pulsar-client-admin-original`**\n- Directory `pulsar-functions/localrun/` → project `:pulsar-functions:pulsar-functions-local-runner-original`\n\nAlways use the Gradle project path (left of any `--tests`), e.g. `./gradlew :pulsar-client-original:test`.\nCheck `settings.gradle.kts` when a path is ambiguous.\n\n### Java compatibility boundaries\n\n`pulsar.java-conventions` defaults main sources to Java 21 and explicitly lists the Java 17 client\nand public API dependency closure. This includes both client generations, admin/auth/crypto clients,\nTLS/HTTP SPIs, shared common/package APIs, and the Functions/IO interfaces. Functions implementations,\nbrokers, and other server components target Java 21. Client CLI tools also remain Java 17 compatible.\n`pulsarJavaVersion` and `pulsarClientJavaVersion` control these targets (defaults 21 and 17).\nTest sources default to `pulsarJavaVersion` so client tests can use server fixtures; the dedicated\nconsumer tests use `pulsarClientJavaVersion` for compilation and their runtime toolchain.\nThe bytecode check and published JVM metadata follow the configured client target.\n\nWhen adding a client dependency, keep its full compile/runtime closure Java 17 compatible. JVM\nvariant attributes reject Java 21 project dependencies; `verifyClientJavaCompatibility` also checks\nclass-file versions of dependencies without Gradle metadata and the final shaded client jars.\nMulti-release jars are checked using the entries selected by Java 17. This verifies bytecode, not\nall possible reflective or JDK API usage in third-party libraries; the Java 17 consumer tests provide\nruntime coverage. Do not mark a server implementation as Java 17 just to bypass a dependency error.\n\nThe client fastutil minimizer reads CLI classes as build-only reachability roots. Its published jar has no\ntransitive project dependencies and is checked as Java 17.\n`buildtools` and `testmocks` also stay Java 17 so the consumer compatibility tests can load them.\n\n### Changing the build\n\nWhen editing `build-logic/`, `settings.gradle.kts`, a module `build.gradle.kts`, `gradle.properties`,\n`gradle/libs.versions.toml`, or the `pulsar-dependencies` platform:\n\n- **Edit shared config in `build-logic/conventions/`**, not per-module.\n- **Versions come from `gradle/libs.versions.toml`** (`libs.*` / `pulsar-dependencies`) — never\n  hardcode a version in a build script.\n- **Keep tasks configuration-cache and configure-on-demand compatible** (both are enabled): no reading\n  of mutable state at execution time and no `Project` access in task actions — use `Provider` / value\n  sources, and verify with `--configuration-cache`. Tasks reached by the common flows (`assemble`,\n  `test`, `integrationTest`, `rat` / `spotlessCheck` / `checkstyle*`, `checkBinaryLicense`, `docker*`)\n  must be compatible; one-off tooling tasks not part of those flows (e.g. `verifyTestGroups`, ad-hoc\n  report tasks) may be exempt. When a third-party plugin is incompatible and cannot be fixed locally,\n  opt its tasks out with `notCompatibleWithConfigurationCache(\"<reason>\")` (see\n  `tests/pulsar-client-native-image/build.gradle.kts` for the GraalVM native-build-tools case) so the\n  build degrades to running without the cache instead of failing.\n- **Published modules must not depend on internal modules** at compile/runtime scope — the artifact\n  would be unresolvable from Maven Central. A module is published only when it applies\n  `pulsar.public-java-library-conventions`.\n- **After a dependency change**, run `./gradlew checkBinaryLicense` and update the distribution\n  `LICENSE`/`NOTICE`; justify any genuinely new dependency (see\n  [`CODING.md` → Dependencies](CODING.md#dependencies)).\n- **Follow the [Gradle best practices](https://docs.gradle.org/current/userguide/best_practices_index.html)**\n  — AI agents should read the\n  [AsciiDoc source](https://github.com/gradle/gradle/blob/master/platforms/documentation/docs/src/docs/userguide/best-practices/best_practices_index.adoc),\n  which is plain text and cheaper to parse than the rendered HTML.\n\nBefore finishing a build change, confirm the affected task and `./gradlew help` run clean with\n`--configuration-cache`, and that `assemble` and `quickCheck` (license headers + checkstyle across\nall modules) pass (plus `checkBinaryLicense` if a dependency changed).\n","AGENTS.md":"# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n","microbench/CLAUDE.md":"# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n","CLAUDE.md":"# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n",".github/copilot-instructions.md":"../AGENTS.md"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/apache/pulsar/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n","isInternal":false,"tokens":1672,"sizeBytes":7124},{"name":"AGENTS.md","path":"microbench/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/apache/pulsar/HEAD/microbench/AGENTS.md","title":"microbench - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Agent guide for the microbenchmarks\n\nSupplemental guidance for AI coding assistants working on the JMH microbenchmarks, on top of the repository's\n[`AGENTS.md`](../AGENTS.md). [`README.md`](README.md) describes building, running and profiling the benchmarks; read\nit before running or writing one.\n\n- Run the benchmarks a question needs, selected with a pattern, rather than all of them.\n- Treat results from other platforms as provisional until they are confirmed on Linux x86_64, as the README explains.\n- A benchmark measures a single class or method. The effect of a change on a running cluster is what\n  [the Pulsar Performance Testing Framework](../tests/performance/AGENTS.md) measures.\n","isInternal":false,"tokens":154,"sizeBytes":696},{"name":"ARCHITECTURE.md","path":"ARCHITECTURE.md","rawUrl":"https://raw.githubusercontent.com/apache/pulsar/HEAD/ARCHITECTURE.md","title":"System Architecture & Module Boundaries","category":"project-spec","format":"markdown","content":"# Architecture\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive (brokers, storage,\nnetworking).\n\nThe authoritative documentation lives at <https://pulsar.apache.org> — see the\n[Architecture Overview](https://pulsar.apache.org/docs/4.2.x/concepts-architecture-overview/) for the\nconceptual model. For a deeper, generated architecture description see\n[DeepWiki](https://deepwiki.com/apache/pulsar); coding agents can install the\n[DeepWiki MCP](https://docs.devin.ai/work-with-devin/deepwiki-mcp) for richer coverage of Pulsar's\narchitecture. This file is a map of the repository for contributors (and AI coding agents) who need to\nfind their way around the modules quickly.\n\n## Big picture\n\nPulsar separates a **stateless serving layer** (brokers) from **durable storage** (Apache\nBookKeeper) and a **metadata store** (Oxia / ZooKeeper). The Gradle modules layer\naccordingly:\n\n- **`pulsar-client-api`, `pulsar-client-admin-api`** — public, backward-compatible interfaces only.\n  `pulsar-client-api-v5` / `pulsar-client-v5` are the newer V5 client API (PIP-466/468).\n  Applications using either v4 or v5 can use [`pulsar-client-v5-all`](pulsar-client-v5-all/README.md)\n  for the unshaded client and admin together, or `pulsar-client-v5-shaded` for the combined shaded jar.\n- **`pulsar-client` (`:pulsar-client-original`)** — the Java client implementation\n  (producer/consumer/reader, connection pooling). `pulsar-client-admin` implements the admin REST\n  client.\n- **`pulsar-common`** — wire protocol and shared types. Protobuf / lightproto messages are\n  **generated** into `generated-lightproto/` / `generated-sources/` (excluded from checkstyle and\n  spotless).\n- **`pulsar-metadata`** — pluggable metadata store abstraction (Oxia / ZooKeeper, plus RocksDB and memory)\n  used by broker and bookkeeper.\n- **`managed-ledger`** — the storage abstraction over **Apache BookKeeper**: append-only ledgers +\n  cursors that track consumer/subscription positions. This is the durability layer the broker reads\n  and writes through.\n- **`pulsar-broker`** — the server. `PulsarService` is the composition root wiring everything\n  together; `BrokerService` manages topics, subscriptions, and client connections. Entry points:\n  `PulsarBrokerStarter` (broker), `PulsarStandalone` / `PulsarStandaloneStarter` (all-in-one),\n  `PulsarClusterMetadataSetup` (cluster init).\n- **`pulsar-proxy`** — optional proxy/gateway in front of brokers.\n- **`pulsar-functions/*`** — serverless compute (Functions): `proto`, `api-java`, `instance`,\n  `runtime`, `worker`, `localrun`.\n- **`pulsar-io/*`** — connector framework core only; most built-in connectors were moved to the\n  separate `pulsar-connectors` repo (PIP-465).\n- **`pulsar-transaction/*`** — transaction coordinator and common types.\n- **`tiered-storage/*`, `offloaders/`** — offload ledger data to cloud/filesystem storage.\n- **`pulsar-websocket`** — WebSocket-to-Pulsar bridge. **`pulsar-client-tools`** — the\n  `pulsar-admin` / `pulsar-client` CLIs.\n- **Shaded / distribution** — `pulsar-client-shaded`, `pulsar-client-all`,\n  `pulsar-client-admin-shaded` produce relocated fat jars; `distribution/*` assembles\n  server/shell/offloader tarballs.\n\n## Pulsar Improvement Proposals (`pip/`)\n\nThe **`pip/`** directory holds **Pulsar Improvement Proposals** (`pip-<N>.md`) — the design\ndocuments for significant changes, referenced as `PIP-<N>` throughout commit messages and code (e.g.\nPIP-463 = Maven→Gradle migration, PIP-465 = IO connectors moved out, PIP-466/468 = V5 client).\n`pip/README.md` describes the process and `pip/TEMPLATE.md` is the proposal template. Consult the\nrelevant PIP for the rationale behind a non-trivial feature or architectural decision. A PIP **number\nis reserved by the first `dev@pulsar.apache.org` thread that uses it** — start the discussion to claim\nthe next free number.\n\n## Concurrency model (a known gap)\n\nPulsar does **not** have a clearly established, documented concurrency model, which makes it hard to\nevaluate whether a given piece of code is correct by construction. (Contrast Netty, which has a clear\nrule: all handling on the IO thread is non-blocking, which by extension means avoiding synchronization\nand locks on that path.) Pulsar does not strictly follow such a rule; modern JVMs and hardware\noptimize `synchronized` code well enough that this has not blocked high performance, but it does make\nreasoning about correctness harder than it needs to be.\n\nConventions that **should** be documented (and largely are not yet):\n\n- which work belongs on the network-connection **event loop** vs. other threads;\n- how the various **thread pools** are intended to be used, and what kind of work belongs on each;\n- how threads are expected to **hand off state** to each other;\n- when a `CompletableFuture`'s **completion thread should be switched** to another thread, and which one;\n- **concurrency limits** for asynchronous tasks;\n- preferring the **single-writer principle** to avoid concurrent state mutation.\n\nUntil such a model is written down, follow the surrounding code's conventions and the Java-Memory-Model\nrules in [`CODING.md`](CODING.md#concurrency). Once a model is defined, it becomes far more tractable to\n\"lift and shift\" existing code toward it and enforce the rules consistently rather than having each\ncontributor rediscover the conventions case by case.\n\n## Backpressure\n\nClosely tied to the concurrency model is **backpressure** — how the system avoids accepting more work\nthan it can handle, particularly with respect to memory. The memory side is described in\n[PIP-442 \"Existing Broker Memory Management\"](pip/pip-442.md#existing-broker-memory-management). Broader\nbackpressure (beyond memory) is not yet documented and would benefit from being defined alongside the\nconcurrency model.\n\n## Build infrastructure\n\nApache Pulsar uses a **Gradle** build (migrated from Maven via PIP-463; some older tooling and docs\nelsewhere still reference Maven). The wrapper `./gradlew` requires **JDK 21, 25 or 26** (server bytecode\ntargets Java 21; client/API bytecode targets Java 17). See\n[`CONTRIBUTING.md` → Building](CONTRIBUTING.md#building) for the build and lint commands.\n\n- `settings.gradle.kts` — all modules, organized in dependency tiers (Tier 0 has no internal deps,\n  higher tiers build on lower ones).\n- `build-logic/conventions/` — convention plugins (`pulsar.java-conventions`,\n  `pulsar.code-quality-conventions`, `pulsar.shadow-conventions`, etc.) applied by modules. Shared\n  compile/test/dependency config lives here — edit it here rather than duplicating across modules.\n- `gradle/libs.versions.toml` — version catalog (single source of truth for dependency versions;\n  referenced as `libs.*` in build scripts).\n- `pulsar-dependencies` — enforced platform (BOM) pinning all dependency versions; applied to every\n  module.\n\nThe build enables both the **configuration cache** (`org.gradle.configuration-cache=true`) and\n**configure-on-demand** (`org.gradle.configureondemand=true`).\n\n### Module name vs. directory name gotcha\n\nSeveral Gradle project paths do **not** match their directory because the Maven artifactId is\npreserved. Most importantly:\n\n- Directory `pulsar-client/` → project **`:pulsar-client-original`**\n- Directory `pulsar-client-admin/` → project **`:pulsar-client-admin-original`**\n- Directory `pulsar-functions/localrun/` → project `:pulsar-functions:pulsar-functions-local-runner-original`\n\nAlways use the Gradle project path (left of any `--tests`), e.g. `./gradlew :pulsar-client-original:test`.\nCheck `settings.gradle.kts` when a path is ambiguous.\n\n### Java compatibility boundaries\n\n`pulsar.java-conventions` defaults main sources to Java 21 and explicitly lists the Java 17 client\nand public API dependency closure. This includes both client generations, admin/auth/crypto clients,\nTLS/HTTP SPIs, shared common/package APIs, and the Functions/IO interfaces. Functions implementations,\nbrokers, and other server components target Java 21. Client CLI tools also remain Java 17 compatible.\n`pulsarJavaVersion` and `pulsarClientJavaVersion` control these targets (defaults 21 and 17).\nTest sources default to `pulsarJavaVersion` so client tests can use server fixtures; the dedicated\nconsumer tests use `pulsarClientJavaVersion` for compilation and their runtime toolchain.\nThe bytecode check and published JVM metadata follow the configured client target.\n\nWhen adding a client dependency, keep its full compile/runtime closure Java 17 compatible. JVM\nvariant attributes reject Java 21 project dependencies; `verifyClientJavaCompatibility` also checks\nclass-file versions of dependencies without Gradle metadata and the final shaded client jars.\nMulti-release jars are checked using the entries selected by Java 17. This verifies bytecode, not\nall possible reflective or JDK API usage in third-party libraries; the Java 17 consumer tests provide\nruntime coverage. Do not mark a server implementation as Java 17 just to bypass a dependency error.\n\nThe client fastutil minimizer reads CLI classes as build-only reachability roots. Its published jar has no\ntransitive project dependencies and is checked as Java 17.\n`buildtools` and `testmocks` also stay Java 17 so the consumer compatibility tests can load them.\n\n### Changing the build\n\nWhen editing `build-logic/`, `settings.gradle.kts`, a module `build.gradle.kts`, `gradle.properties`,\n`gradle/libs.versions.toml`, or the `pulsar-dependencies` platform:\n\n- **Edit shared config in `build-logic/conventions/`**, not per-module.\n- **Versions come from `gradle/libs.versions.toml`** (`libs.*` / `pulsar-dependencies`) — never\n  hardcode a version in a build script.\n- **Keep tasks configuration-cache and configure-on-demand compatible** (both are enabled): no reading\n  of mutable state at execution time and no `Project` access in task actions — use `Provider` / value\n  sources, and verify with `--configuration-cache`. Tasks reached by the common flows (`assemble`,\n  `test`, `integrationTest`, `rat` / `spotlessCheck` / `checkstyle*`, `checkBinaryLicense`, `docker*`)\n  must be compatible; one-off tooling tasks not part of those flows (e.g. `verifyTestGroups`, ad-hoc\n  report tasks) may be exempt. When a third-party plugin is incompatible and cannot be fixed locally,\n  opt its tasks out with `notCompatibleWithConfigurationCache(\"<reason>\")` (see\n  `tests/pulsar-client-native-image/build.gradle.kts` for the GraalVM native-build-tools case) so the\n  build degrades to running without the cache instead of failing.\n- **Published modules must not depend on internal modules** at compile/runtime scope — the artifact\n  would be unresolvable from Maven Central. A module is published only when it applies\n  `pulsar.public-java-library-conventions`.\n- **After a dependency change**, run `./gradlew checkBinaryLicense` and update the distribution\n  `LICENSE`/`NOTICE`; justify any genuinely new dependency (see\n  [`CODING.md` → Dependencies](CODING.md#dependencies)).\n- **Follow the [Gradle best practices](https://docs.gradle.org/current/userguide/best_practices_index.html)**\n  — AI agents should read the\n  [AsciiDoc source](https://github.com/gradle/gradle/blob/master/platforms/documentation/docs/src/docs/userguide/best-practices/best_practices_index.adoc),\n  which is plain text and cheaper to parse than the rendered HTML.\n\nBefore finishing a build change, confirm the affected task and `./gradlew help` run clean with\n`--configuration-cache`, and that `assemble` and `quickCheck` (license headers + checkstyle across\nall modules) pass (plus `checkBinaryLicense` if a dependency changed).\n","isInternal":false,"tokens":2809,"sizeBytes":11756},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/apache/pulsar/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n","isInternal":false,"tokens":1672,"sizeBytes":7124},{"name":"CLAUDE.md","path":"microbench/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/apache/pulsar/HEAD/microbench/CLAUDE.md","title":"microbench - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n","isInternal":false,"tokens":1672,"sizeBytes":7124},{"name":"copilot-instructions.md","path":".github/copilot-instructions.md","rawUrl":"https://raw.githubusercontent.com/apache/pulsar/HEAD/.github/copilot-instructions.md","title":"GitHub Copilot Instructions","category":"copilot-instructions","format":"markdown","content":"../AGENTS.md","isInternal":false,"tokens":4,"sizeBytes":12}],"systemPromptSnippet":"<yakaai_skills repo=\"apache/pulsar\">\n<!-- File: AGENTS.md (Tokens: ~1672 | Category: root-instruction) -->\n# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n\n<!-- File: microbench/AGENTS.md (Tokens: ~154 | Category: root-instruction) -->\n# Agent guide for the microbenchmarks\n\nSupplemental guidance for AI coding assistants working on the JMH microbenchmarks, on top of the repository's\n[`AGENTS.md`](../AGENTS.md). [`README.md`](README.md) describes building, running and profiling the benchmarks; read\nit before running or writing one.\n\n- Run the benchmarks a question needs, selected with a pattern, rather than all of them.\n- Treat results from other platforms as provisional until they are confirmed on Linux x86_64, as the README explains.\n- A benchmark measures a single class or method. The effect of a change on a running cluster is what\n  [the Pulsar Performance Testing Framework](../tests/performance/AGENTS.md) measures.\n\n<!-- File: ARCHITECTURE.md (Tokens: ~2809 | Category: project-spec) -->\n# Architecture\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive (brokers, storage,\nnetworking).\n\nThe authoritative documentation lives at <https://pulsar.apache.org> — see the\n[Architecture Overview](https://pulsar.apache.org/docs/4.2.x/concepts-architecture-overview/) for the\nconceptual model. For a deeper, generated architecture description see\n[DeepWiki](https://deepwiki.com/apache/pulsar); coding agents can install the\n[DeepWiki MCP](https://docs.devin.ai/work-with-devin/deepwiki-mcp) for richer coverage of Pulsar's\narchitecture. This file is a map of the repository for contributors (and AI coding agents) who need to\nfind their way around the modules quickly.\n\n## Big picture\n\nPulsar separates a **stateless serving layer** (brokers) from **durable storage** (Apache\nBookKeeper) and a **metadata store** (Oxia / ZooKeeper). The Gradle modules layer\naccordingly:\n\n- **`pulsar-client-api`, `pulsar-client-admin-api`** — public, backward-compatible interfaces only.\n  `pulsar-client-api-v5` / `pulsar-client-v5` are the newer V5 client API (PIP-466/468).\n  Applications using either v4 or v5 can use [`pulsar-client-v5-all`](pulsar-client-v5-all/README.md)\n  for the unshaded client and admin together, or `pulsar-client-v5-shaded` for the combined shaded jar.\n- **`pulsar-client` (`:pulsar-client-original`)** — the Java client implementation\n  (producer/consumer/reader, connection pooling). `pulsar-client-admin` implements the admin REST\n  client.\n- **`pulsar-common`** — wire protocol and shared types. Protobuf / lightproto messages are\n  **generated** into `generated-lightproto/` / `generated-sources/` (excluded from checkstyle and\n  spotless).\n- **`pulsar-metadata`** — pluggable metadata store abstraction (Oxia / ZooKeeper, plus RocksDB and memory)\n  used by broker and bookkeeper.\n- **`managed-ledger`** — the storage abstraction over **Apache BookKeeper**: append-only ledgers +\n  cursors that track consumer/subscription positions. This is the durability layer the broker reads\n  and writes through.\n- **`pulsar-broker`** — the server. `PulsarService` is the composition root wiring everything\n  together; `BrokerService` manages topics, subscriptions, and client connections. Entry points:\n  `PulsarBrokerStarter` (broker), `PulsarStandalone` / `PulsarStandaloneStarter` (all-in-one),\n  `PulsarClusterMetadataSetup` (cluster init).\n- **`pulsar-proxy`** — optional proxy/gateway in front of brokers.\n- **`pulsar-functions/*`** — serverless compute (Functions): `proto`, `api-java`, `instance`,\n  `runtime`, `worker`, `localrun`.\n- **`pulsar-io/*`** — connector framework core only; most built-in connectors were moved to the\n  separate `pulsar-connectors` repo (PIP-465).\n- **`pulsar-transaction/*`** — transaction coordinator and common types.\n- **`tiered-storage/*`, `offloaders/`** — offload ledger data to cloud/filesystem storage.\n- **`pulsar-websocket`** — WebSocket-to-Pulsar bridge. **`pulsar-client-tools`** — the\n  `pulsar-admin` / `pulsar-client` CLIs.\n- **Shaded / distribution** — `pulsar-client-shaded`, `pulsar-client-all`,\n  `pulsar-client-admin-shaded` produce relocated fat jars; `distribution/*` assembles\n  server/shell/offloader tarballs.\n\n## Pulsar Improvement Proposals (`pip/`)\n\nThe **`pip/`** directory holds **Pulsar Improvement Proposals** (`pip-<N>.md`) — the design\ndocuments for significant changes, referenced as `PIP-<N>` throughout commit messages and code (e.g.\nPIP-463 = Maven→Gradle migration, PIP-465 = IO connectors moved out, PIP-466/468 = V5 client).\n`pip/README.md` describes the process and `pip/TEMPLATE.md` is the proposal template. Consult the\nrelevant PIP for the rationale behind a non-trivial feature or architectural decision. A PIP **number\nis reserved by the first `dev@pulsar.apache.org` thread that uses it** — start the discussion to claim\nthe next free number.\n\n## Concurrency model (a known gap)\n\nPulsar does **not** have a clearly established, documented concurrency model, which makes it hard to\nevaluate whether a given piece of code is correct by construction. (Contrast Netty, which has a clear\nrule: all handling on the IO thread is non-blocking, which by extension means avoiding synchronization\nand locks on that path.) Pulsar does not strictly follow such a rule; modern JVMs and hardware\noptimize `synchronized` code well enough that this has not blocked high performance, but it does make\nreasoning about correctness harder than it needs to be.\n\nConventions that **should** be documented (and largely are not yet):\n\n- which work belongs on the network-connection **event loop** vs. other threads;\n- how the various **thread pools** are intended to be used, and what kind of work belongs on each;\n- how threads are expected to **hand off state** to each other;\n- when a `CompletableFuture`'s **completion thread should be switched** to another thread, and which one;\n- **concurrency limits** for asynchronous tasks;\n- preferring the **single-writer principle** to avoid concurrent state mutation.\n\nUntil such a model is written down, follow the surrounding code's conventions and the Java-Memory-Model\nrules in [`CODING.md`](CODING.md#concurrency). Once a model is defined, it becomes far more tractable to\n\"lift and shift\" existing code toward it and enforce the rules consistently rather than having each\ncontributor rediscover the conventions case by case.\n\n## Backpressure\n\nClosely tied to the concurrency model is **backpressure** — how the system avoids accepting more work\nthan it can handle, particularly with respect to memory. The memory side is described in\n[PIP-442 \"Existing Broker Memory Management\"](pip/pip-442.md#existing-broker-memory-management). Broader\nbackpressure (beyond memory) is not yet documented and would benefit from being defined alongside the\nconcurrency model.\n\n## Build infrastructure\n\nApache Pulsar uses a **Gradle** build (migrated from Maven via PIP-463; some older tooling and docs\nelsewhere still reference Maven). The wrapper `./gradlew` requires **JDK 21, 25 or 26** (server bytecode\ntargets Java 21; client/API bytecode targets Java 17). See\n[`CONTRIBUTING.md` → Building](CONTRIBUTING.md#building) for the build and lint commands.\n\n- `settings.gradle.kts` — all modules, organized in dependency tiers (Tier 0 has no internal deps,\n  higher tiers build on lower ones).\n- `build-logic/conventions/` — convention plugins (`pulsar.java-conventions`,\n  `pulsar.code-quality-conventions`, `pulsar.shadow-conventions`, etc.) applied by modules. Shared\n  compile/test/dependency config lives here — edit it here rather than duplicating across modules.\n- `gradle/libs.versions.toml` — version catalog (single source of truth for dependency versions;\n  referenced as `libs.*` in build scripts).\n- `pulsar-dependencies` — enforced platform (BOM) pinning all dependency versions; applied to every\n  module.\n\nThe build enables both the **configuration cache** (`org.gradle.configuration-cache=true`) and\n**configure-on-demand** (`org.gradle.configureondemand=true`).\n\n### Module name vs. directory name gotcha\n\nSeveral Gradle project paths do **not** match their directory because the Maven artifactId is\npreserved. Most importantly:\n\n- Directory `pulsar-client/` → project **`:pulsar-client-original`**\n- Directory `pulsar-client-admin/` → project **`:pulsar-client-admin-original`**\n- Directory `pulsar-functions/localrun/` → project `:pulsar-functions:pulsar-functions-local-runner-original`\n\nAlways use the Gradle project path (left of any `--tests`), e.g. `./gradlew :pulsar-client-original:test`.\nCheck `settings.gradle.kts` when a path is ambiguous.\n\n### Java compatibility boundaries\n\n`pulsar.java-conventions` defaults main sources to Java 21 and explicitly lists the Java 17 client\nand public API dependency closure. This includes both client generations, admin/auth/crypto clients,\nTLS/HTTP SPIs, shared common/package APIs, and the Functions/IO interfaces. Functions implementations,\nbrokers, and other server components target Java 21. Client CLI tools also remain Java 17 compatible.\n`pulsarJavaVersion` and `pulsarClientJavaVersion` control these targets (defaults 21 and 17).\nTest sources default to `pulsarJavaVersion` so client tests can use server fixtures; the dedicated\nconsumer tests use `pulsarClientJavaVersion` for compilation and their runtime toolchain.\nThe bytecode check and published JVM metadata follow the configured client target.\n\nWhen adding a client dependency, keep its full compile/runtime closure Java 17 compatible. JVM\nvariant attributes reject Java 21 project dependencies; `verifyClientJavaCompatibility` also checks\nclass-file versions of dependencies without Gradle metadata and the final shaded client jars.\nMulti-release jars are checked using the entries selected by Java 17. This verifies bytecode, not\nall possible reflective or JDK API usage in third-party libraries; the Java 17 consumer tests provide\nruntime coverage. Do not mark a server implementation as Java 17 just to bypass a dependency error.\n\nThe client fastutil minimizer reads CLI classes as build-only reachability roots. Its published jar has no\ntransitive project dependencies and is checked as Java 17.\n`buildtools` and `testmocks` also stay Java 17 so the consumer compatibility tests can load them.\n\n### Changing the build\n\nWhen editing `build-logic/`, `settings.gradle.kts`, a module `build.gradle.kts`, `gradle.properties`,\n`gradle/libs.versions.toml`, or the `pulsar-dependencies` platform:\n\n- **Edit shared config in `build-logic/conventions/`**, not per-module.\n- **Versions come from `gradle/libs.versions.toml`** (`libs.*` / `pulsar-dependencies`) — never\n  hardcode a version in a build script.\n- **Keep tasks configuration-cache and configure-on-demand compatible** (both are enabled): no reading\n  of mutable state at execution time and no `Project` access in task actions — use `Provider` / value\n  sources, and verify with `--configuration-cache`. Tasks reached by the common flows (`assemble`,\n  `test`, `integrationTest`, `rat` / `spotlessCheck` / `checkstyle*`, `checkBinaryLicense`, `docker*`)\n  must be compatible; one-off tooling tasks not part of those flows (e.g. `verifyTestGroups`, ad-hoc\n  report tasks) may be exempt. When a third-party plugin is incompatible and cannot be fixed locally,\n  opt its tasks out with `notCompatibleWithConfigurationCache(\"<reason>\")` (see\n  `tests/pulsar-client-native-image/build.gradle.kts` for the GraalVM native-build-tools case) so the\n  build degrades to running without the cache instead of failing.\n- **Published modules must not depend on internal modules** at compile/runtime scope — the artifact\n  would be unresolvable from Maven Central. A module is published only when it applies\n  `pulsar.public-java-library-conventions`.\n- **After a dependency change**, run `./gradlew checkBinaryLicense` and update the distribution\n  `LICENSE`/`NOTICE`; justify any genuinely new dependency (see\n  [`CODING.md` → Dependencies](CODING.md#dependencies)).\n- **Follow the [Gradle best practices](https://docs.gradle.org/current/userguide/best_practices_index.html)**\n  — AI agents should read the\n  [AsciiDoc source](https://github.com/gradle/gradle/blob/master/platforms/documentation/docs/src/docs/userguide/best-practices/best_practices_index.adoc),\n  which is plain text and cheaper to parse than the rendered HTML.\n\nBefore finishing a build change, confirm the affected task and `./gradlew help` run clean with\n`--configuration-cache`, and that `assemble` and `quickCheck` (license headers + checkstyle across\nall modules) pass (plus `checkBinaryLicense` if a dependency changed).\n\n<!-- File: CLAUDE.md (Tokens: ~1672 | Category: claude-rule) -->\n# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n\n<!-- File: microbench/CLAUDE.md (Tokens: ~1672 | Category: claude-rule) -->\n# Agent guide for Apache Pulsar\n\nSupplemental guidance for AI coding assistants (Claude Code, Copilot, Cursor, Gemini, Codex, Aider,\nand similar tools) working in this repository. Keep this file short — it is a **router**. The detail\nlives in the human-facing docs linked below; read the one that fits your task rather than pulling\neverything into context up front.\n\nApache Pulsar is a distributed pub-sub messaging and streaming platform. The codebase is\nperformance-critical, heavily asynchronous, and concurrency-sensitive. Prioritize **correctness,\nthread safety, performance, maintainability, and backward compatibility**.\n\n## Licensing and provenance (read first)\n\nApache Pulsar is licensed under the Apache License 2.0, and all contributions must meet the ASF's\n[Generative Tooling guidance](https://www.apache.org/legal/generative-tooling.html):\n\n- **A human is in the loop and is accountable.** Every pull request and every security report must be\n  submitted by a human contributor who has reviewed and verified the change and takes responsibility\n  for it. Fully autonomous agents (e.g. OpenClaw-style bots) opening PRs or filing reports on their own\n  are not acceptable — the AI assists, the human is accountable.\n- **Don't introduce code of incompatible or unknown provenance.** Never copy verbatim from\n  GPL/AGPL/LGPL, proprietary, or unlicensed sources (including Stack Overflow / blog / forum snippets of\n  unclear licensing), and don't use a tool whose terms restrict the output inconsistently with open\n  source. Reimplement from specifications or Apache-compatible sources, and follow the\n  [ASF 3rd Party Licensing Policy](https://www.apache.org/legal/resolved.html).\n- **Every new source file needs the ASF license header** (Spotless enforces this — copy the form from\n  an existing `.java` file).\n- **Consider attributing AI assistance.** When AI tooling assisted on a change, consider adding an\n  `Assisted-by: <tool/version>` commit trailer (the default, since a human still does the final\n  review); `Generated-by: <tool/version>` is for minimally-modified generated output.\n\n## Canonical docs (read the one that fits the task)\n\n| Doc | Use for |\n|-----|---------|\n| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Local dev workflow: building (prerequisites, build/lint commands), running tests & test groups, integration tests, Personal CI, PR conventions, security reporting. |\n| [`ARCHITECTURE.md`](ARCHITECTURE.md) | Big-picture module map, the Gradle build infrastructure and how to change build files (convention plugins, version catalog, the module-name-vs-directory gotcha), the concurrency model and backpressure, and the `pip/` proposals. |\n| [`CODING.md`](CODING.md) | Coding conventions: style, async/`CompletableFuture`, concurrency, logging ([slog](https://github.com/merlimat/slog)), dependencies, backward compatibility, testing, and the review checklist. |\n| [`SECURITY.md`](SECURITY.md) | Reporting a vulnerability, disclosure hygiene, and checking exposure to an already-public CVE. |\n\nSome areas have an agent guide of their own, which routes to that area's docs; read it before working there:\n\n| Guide | Area |\n|-------|------|\n| [`tests/integration/AGENTS.md`](tests/integration/AGENTS.md) | The integration tests, which test Pulsar clusters in Docker containers. |\n| [`tests/performance/AGENTS.md`](tests/performance/AGENTS.md) | The Pulsar Performance Testing Framework, which runs a Pulsar cluster and its workloads in Docker on one host: performance experiments, profiling, A/B comparisons of revisions with charts, and automating them, including agent-based tuning. |\n| [`microbench/AGENTS.md`](microbench/AGENTS.md) | The JMH microbenchmarks, for the performance of a single class or method. |\n\nThe authoritative project documentation is at <https://pulsar.apache.org>, whose source lives in the\n[`apache/pulsar-site`](https://github.com/apache/pulsar-site) repository (where documentation changes\nare contributed). The files above and the website remain the source of truth — this guide just layers\nAI-specific pointers on top.\n\n## Agent guardrails\n\nA few rules matter specifically when an AI tool makes the change, on top of the canonical docs above:\n\n- **Verify, don't fabricate.** Before you use a class, method, field, configuration key, Gradle task,\n  plugin, or DSL name, confirm it actually exists (search the code or the build files) — don't invent\n  APIs, test assertions, or symbol names. Don't assert a CVE is \"fixed\" / \"not affected\" without\n  checking the merged PRs and the shipped version.\n- **Confirm state-changing actions.** Get the user's explicit confirmation before pushing, opening or\n  updating a PR, or posting a comment. Being asked to start a task is not standing authorization for\n  these outward-facing actions — see *Licensing and provenance* above.\n- **A clean local run is weak evidence for concurrency/data race fixes** (timing- and\n  platform-dependent). See [`CODING.md`](CODING.md#reproducing-concurrency--memory-visibility-bugs).\n- **Follow Java style guidance** in [`CODING.md`](CODING.md#style). One hard rule: reference classes\n  by simple name with an `import`, never by fully qualified name inline — unless two classes share a\n  simple name in one file, in which case the less used one stays qualified.\n- **Check before claiming conformance.** Run `./gradlew quickCheck` for a fast source-only pass\n  (license headers + checkstyle, no compilation) or `./gradlew sanityCheck` to also\n  compile every module's main and test sources; neither builds shadow jars. See\n  [`CONTRIBUTING.md`](CONTRIBUTING.md#building).\n\n## Critical rules\n\n1. **Don't break backward compatibility** — public APIs, client compatibility, wire protocol, and\n   serialized/metadata formats. Servers must interoperate with older and newer clients.\n2. **Never block on async/event-loop threads;** methods returning `CompletableFuture` must not throw\n   synchronously. See [`CODING.md`](CODING.md#asynchronous-programming).\n3. **Logging:** prefer [slog](https://github.com/merlimat/slog) via `@CustomLog`; default new logs to\n   `TRACE`/`DEBUG`, not `INFO`.\n4. **Tests:** scope runs with `--tests`; no reflection into private state (use a `@VisibleForTesting`\n   package-private accessor); release buffers and resources.\n5. **PRs:** semantic `[type][scope]` title; describe **motivation** and **modifications**; do not\n   rebase once the PR is open in `apache/pulsar` — merge upstream `master` instead.\n6. **Security:** never disclose a vulnerability — or the security nature of a change — in a public\n   issue, PR, or commit. See [`SECURITY.md`](SECURITY.md).\n7. **Stay in scope.** Keep a change focused on its task; don't bundle unrelated drive-by refactors or\n   generate broad mass-refactoring PRs. Discuss large refactorings on `dev@pulsar.apache.org` first.\n   See [`CONTRIBUTING.md`](CONTRIBUTING.md#pull-requests).\n\n## Where to ask\n\n- Dev mailing list: <dev@pulsar.apache.org> · Slack: <https://apache-pulsar.slack.com/>\n- Issues: <https://github.com/apache/pulsar/issues> · Discussions: <https://github.com/apache/pulsar/discussions>\n\n<!-- File: .github/copilot-instructions.md (Tokens: ~4 | Category: copilot-instructions) -->\n../AGENTS.md\n</yakaai_skills>"}