diff --git a/docs/data/roadmap.yaml b/docs/data/roadmap.yaml index 79c1d896f2..d0970df5bd 100644 --- a/docs/data/roadmap.yaml +++ b/docs/data/roadmap.yaml @@ -86,10 +86,13 @@ entries: one term, on both rebalance assignors, with the pre-fix arm failing every repetition and the fixed arm none. The family is not closed by it - the transactional revoke wait (astubbs#44, which carries upstream's verified-bug label) is a separate defect in a commit mode that fix - cannot reach, a third mechanism (a closing instance polling too little to leave its group - cleanly) has an open fix attempt in astubbs#444, and the family ledger - (`docs/inflight/bug-857-family.md`) still carries unattributed stall sightings reproducing on - trees that already carry astubbs#29's fix. + cannot reach - and on 2026-09-07 the owner placed it outside 0.6.0.0 for now, so the release + claim names it as the known exception rather than the release waiting on it. The suspected + third mechanism (a closing instance polling too little to leave its group cleanly) was measured + by astubbs#444 as the consumer-group protocol under the test's churn rate, not a PC defect. The + family ledger (`docs/inflight/bug-857-family.md`) still carries stall sightings on trees that + already carry astubbs#29's fix; the ones since classified are calibration and worker + saturation, not wedges. why_now: The release claim rests on it, and the evidence has to be inspectable rather than asserted. done_when: >- No known critical defect open in release scope, and each resolution has a named guard that @@ -100,7 +103,7 @@ entries: - id: streams-parallelism-preview title: Give a Kafka Streams topology the per-key parallelism of Parallel Consumer serves: [flexibility, performance] - horizon: "0.6.0.0" + horizon: next-0x blocks_1_0: false stage: limited-poc stage_delivery: draft @@ -117,7 +120,7 @@ entries: - id: connect-integration-preview title: Run a Kafka Connect sink with Parallel Consumer underneath serves: [flexibility] - horizon: "0.6.0.0" + horizon: next-0x blocks_1_0: false stage: limited-poc stage_delivery: draft diff --git a/docs/inflight/ci-the-coverage-uploads-still-use-the-inert-glob.md b/docs/inflight/ci-the-coverage-uploads-still-use-the-inert-glob.md index b0b8ab957a..d2504f4600 100644 --- a/docs/inflight/ci-the-coverage-uploads-still-use-the-inert-glob.md +++ b/docs/inflight/ci-the-coverage-uploads-still-use-the-inert-glob.md @@ -2,6 +2,7 @@ + diff --git a/docs/inflight/process-candidate-ranking.md b/docs/inflight/process-candidate-ranking.md index cbcae1abad..f489d90c8d 100644 --- a/docs/inflight/process-candidate-ranking.md +++ b/docs/inflight/process-candidate-ranking.md @@ -55,16 +55,32 @@ astubbs/parallel-consumer#29 carried. ## What gates v6, as the sweep read it -[`release-when-is-v6-good-enough.md`](release-when-is-v6-good-enough.md) set the bar as "the bugs -that are already open". Six area sweeps each named what they read as gating (the owner's pass over +Moved into `release-v6-scope.md` on 2026-09-08 and back here on 2026-09-09, because it is the +sweep's dated reading rather than a decision; the burn-down's tiers override it where they +disagree and say so there. Kept whole as the record. + +### The sweep's list, 2026-09-07 + +Moved here from `process-candidate-ranking.md` on 2026-09-08 (it was written by the six-agent sweep +on 2026-09-07 and is the agents' reading, with their stated confidence - not the owner's decision). +Where it disagrees with the tiers above, the tiers say so: the poisoned-transaction pair (the sweep: +not gating; the owner named it the second exception on 2026-09-09), the transactional revoke wait (the sweep read +astubbs#466 as having replaced the unbounded wait, which is right, and astubbs#408 as owning the +bound), and the `batchSize` validation bound (the sweep: cheapest real fix; the triage had filed +it as 0.6.0.x, and the owner moved it into tier 1 on 2026-09-09). Item 2 in its list, the dead poll thread, is +astubbs#477, merged. + +The bar above is "the bugs that are already open". Six area sweeps each named what they read as gating (the owner's pass over the sweep's proposals is done - [`process-inflight-vet-sweep.md`](process-inflight-vet-sweep.md) records it); this is the union, ordered by user-visible consequence, with the confidence each agent stated. The mechanical gate comes first because nothing else matters until it clears. -- **The quarantine registry is non-empty, and every entry is unowned.** `release.yml` refuses the - cut while [`docs/quarantined-tests.md`](../quarantined-tests.md) lists anything; read that file, - not this line. +- ~~**The quarantine registry is non-empty, and every entry is unowned.**~~ *The sweep's reading on + 2026-09-07; the registry is empty on master (astubbs#80 emptied it and nothing has joined since), + which this note says in its tag-day checks.* `release.yml` refuses the cut while + [`docs/quarantined-tests.md`](../quarantined-tests.md) lists anything; read that file, not this + line. - **Verified defects, in the code as written today:** 1. `bug-857-transactional-revoke-wait.md` - was the unbounded wait inside the revoke callback, with a user report carrying upstream's verified-bug label. astubbs#466 (merged the day the sweep @@ -73,14 +89,15 @@ comes first because nothing else matters until it clears. `core-revoke-commit-skips-the-work-mailbox-drain.md` as gating - a deterministic exactly-once break with C9 refuted - and the same commit fixed it; the note is gone and the record is in `docs/solutions/logic-errors/`. - 2. A dead poll thread holding its partitions for `max.poll.interval.ms` in the default commit mode - - read as gating, and traced end to end but untested and unfixed when the sweep ran. Now tested - and fixed: `maybeCloseConsumer` gained an arm for a poll thread that ended without closing the - consumer, the note is gone, and the record is in - `docs/solutions/logic-errors/a-duty-assigned-by-role-is-unassigned-when-the-role-holder-dies-2026-09-08.md`. + 2. A dead poll thread holding its partitions for `max.poll.interval.ms` in the default commit + mode - read as gating, traced end to end but untested and unfixed when the sweep ran. Now + tested and fixed by astubbs#477 (merged): `maybeCloseConsumer` gained an arm for a poll thread + that ended without closing the consumer; the note is gone and the record is in + `docs/solutions/logic-errors/`. 3. `pr-431-must-pair-its-queue-removal-with-the-shard-removal.md` with `bug-retry-queue-write-lock-on-the-rebalance-path.md` - the retry-queue orphan window; master - is still shard-first and astubbs#431 is a draft. + is still shard-first and astubbs#431 is a draft. *(Since overtaken: astubbs#431 closed as + superseded by the owner's astubbs#481, ready and green, which is what tier 1 lists.)* 4. `batchSize(0)` silently processing nothing - read as the cheapest real fix in the set, and it was. Now fixed: `validate()` rejects zero, a negative and null, which is astubbs#311's validation half; the arithmetic half stays open in `bug-batch-quantity-over-request.md`. The @@ -117,6 +134,66 @@ comes first because nothing else matters until it clears. by the shared-nothing rework); and the poisoned-transaction pair, where today's behaviour is strictly better than what it replaced. +### Every open bug note's disposition against the v6 bar, as of 2026-09-08 + +The sweep's reading above agrees with the look-at items below and added one this section had filed +as 0.6.0.x: `batchSize(0)` silently processes nothing, and the sweep calls the `validate()` bound +"the cheapest real fix in the set" (astubbs#311) - now in tier 1 by the owner's 2026-09-09 decision. Its list of instruments the release decision is +read through that are currently lying or unproven is worth reading before trusting a green. + +"Gate on open bugs" only works if every open bug has a disposition, so this is every `bug-` note on +master that no queue PR addresses (`ls docs/inflight/bug-*.md` is the list; the impact tag on each +is the sort key). Re-derive it before the tag rather than trusting it: a note can gain a PR or lose +its subject at any merge. + +**Look at before the tag - these contradict the release claim if left silent:** + +- ~~The eager-mode stall that reproduces with the fixes applied~~ - **withdrawn, astubbs#478 (merged)** + (2026-09-08): not a defect, a timing bound crossing on processor count. Nothing to ship or name. +- ~~Poller death leaves the consumer open in consumer-commit modes~~ - **now astubbs#477 in tier 1** + (2026-09-08). The fix was as small as the note proposed, and its defect-class sweep - cleanup gated + on "am I the role-holder?" where the holder may be dead - found no other instance across the four + modules' `close()` paths. + +**Owner's decision - taken 2026-09-08: in v6, as astubbs#480 (tier 1).** + +- ~~Run-length plausibility ceiling~~ - a readable but absurd run length marked a vast range complete + and PC silently skipped it; data-loss class, reachable only through a corrupt or foreign payload, + which is why astubbs#207 did not cover it. astubbs#480 bounds every decoded run and bitset by the + partition's log end offset - the one bound that cannot reject a real map, since PC only encodes + offsets it polled - routed through `invalidOffsetMetadataPolicy` with no parallel policy, failing + open with a warn if the broker will not answer. The same defect class was found and fixed in the + bitset decoder; the simple serialisation has no declared count and is clean. The inflight note is + retired into `docs/solutions/`. + +**0.6.0.x - open, real, not a gate for a bug release:** + +- Config lies: `maxFailureHistory` is read nowhere; `offsetCommitTimeout` bounds two different + waits; `batchSize`'s over-request arithmetic (astubbs#311's other half, deferred) - its validation + bound is in tier 1 since 2026-09-09. +- Blind spots: the racy and uncalled pause API; no metric for a discarded offset map under the + default `IGNORE` policy; the worker future swallowing framework exceptions. +- Misdirection: the plain-`int` out-for-processing counter; the module's processor reference + overwritten before the owner guard; the rest of the unbounded-log-lines class; the two 857 mirror + attributions never verified against the reporter's environment. +- Deferred with a reason in the note, and outside a bug release: the shard's available-work + counter undercounting after a stale replacement + ([`bug-processing-shard-available-work-undercount.md`](bug-processing-shard-available-work-undercount.md) + - a gauge inaccuracy that loses no records; the decision is whether the counter is worth keeping); + the deferred-commit WARN naming no offsets + ([`bug-deferred-commit-warn-names-no-offsets.md`](bug-deferred-commit-warn-names-no-offsets.md) - + astubbs#352 owns the method and adds the field the fix needs); and batching requesting a full + extra in-flight target ([`bug-batch-quantity-over-request.md`](bug-batch-quantity-over-request.md) + - throughput only). +- The shutdown teardown race; the test-only `close()` shadowing; and + [`bug-shared-collections-across-the-poll-boundary.md`](bug-shared-collections-across-the-poll-boundary.md), + which is mostly stale - the metrics set and the shared empty set it names are both fixed on master + and the note needs shrinking to whatever remains. + +**Not a bug note, but a signal - settled:** the `simpleBatchTest` failures across the Reactor, +Mutiny and Vert.x modules were the test's own randomised key draw, not the batcher (astubbs#482, +see the known-unknowns section). The register's most-sighted row is retired. + ## Ready picks Collisions are in `pr-blockers-and-collisions.md`. The ranked backlog and full verdicts live in diff --git a/docs/inflight/release-0.6.0.0.md b/docs/inflight/release-0.6.0.0.md index 6180e2dba5..91ad08e9c5 100644 --- a/docs/inflight/release-0.6.0.0.md +++ b/docs/inflight/release-0.6.0.0.md @@ -127,7 +127,7 @@ worth. At release, when the changelog section is regenerated, check both survived into `=== Breaking`: generation reads the commit log, so they are only as findable as those commit bodies. The rename side -of that same check is in [`release-0600-blockers.md`](release-0600-blockers.md). +of that same check is in [`release-v6-scope.md`](release-v6-scope.md), under the tag-day artefact checks. ## Public API change landing with astubbs#204: the commit give-up exception @@ -212,6 +212,22 @@ Evidence is in `docs/data/testing-evidence.yaml`; the checks to run are in `docs/data/module-maturity.yaml` under `release_validation`. If a check fails, amend the claim rather than waive the item. +**The claim is amended, 2026-09-07: one known critical defect is outside 0.6.0.0's scope, and the +release notes must name it.** The transactional revoke wait - astubbs#44, upstream's only +verified-bug label, `PERIODIC_TRANSACTIONAL_PRODUCER` only; **bounded since astubbs#466 by +`commitLockAcquisitionTimeout`, not yet declined** (astubbs#408 measures that bound and holds the decline seam; astubbs#466 refuted declining as the fix, so it is only the deadline fallback), so the release +note says "bounded, not yet declined" rather than "unbounded" - detail in +[`bug-857-transactional-revoke-wait.md`](bug-857-transactional-revoke-wait.md) - has its fix in +astubbs#408, which depends on producer-fencing recovery (astubbs#410) by design, and the owner has +placed that work after v6 for now. So the published sentence is not "every known critical defect", +it is "every known critical defect except this one, which is named, reproduced, and fixed on a +branch". **Amended again 2026-09-09: a second named exception, the poisoned-transaction wedge** - +in `PERIODIC_TRANSACTIONAL_PRODUCER` mode a single record the producer rejects as too large is +never aborted while the instance runs, so its partition stops for the life of the process; fixed +by astubbs#434 on the same stack, outside 0.6.0.0 by the same decision, and named beside +astubbs#44 rather than carried as a standalone abort. The standard is unchanged; the claim is what moved, which is the order this paragraph asks +for. If astubbs#410 lands before the tag, delete this paragraph. + **Deliberately not in this release:** virtual threads, micro-batching and the dead letter queue. These are new capabilities rather than known-defect exceptions, so deferring them does not weaken the gate. They carry horizons in `docs/data/roadmap.yaml`. diff --git a/docs/inflight/release-0600-blockers.md b/docs/inflight/release-0600-blockers.md deleted file mode 100644 index 42d855a754..0000000000 --- a/docs/inflight/release-0600-blockers.md +++ /dev/null @@ -1,103 +0,0 @@ -# Release 0.6.0.0 - correctness of the artefacts we are about to publish - - - - - - -Scope: are the things 0.6.0.0 *publishes* (`CHANGELOG.adoc`, `README.adoc`) true on the day we cut it? -Release mechanics live in [`release-0.6.0.0.md`](release-0.6.0.0.md); the tracking issue is astubbs#197. - -## Still open - -- **The package rename landed, so what is left is keeping the release notes honest about it.** - `io.confluent.parallelconsumer.*` → `bz.stub.parallelconsumer.*` went in with astubbs#294, and the - README and the `== 0.6.0.0` changelog section now both describe a namespace that exists - the docs - are no longer ahead of the code. The release-day risk is regeneration: that changelog section is - rebuilt from the commit log when the tag is cut, and generation reads commits, so it will not notice - that it has dropped a claim the current text makes. After regenerating, confirm the opening - paragraph and the `=== Breaking` bullet still name **both** changes - the Maven `groupId` and the - Java packages every import names - rather than reverting to "the only required change is the Maven - groupId". Reasoning, Apache 2.0 analysis and task inventory: - [`docs/plans/2026-08-11-001-refactor-package-rename-plan.md`](../plans/2026-08-11-001-refactor-package-rename-plan.md); - the project entry is [`branch-package-rename.md`](branch-package-rename.md). -- **Recheck the documentation data before the tag, and again after the critical fixes land.** The - published claim is now "every known **critical** defect resolved and evidenced", not "all known - defects" - the earlier wording was a promise the project cannot keep. Nothing verifies that claim - automatically; `bin/check-docs-data.sh` checks structure only, on purpose. So at release: - - Confirm no known critical defect is open in scope. The `confluentinc#857` deadlock is the live - one, and a module cannot honestly be described as fit for production use while a known defect can - lock up a consumer. If it is still open, amend the claim rather than the standard. - - Move the staged content up as its modules land: the Streams and Connect rows in - `docs/data/staging/module-maturity-rows.yaml`, and the record in `docs/features/staging/`. Each - move belongs to the PR that lands the thing, not to a later sweep - astubbs#271 for Streams, - astubbs#269 for Connect, both open and neither touching the data yet. - - **A third module has no row at all.** astubbs#268 adds `parallel-consumer-dashboard`, which is - also the 1.0 gate the roadmap calls a running-instance view. It needs a staged row and a feature - record before it lands, or it ships undocumented. - - Re-read the maturity wording itself. `stable` was withdrawn because it was untrue; the - replacement, `production-use`, is only as good as the critical-defect gate holding. - - **Rechecked at this commit (2026-09-05), the "before the tag" half only - the "again after the - critical fixes land" half stays open below.** `docs/data/module-maturity.yaml` was read and - deliberately left unchanged, and **what the pass actually saw is worth writing down, because the - file is only half conditional.** Each shipped module carries a bare `maturity: production-use` - field value with no condition attached to it, and *separately* a `support_posture` line reading - "Maintained for production use when the release validation passes." Only the second is qualified; - the first is a naked value that a renderer or a reader can lift on its own. Whether that unqualified - value is a claim the still-open confluentinc#857 family falsifies, or a category label the - `support_posture` line exists to condition, is a **release call for the maintainer** - so this pass - established the state and changed no value. The list is - `grep -n 'maturity:\|support_posture' docs/data/module-maturity.yaml`; the second recheck should - start from that rather than from "already conditional", which is what the first pass wrote and is - true of only one of the two. `docs/data/roadmap.yaml`'s - `known-defects-cleared` stage detail did carry a stale claim - it said astubbs#29 "remains - unmerged", and astubbs#29 merged 2026-09-02, fixing one confluentinc#857 mechanism (the - poll/control revoke-path deadlock). Corrected in place, without weakening what was already true: - the family is **not** closed by that merge. astubbs#44 (the transactional revoke wait) is a - separate defect the merged fix cannot reach, and `docs/inflight/bug-857-family.md` records - unattributed stall sightings reproducing on trees that already carry astubbs#29's fix. - The third mechanism this bullet used to carry - a closing instance - polling too little to leave its group cleanly - is no longer a PC-side candidate: astubbs#444 - merged 2026-09-07 carrying no product change, having measured that residual as the Kafka consumer - group protocol under the churn rate of the `largeNumberOfInstances` profile. So `confluentinc#857` - is still the open critical defect blocking this gate, and the "amend the claim rather than the - standard" instruction above still applies. - **Still open: recheck again after astubbs#44 and the family ledger's remaining sightings resolve** - - this pass only established today's state, not the state at cut. - -- **The rest of astubbs#197's triage list**, minus the ones that have since been picked up (an - `OffsetEncoding` magic-byte hazard in astubbs#217, the "Max loading factor steps reached" WARN in - astubbs#201). Still open: MDC context is not captured at submit time, so a caller's `trace_id` is - lost into the worker pool and the vert.x event loop. (The second item this bullet used to carry - - `release.yml` publishing an empty GitHub Release body - was already false when it was written: - astubbs#72 gave the workflow a `--notes-file` built from the `CHANGELOG.adoc` section on - 2026-07-29, with `--generate-notes` only as a fallback. Corrected 2026-09-07.) - -- **After it ships:** ~11 mirrored issues describe 0.6.0.0 in the future tense and need the real - coordinate; astubbs#186, astubbs#188 and astubbs#195 close with a pointer to the release. -- **Three `3.9.1` references - one was wrong, two are not.** The genuine defect was the CI - description telling contributors PRs run "split suites on default Kafka 3.9.1" when CI's default - is whatever `pom.xml` says - now `3.9.2`. **Fixed in astubbs#272**, which moved that text into - `docs/ci.md` and dropped the version entirely, so it names no number that can go stale again. - The other two are `bin/ci-build.sh 3.9.1` command examples - one in `AGENTS.md` under *How to - Build*, and the `bin/ci-build.sh 3.9.1` line in `src/docs/README_TEMPLATE.adoc`, which does reach the published `README.adoc`. Being - inside a published artefact does not make that one an error: it demonstrates that the script *takes* - a version argument and asserts nothing about which version CI defaults to, so it stays correct - whatever the pom says. Do not "fix" either of them. - -## Context worth inheriting - -- **`README.adoc` is generated - never hand-edit it.** Edit `src/docs/README_TEMPLATE.adoc` and - regenerate with `./mvnw -N asciidoc-template:build` (or `mvn process-sources`). Every README change - is therefore a two-file diff, and a PR that touches only the template has silently not changed the - published README. -- **`CHANGELOG.adoc` is not a per-PR chore, and the `== 0.6.0.0` section is not final** (AGENTS.md → - *Changelog*). It is regenerated from the commit log when the release is cut, so the text there now - is working text - do not quote it as the release notes. A PR editing the file is either fixing a - factual error in existing text or is wrong. When several agents work in parallel, exactly one may - hold that file - it is the highest-collision file in the repo and conflicts in it are pure noise. -- **Anything asserting a dependency version in prose can drift silently.** The `3.9.1`/`3.9.2` mismatch - arose because a Dependabot group bump moved `kafka.version` after the release note was written, and - nothing cross-checks prose against `pom.xml`. Re-read the `=== Dependencies` section against the pom - immediately before cutting, not weeks earlier. diff --git a/docs/inflight/release-experimental-module-records.md b/docs/inflight/release-experimental-module-records.md index a3896a27f9..f2c48b6130 100644 --- a/docs/inflight/release-experimental-module-records.md +++ b/docs/inflight/release-experimental-module-records.md @@ -2,7 +2,7 @@ - + `docs/features/kafka-streams-experimental.yaml` and `kafka-connect-experimental.yaml` were written and diff --git a/docs/inflight/release-v6-announcement.md b/docs/inflight/release-v6-announcement.md index 5d2b88b675..dc19d8cb02 100644 --- a/docs/inflight/release-v6-announcement.md +++ b/docs/inflight/release-v6-announcement.md @@ -11,6 +11,7 @@ announcement was invisible from master. The content is unchanged apart from punc above. Several documents it cites still live only on those branches; each is marked where it is cited, and `node bin/inflight.mjs docs show ` reads it from the branch that holds it. + **What this note is, corrected 2026-09-09 by the owner.** It is an aggregate written when 0.6.0.0 was going to carry features. It no longer does: 0.6.0.0 is a bugs-only stability release (decision of 2026-09-07), and the scope note carried by astubbs#475 is the source of truth for what ships. Most @@ -19,6 +20,7 @@ polyglot positioning, the performance inventory and the claims decision built on the next release, 6.1, which the owner plans to start on once 0.6.0.0 is cut. What this note contributes to 0.6.0.0 is the theme and the ordering of the announcement, and the rule that nothing experimental is claimed; [`release-0.6.0.0.md`](release-0.6.0.0.md) holds 0.6.0.0's own wording. + **Every performance figure below came from an experimental branch, not from master.** This note was written on the language-proxy branch and grew on the engine-performance stack, whose engine is diff --git a/docs/inflight/release-v6-scope.md b/docs/inflight/release-v6-scope.md new file mode 100644 index 0000000000..1cb30af5ff --- /dev/null +++ b/docs/inflight/release-v6-scope.md @@ -0,0 +1,535 @@ +# v6 (0.6.0.0) release scope and burn-down + + + + +**The source of truth for 0.6.0.0**: the owner's decisions, the burn-down to the tag, every open +question, and the tag-day checks. [`release-0.6.0.0.md`](release-0.6.0.0.md) holds the published +wording and answers "is it ready?"; this note answers "is it enough?" and, since the answer came +back "yes, once the fixes already built are merged", carries the list. Its own file rather than a +section, so it sits in the session-start index where an agent trips over it. Named +`release-when-is-v6-good-enough.md` until 2026-09-08, when it stopped being a question. + +## Every v6 note, and what each one owns + +**This file is the source of truth for the release.** astubbs#197 is the tracking *handle* - the +thing to link from PRs, mirrors and upstream threads - and since 2026-09-09 its body says only that +and points here; nothing is maintained on the issue. Everything else below owns one thing: + +| Where | Owns | +|---|---| +| [`release-v6-scope.md`](release-v6-scope.md) (this file) | Scope, the burn-down, every open decision, the tag-day checks, the upstream survey | +| [`release-0.6.0.0.md`](release-0.6.0.0.md) | The published wording: the release-note draft and the breaking-change record; "is it ready?" | +| [`release-0.6.0.0-issue-response-drafts.md`](release-0.6.0.0-issue-response-drafts.md) | Issue replies held until the release note exists; posted in the after-it-ships sweep | +| [`release-three-mirrors-label-undecided.md`](release-three-mirrors-label-undecided.md) | Three closed mirrors that may belong under the `0.6.0.0` label - owner's call | +| [`release-groom-1-0-train-issue.md`](release-groom-1-0-train-issue.md) | The 1.0 train issue, groomed against the roadmap data after v6 ships | +| [`release-experimental-module-records.md`](release-experimental-module-records.md) | Feature records for the modules that do NOT ship in v6 (deferred, 2026-09-07 decision) | +| [`process-candidate-ranking.md`](process-candidate-ranking.md) | Candidate ranking, the vetting sweep's reading of what gates v6, and the dated disposition of every open bug note | +| [`upstream-items-with-no-fix-and-no-response.md`](upstream-items-with-no-fix-and-no-response.md) | The survey of upstream items nothing addresses yet; after the tag | +| [`bug-857-family.md`](bug-857-family.md) | The register the release note's confluentinc#857 wording is read from | +| [`test-untracked-ci-flakes.md`](test-untracked-ci-flakes.md) | The flake register - a tag needs a green master | +| [`docs/releasing.md`](../releasing.md) | The mechanics: strip `-SNAPSHOT`, merge, `publish.yml` deploys and tags, `release.yml` cuts the GitHub release from the curated changelog section | +| [`docs/data/roadmap.yaml`](../data/roadmap.yaml), [`docs/data/module-maturity.yaml`](../data/module-maturity.yaml) | The claims rendered into the README; the maturity value is a tag-day recheck | +| `CHANGELOG.adoc` | Generated from the commit log at release time; working text until the tag | +| [`docs/plans/2026-07-28-release-pipeline-hardening.md`](../plans/2026-07-28-release-pipeline-hardening.md) | The dated plan for the publish pipeline | +| [`release-v6-announcement.md`](release-v6-announcement.md) | The announcement theme and plan, qualified on 2026-09-09 as 6.1 material with its figures from an experimental branch; what it lends 0.6.0.0 is the theme, the ordering and the experimental-claims rule | +| `release-v6-merge-order.md`, `release-0600-blockers.md` (deleted) | Folded into this file on 2026-09-08; `git show 2c874ecac:docs/inflight/release-0600-blockers.md` for the history | + +**astubbs#197's body was shed to a pointer on 2026-09-09.** Everything it carried is either done on +master (its two artefact claims, its not-blocking list) or in the tiers and the tag-day list below +(the after-it-ships sweep, including the announcing comments on the three upstream threads that +asked for a release). The old body is in the issue's edit history. + +## The decisions - 2026-09-07 by the owner, confirmed and extended 2026-09-08 + +**v6 is a bug release. It is overdue. The bar is the one already stated** in +[`release-0.6.0.0.md`](release-0.6.0.0.md) under *"This release is a stability release, and that is +the point"* - nothing else has to be true. The owner took four decisions on 2026-09-07 (recorded on + +branch `docs/v6-scope-decisions`, merged into astubbs#475) and confirmed the bar on 2026-09-08: + +- **The bar is the stability release, and nothing else.** "Every known critical defect resolved, + with a guard" is the whole bar. Anything not fixing an open bug or clearing a release gate is out + of v6, however finished it looks. That one sentence settles the feature PRs without arguing each: + the commit-failure seam, virtual threads, residence time, the proxy stack, the perf campaign. +- **Streams and Connect do not ship in v6.** Both moved to the `next-0x` horizon in + `docs/data/roadmap.yaml`; the announcement carries them as what is coming. The feature-record + note that waited on their modules is deferred. +- **The transactional revoke wait (astubbs#44) is outside v6 for now, and the claim names it.** Its + fix (astubbs#408) is stacked on producer-fencing recovery (astubbs#410) by design, not by + chronology: declining the lock is only safe once a fenced producer is recoverable. So the choice + was the whole fencing work in v6 or the claim naming the exception, and the owner chose the + exception. `release-0.6.0.0.md`'s release condition carries the amended claim, with the + instruction to delete that paragraph if astubbs#410 lands before the tag. +- **The `0.6.0.0` issue label means "closes when the release ships".** Swept the same day; the + features and the decision-only mirrors lost it. +- **Which open items are genuinely v6?** (2026-09-08) The merge queue below, and only it. A thing + being ready is not a reason to ship it in this one. +- **Does the roadmap announcement have to be simultaneous?** (2026-09-08) No. Its plan is + astubbs#446; it can land before the tag and take pressure off sooner. The announcement is what + lets the first release be a bug release without being the only thing anyone sees. + +**Why a stability release is the right first release.** The scope question carried an unstated +assumption: that the first release of a revived fork must be a feature release to justify the +attention it gets. The record does not support that. The change set since 0.5.3.3 is the largest +this codebase has shipped in one version: the confluentinc#857 commit-path deadlock, the torn-read +family, the metrics leak, offset accuracy on assignment, the async-commit acknowledgement, the +package rename, MDC propagation, the log-noise fixes, and the chaos and Lincheck lanes that guard +each of them. For the users this project serves, that is the release that matters. What people +learn about the direction of the project comes from the roadmap announcement, which is decoupled +from the tag, so the release does not need to carry it. The cost of the alternative is already on +record: the 26 August target passed with nothing shipped, and the previous version of this note had +named "never shipping" as the failure mode to avoid. + + +**Prior art this supersedes, and what it still gets right.** A merge-order note from 2026-08-08, +`release-v6-merge-order.md`, sat on the never-pushed branch `docs/v6-merge-order`; that branch was +merged into astubbs#475 and the file removed there, so the note is in history +(`git log --all --oneline -- docs/inflight/release-v6-merge-order.md`) and nowhere live. It ordered a far larger v6: the +transactional-atomicity trio first, then the loss and confluentinc#857 fixes, then **new surface** +(the health check, MDC, the mock consumer in the main jar), then **new opt-in modules** (the +dashboard, the Streams and Connect proofs of concept) and the examples rewrite, on the argument that +a first release whose job is to make "actively maintained" credible should ship the surface. Its +first two tiers have all merged. **The 2026-09-08 decision overrides its tiers three, seven and +eight**: new surface and new modules are not defects, so they do not gate a bug release, and the +announcement plan carries the "maintained, and past where upstream stopped" claim instead. Two of +its points survive: astubbs#197's body reads as more blocked than it is (since shed to a pointer), and +astubbs#199 - which it called the one item that cannot follow the tag - can, because the release +page body is posted by hand on the day (tier 3) and astubbs#199 only automates that. Its open question +of which modules v6 publishes is moot under this decision, since no module PR is in the queue. + + + +**"Draft" on a fork PR means "needs the owner to review and merge", not "unfinished".** Every PR in +the queue below is implemented, tested and green on everything except the human-LGTM gate and, where +it stacks, the dependency gate. `gh pr list -R astubbs/parallel-consumer` shows near enough every +PR as a draft, so the state flag carries no information here; what a PR still needs is written +against it below, because that is the part `gh` cannot say. + +## Proposed cut-off and order of work + +**Confirmed by the owner, 2026-09-09: the merge queue is closed as of today.** Nothing joins it that +is not already a fix for an open defect with a PR. Anything a soak or a chaos lane finds after +2026-09-09 is a 0.6.0.x unless it is data loss on a default configuration, and then it joins tier 1. +Tag when tier 3 is done, not when the "can follow" list is empty. + +The order is chosen so that every merge is independently shippable - if the queue stops anywhere, +what is on master is still a release. + +### Tier 1 - self-contained fixes, any order, each blocked only on LGTM + +Data-shaped and stall-shaped, no design question open, no stack. These are the release. + +- [x] **astubbs#470** - merged 2026-09-08. An async commit counts as committed when the broker + answers, not when it is sent; silent loss on the shipped default commit mode. Serves astubbs#248. +- [x] **astubbs#466** - merged 2026-09-08. The revoke-path commit drains the work mailbox first; in + transactional mode a rebalance could publish a transaction whose offsets omitted records it + contained. Its proof left quarantine with it. Its commit body says it **collides with astubbs#408 + on `tryCommitOffsetsOnRevoke`**, so astubbs#408 now carries that resolution. +- [x] **astubbs#468** - merged 2026-09-08. `WorkContainer` equality is identity, so the stale + sweep removes only the container it inspected, never a fresh replacement racing in from the + controller. Marked breaking (`fix(core)!`) for the equality change; the release note carries it. + Of the two further by-key removals astubbs#483 found, astubbs#468 dismissed one + (`ProcessingShard.onSuccess` - the third staleness checkpoint drops a stale result first) and + astubbs#492 fixed the other, the revoke sweep, merged 2026-09-09. +- [x] **astubbs#469** - merged 2026-09-08. The two remaining `PartitionState` flags that cross + threads, measured and then fenced or redesigned; the follow-on astubbs#349 deliberately left. +- [x] **astubbs#481** - merged 2026-09-08. The poll thread never touches the retry queue; the + controller collects what it leaves. The owner's own PR, superseding astubbs#431 (closed - correct + and proven, but more machinery than the defect needed). Same stall from the confluentinc#857 + defect-class sweep: an unbounded fair write-lock wait inside the rebalance callback, spent out of + `max.poll.interval.ms`. astubbs#483 (the shard-displacement reachability verdict) stacked on it + and is being brought level. +- [x] **astubbs#473** - merged 2026-09-08. Cleared the two remaining quarantine entries by fixing + what they were about; `docs/quarantined-tests.md` is empty and the release guard no longer blocks + on it. It also moved the capacity profiles behind a `capacity` tag with scheduled runners, so + their pass rate is measured rather than gating. +- [x] **astubbs#480** - merged 2026-09-09. An offset map whose run or bitset extends past the partition's log end + offset is an unreadable payload, not a completed range. Silent skip of real records on a corrupt + or foreign payload; proven red through the real assignment path, green with the guard, mutation + lane green on the bound. Reworked off the wire before merge: the claim is settled lazily at the + first poll batch against a watermark read without blocking from the consumer's own position and + lag, so no broker round trip sits inside the rebalance callback. Promoted from the + owner's-decision list on 2026-09-08. +- [x] **The `batchSize` validation bound** (astubbs#496, merged 2026-09-09) - `batchSize(0)` silently + processed nothing and a negative value failed obscurely; one `validate()` bound in the options, + in the style of its neighbours, now rejects zero, a negative and null (astubbs#311, the + validation half only - the over-request arithmetic stays deferred, so the issue stays open). A + startup exception where there was silence, so it carries `!` and the release note names it under + breaking. +- [ ] **The gate-latch warning** (astubbs#497, draft, in review; decided 2026-09-09) - a WARN when + the record-intake load gate has read loaded across many consecutive control-loop ticks while + nothing retired: the state astubbs#487 measured, today exported only as a paused-partition gauge + and logged nowhere. A log line, no semantic change; the last item to join the queue before it + closed. The Claude review is answered; the Codex review's findings are being worked through. +- [x] **astubbs#477** - merged 2026-09-08. A dead broker-poll thread now closes the consumer in + the consumer-commit modes, the shipped default among them, so the group rebalances at once instead + of after `max.poll.interval.ms`. One derived predicate and one condition, proven red on every + consumer-commit mode and green on the transactional control arm; the review's close-time + subtlety was characterised by running it (no second close - the ownership guard declines the + retry). Retires its inflight note into `docs/solutions/`. + +### Tier 2 - the producer-recovery stack: OUTSIDE v6 by the 2026-09-07 decision, named in the claim + +astubbs#225 (survive producer fencing rather than dying) is a feature, and two open **defects** are +stacked on it: the transactional revoke wait (astubbs#44, upstream's verified-bug label) and the +poisoned-transaction wedge. The owner chose on 2026-09-07 not to pull the whole fencing stack into a +bug release, and to name astubbs#44 as the one known critical defect outside scope instead. **That +call stands unless the owner reopens it**; this tier records the stack and its order so that if it +is reopened - or if the stack simply lands before the tag - nothing has to be re-derived. + +The order, bottom-up, each rung re-cut on 2026-09-07 so it can be reviewed against pieces already +reviewed: astubbs#472 (vocabulary and plumbing, no behaviour change), astubbs#474 (keep every +completed record until the commit that carries it succeeds), astubbs#410 (recovery itself, closes +astubbs#225), astubbs#434 (abort a transaction poisoned by a terminal send failure), astubbs#408 +(a revocation declines the transaction lock, closes astubbs#44 - the one PR in the stack with real +reds, and it must now resolve the `tryCommitOffsetsOnRevoke` collision with the merged +astubbs#466), then astubbs#420 (producer-ownership polish, after v6 in any case). + +**Decided 2026-09-09: the poisoned-transaction wedge is the second named exception**, beside +astubbs#44 in `release-0.6.0.0.md`; astubbs#434 stays in tier 2. The wedge ([`bug-poisoned-transaction-not-aborted-while-running.md`](bug-poisoned-transaction-not-aborted-while-running.md), +which astubbs#476's vetting sweep merged its sibling note into) +is fixed by astubbs#434, which also stacks on astubbs#410. With the stack outside v6 the claim +has two named exceptions: a single oversized record stops its partition for the life of the +process in transactional mode. The astubbs#476 vetting sweep read the pair as **not gating** +("today's behaviour is strictly better than what it replaced"); the owner named it anyway rather +than carry a standalone abort. + +### Tier 3 - release plumbing, then tag + +- [ ] **Finalise the `== 0.6.0.0` changelog section as the release notes** (astubbs#498, in + review). `docs/releasing.md` says the section is generated at release time, but there is no + generator in `bin/`, so astubbs#498 is that generation done by hand from the commit log and the + release document. Until it merges the section is working text; after it, the section is what + the release page carries. +- [ ] **Post the release page body by hand.** `release.yml` tries to build the notes from the + `CHANGELOG.adoc` section, but its heading match is exact and the section is headed + `== 0.6.0.0 (unreleased)`, so on master it matches nothing and falls back to generated notes. + On the day: convert the curated section and `gh release edit v0.6.0.0 --notes-file ` + after `release.yml` has cut the release. astubbs#199 fixes the match and can follow. +- [x] **astubbs#446** - merged 2026-09-09. Lift the announcement plan onto master, so the announcement is not being + written from a branch nobody merges. +- [ ] The tag-day artefact checks in the section of that name below. +- [ ] Amend the release claim, not the standard, for what is still open (astubbs#498, in review, + carries it). `release-0.6.0.0.md` already names astubbs#44 as the exception (2026-09-07) and the + poisoned-transaction wedge as the second (2026-09-09); astubbs#498 adds the "claim as published" + paragraph there, and its changelog section on consumption stopping after a rebalance says which + confluentinc#857 mechanisms are closed, each with its PR, and names the one arm still + unattributed: a member that stops answering the coordinator during a churn storm. Ticks when + astubbs#498 merges. +- [ ] Post the drafted issue responses (`ls docs/inflight/issue-response-*.md` and + [`release-0.6.0.0-issue-response-drafts.md`](release-0.6.0.0-issue-response-drafts.md)) in the + pre-release sweep [`docs/releasing.md`](../releasing.md) describes. +- [ ] Tag. Then the after-it-ships items below, and the rest of astubbs#197. + +### Can follow - finished or nearly, and deliberately not v6 + +Named so nobody re-argues them in: the producer-recovery stack in tier 2 (by the 2026-09-07 +decision, unless reopened); astubbs#199 (the changelog heading match in `release.yml` - the release +page body is posted by hand on the day, so this follows the tag); astubbs#352 (commit-failure seam - a feature, even though +confluentinc#833's reporter patched the library for it), astubbs#226 (health check), astubbs#306 +(offset density), astubbs#360 (virtual threads), astubbs#405 (the torture harness - test +infrastructure; astubbs#471's soak has merged and its finding is in the confluentinc#857 list), astubbs#479 (the +God-class decomposition plan and the five classes below it - a refactor track whose own notes say +which open PRs must merge before each cut, so it follows the release rather than gating it), and +every Streams, proxy, perf, rate-limiting and dashboard stack. + +## What v6 must say about the confluentinc#857 family + +[`bug-857-family.md`](bug-857-family.md) owns the evidence; its retirement rule is that every +mechanism is individually explained or closed, so the family does not close with the release. +What v6 ships, and what the release note has to be honest about: + +**Closed on master** (each with its guard): the poll/control commit deadlock (astubbs#29), the +poller death on `RebalanceInProgressException` (astubbs#100), the draining busy-spin (astubbs#80), +the orphaned retry entry (astubbs#346), the poll-thread NPE (astubbs#345), the load-gate phantom +counts (astubbs#336), the sign-reversed shard count (astubbs#373), the retry-queue orphan window +(astubbs#437), a revoke surviving a failed assignment (astubbs#451). The lag-stagnation line was +demoted to a timing proxy, and astubbs#444 measured the large-instance residual as group-protocol +churn rather than a PC defect. + +**Still open - the release note names each, and each has an agent on it (2026-09-08).** A ticked +box means the v6 action for that line is done, not that the defect is closed: + +- [x] **astubbs#408 (tier 2, after v6)** - the transactional revoke wait, astubbs#44 + (confluentinc#803). Outside v6 by the 2026-09-07 decision; the release claim names it as the + known exception. The decision predates astubbs#466, which replaced the unbounded spin with a wait + bounded by `commitLockAcquisitionTimeout`, so what astubbs#408 still owns is the measurement of + that bound and the held decline seam - astubbs#466 refuted declining as the fix, so it is only the + deadline fallback. The v6 action is the release-note sentence, and + [`release-0.6.0.0.md`](release-0.6.0.0.md) now says "bounded, not yet declined" rather than + "unbounded". astubbs#408's own probe still reads the callback over the poll-interval budget on + today's master, which is the defect reproduced against the bounded design; its title and whether + it still closes astubbs#44 are the owner's, after v6. +- [x] **astubbs#488 (merged 2026-09-09)** - `INSTANCE_STALL` and `ZOMBIE_MEMBER` sightings that replay clean on + idle runners, so they read as starvation rather than a wedge. The idle replay was the weak + direction: a load-shaped stall needs the load. astubbs#488 ran the load arm - three seeds, idle + and under CPU burners, one term differing - and on one seed both arms crossed the bound that raised + every gating firing on CI, with the detector reporting the member busy in user code and no stall + violation or dump in any arm, every window proven open. Starvation, confirmed from the load side. + It proposes a PROPOSED close for the `INSTANCE_STALL` line only, owner-gated; the `ZOMBIE_MEMBER` + arm never fired, so nothing there moves; its two recorded seeds and the busy-observation + calibration are what the experiment runner stays for, and its retire condition is in the + runner's row. Merged. +- [x] **astubbs#487 (merged 2026-09-09)** - **the intake stall under an always-failing key, found by + astubbs#471's soak, is the load gate, and head-of-line blocking is not why.** Three arms, one + term each, predictions written first, every one confirmed. Under KEY ordering with half the keys + poisoned, the gate `WorkManager#isSufficientlyLoaded` latched true on the first fetch, under a + second in, and never unlatched: every partition paused, successes frozen at the same count + astubbs#471 saw after thirty minutes, failures retrying at full worker throughput. UNORDERED + stalls identically, which refutes the head-of-line half, and the KEY arm's own arithmetic refutes + it harder - one burst over a thousand distinct keys leaves at most one record per key, so nothing + was queued behind any head. Raising only the gate's threshold (`messageBufferSize`) flips the + outcome: gate false, nothing paused, successes rise - the positive control that says the gate is + the latch. What latches it is records that are themselves workable, retried forever, never + retiring. Offset-encoding back pressure re-eliminated in all three logs. + **There is no gate fix.** The threshold arm exposes the second bound: lifting the intake bound + doubles successes and then plateaus while the held population climbs without limit, so a bigger + threshold trades a hard stall for an unbounded-memory slow starve, and "count only what is + selectable" would let a healthy instance fetch without bound. The property that discriminates is + liveness of the shard head, not decidable from shard state. **The fix bounds the failures, not + the buffer: astubbs#149's dead-letter queue (confluentinc#310), after v6.** One same-class + instance found and pinned by assertion: `drain()` gates on the same over-count. No product code + changed. astubbs#487 carries the flag that reaches the gate's DEBUG line, the gate's operands on + the soak's progress line, one knob per arm, the accounting gap as a characterisation test, and + the working note. confluentinc#833's flat processed-records counter is this state. + **For the release note, and it is stronger than "a poison-record workload":** the stall does not + need a high failure rate, and it does not need saturated workers either. The gate reads + `inShards - parkedForRetry`, and the parked term is throughput times retry delay, not a + population property - it sat at the same value across a thirty-fold change in population. So the + unparked count is the poison population minus what the retry service is holding in back-off, and + it crosses the gate's threshold as soon as the population outgrows that. A fourth arm at a low + poison rate, prediction first, latched the gate at under a hundred held records about a minute + in, with three of fourteen workers busy: the instance stopped fetching while mostly idle and + looking healthy, successes flowed for minutes and then froze for the rest of the run. A slower + retry service latches sooner, since fewer records are parked and more read as workable. So any + long-lived instance with no user-side terminal handling and any poison at all gets there + eventually, silently, and for good: the latch is exported only as a paused-partition count and + logged nowhere, and no poller wakeup is ever attempted because the wakeup is itself gated on the + same reading. That is the best explanation yet for confluentinc#809 and confluentinc#833's flat + processed-records counters. The owner decided on 2026-09-09 not to ask those reporters (assume + no reply); the drafted question stays unposted. One thing the arms did not explain, flagged as the + next arm: the observed retry cadence is about three times the configured delay, and the latch + point is a function of it. **Decided 2026-09-09: the interim warning is v6-sized** - a WARN when + the gate has read loaded across many consecutive ticks while nothing retired, no semantic change - + and joins tier 1 as its own item, still to be built. astubbs#487 itself is merged; the + retry-cadence arm is what remains of the measurement. + +**Resolved or reassigned - one line each, so the release note can say what was ruled out:** + +- The eager-mode stall on trees carrying astubbs#29's fix - **withdrawn, astubbs#478 (merged):** a + timing bound crossing that flips with the processor count; the grid it was opened on was never a + one-term A/B. What survives is the per-shard liveness gap, narrowed by astubbs#491. +- The async-unordered rebalance stall, the family's fifth item - **the group protocol, astubbs#486 + (merged):** a join phase the coordinator holds open, during which every member's poll returns + nothing, then recovers; PC holds nothing during it (control arm). The `ZOMBIE_MEMBER` line does + not discriminate a PC hold from the coordinator, so a sighting is told apart by the closing + members' threads. +- A dead broker-poll thread leaving the consumer open in consumer-commit modes - **fixed, + astubbs#477 (merged).** + +## What v6 must say about data loss and duplicates + +- **Fixed on master, 2026-09-08:** the async-commit acknowledgement (astubbs#470). +- **Fixed on a branch outside v6 scope, and named as the second exception (2026-09-09):** the + poisoned-transaction wedge (astubbs#434, stacked on the producer-recovery work) - see tier 2. +- **Fixed on master:** the revoke-path transaction omitting offsets (astubbs#466); the torn-read family + ([`bug-torn-read-family.md`](bug-torn-read-family.md) - astubbs#337, astubbs#344, astubbs#345, + astubbs#346, astubbs#349); a terminally failed send publishing half a result set (astubbs#261); + the produce-lock double release (astubbs#257); `InvalidPidMappingException` looping + (astubbs#429). +- **By design, needs a documentation reply, not a fix:** in-flight work at revocation is redelivered + (confluentinc#777, [`upstream-173-revocation-duplicate-processing.md`](upstream-173-revocation-duplicate-processing.md)). + One chaos cell (cooperative plus draining) was predicted and never run; a revocation grace period + is an owner decision. +- **Refuted, astubbs#484 (merged 2026-09-08):** the "reset to earlier offset" replay branch behind + confluentinc#546 (its note retired by astubbs#494 into + [`absence-of-commit-data-was-inferred-from-a-sentinel-that-a-real-commit-shares-2026-09-09.md`](../solutions/logic-errors/absence-of-commit-data-was-inferred-from-a-sentinel-that-a-real-commit-shares-2026-09-09.md)). + One fixture, one differing term, both arms' predictions held: polled-below-expected discards every + loaded incomplete and rewinds the commit frontier, which is duplicates by construction, never + loss; and the note's own hypothesis - that `committed()` races the client's position resolution - + is refuted against the kafka-clients source, where the listener runs strictly before the fetcher + resolves positions. The only PC-owned route to that branch was astubbs#337's defect, now pinned + by a four-shape round-trip test. What remains under astubbs#162 is the **false-truncation WARN**: + a new group, and every partition recovered through the foreign-metadata path, logs "truncating" + having truncated nothing. Misdirection operators may alert on; not a data risk. **Decided + 2026-09-09:** absent commit data does not warn - a distinct INFO line saying no committed offset + was found and the partition starts from the polled offset, no truncation branch taken, and the + WARN kept for the genuine truncation cases. Fixed by astubbs#494 (merged 2026-09-09), which closes + astubbs#162: absence of commit data is now recorded from the codec's default entry rather than + inferred from a sentinel that a real commit at offset zero shares, all three defects behind the + warning string are settled, and the mirror's fork-status text is drafted for the pre-release + sweep. +- **Never reproduced:** the commit-response timeout (confluentinc#809, confluentinc#833). astubbs#471 + (merged) is the first experiment that hunts it; its first runs could not reach the timeout because + the instance stalled first - see the intake-stall item in the confluentinc#857 list above, which + is now the live lead. Not a v6 gate in itself; the release note says the symptom's known causes + are fixed and the reports were never reproduced. + +## Known unknowns the release note should not paper over + +**What is still unknown at the cut, so the release note names it rather than implies it is closed.** +Each was surfaced by the work that resolved the items under "Unknowns made known" below, and none is +a v6 gate; the note must simply not claim more than the suite or the code can show. + +- **A single wedged shard is invisible to everything that gates - narrowed to the shard half by + astubbs#491 (merged 2026-09-09).** astubbs#478's surviving finding, owned by + [`test-per-shard-liveness-has-no-gate.md`](test-per-shard-liveness-has-no-gate.md). The commit + half is closed: a red control (one partition's commits answered and dropped, every existing + gating detector shown green on it with an armed control so the silence is not vacuous) came + first, and the gate that came second compares two positions - a member's own next offset to + commit against what the group has committed - held across samples with the group stable, so the + demoted timing bound's false positive is excluded structurally. Both replay seeds the demotion + was argued from re-ran across the old bound with the new gate silent. The note's own prescription + was refuted on the way: "completions advancing" is instance-wide and does not discriminate. What + remains is the shard half: a key-order shard that will never be dispatched again inside an + otherwise healthy partition still gates nothing, any incomplete offset pins the local watermark, + and no red control exists for it - astubbs#483 found the nearest mechanism unreachable, so it is a + reachability question first. The release note says the suite cannot see that shape. One sibling + found by the sweep is recorded, not fixed: the ledger's duplicate allowance is fleet-wide while + redelivery is per-partition. +- ~~**One unconditional by-key shard removal remains on master**~~ - **fixed, astubbs#492 (merged + 2026-09-09).** The revoke sweep in `ShardManager.removeWorkFromShardFor`, the second of the two + astubbs#483's defect-class sweep found, now declines to evict an occupant that is both from a + different registration and still live; red first on a fresh container that had displaced the + stale one, with an ablation arm per leg of the guard. No unconditional by-key removal of a + container remains in main. The retry queue's by-key removal is the same shape but is that queue's + keying model, reported by astubbs#483 and left. Cost before the fix was misdirection bounded to + one control-loop tick by astubbs#481's purge, never loss. +- **The other rows of [`test-untracked-ci-flakes.md`](test-untracked-ci-flakes.md)** - astubbs#482 + closed the most-sighted row, and astubbs#490 (merged 2026-09-09) worked the rest: the + `processInKeyOrder` sanity-check row was already fixed on master by astubbs#29's merge (every + sighting predates it - the wait counted control-loop cycles while the poll thread fills the + batch); a shutdown test whose "in flight" stand-in was two loop cycles is fixed with a control arm; + the ambient-probe extension test's process-global log capture is fixed; rows whose owners merged + without retiring them are retired; four rows stay open with their reasons, none meeting the + quarantine bar. Nothing quarantined. A tag needs a green master, so what is left is tag-day work + rather than scope. +- The maturity claim itself: `docs/data/module-maturity.yaml` carries a bare `production-use` next + to a conditional support posture, and a renderer can lift the bare value without its condition. + The tag-day checks below carry the recheck. + +## Unknowns made known, 2026-09-08 + +Each was a known unknown at the start of 2026-09-08 and was pursued by its own agent on its own +branch; the replay-shaped ones ran one at a time on one machine. One line each; the PR and its +solutions write-up hold the evidence. + +- Whether the six deadlock captures ever replay clean with astubbs#29's fix - **unanswerable by + replay, and proven another way, astubbs#485 (merged):** the fix replaced the monitor the captures + identify the defect by, so a clean replay would say nothing; the control arm on the deterministic + probe passes with the fix and fails every run with it restored. PROPOSED close for the owner. +- Whether the shard-displacement orphan window is reachable - **unreachable, astubbs#483 (merged):** + four-arm test, one per ordering mode plus same-key cross-partition; the one caveat is an + in-generation replay, which no main code produces and astubbs#481 bounds to misdirection. +- Whether "rejoin" after producer fencing is expressible - **yes, by reading the astubbs#472, + astubbs#474 and astubbs#410 diffs:** the instance never leaves the group, so rejoin reduces to + abort, rebuild the producer, replay under the write lock. The one open question, declining the + lock during a rebalance, stays with tier 2. +- Which flakes are load-shaped and which real - **the batch test's own key draw, astubbs#482 + (merged),** and the rest of the register worked by astubbs#490 (merged). + +## What the vetting sweep read, and every open bug note's disposition - moved out + +Two records that were here until 2026-09-09 now live in +[`process-candidate-ranking.md`](process-candidate-ranking.md): the astubbs#476 vetting sweep's +reading of what gates v6, and the disposition of every open `bug-` note against the bar as of +2026-09-08. Both are dated agent readings, not decisions, and the tiers above are what overrode them +where they disagree. What this note kept from them is already in the tiers: the poisoned-transaction +wedge as the second exception, the `batchSize` bound and the gate-latch warning in tier 1, the +withdrawn eager stall, the false-truncation warning on astubbs#494. Re-derive the open-bug list +before the tag rather than trusting either copy: `ls docs/inflight/bug-*.md`, and the state and +impact markers each note carries. + +The survey of upstream items with no fix PR and no prepared response is +[`upstream-items-with-no-fix-and-no-response.md`](upstream-items-with-no-fix-and-no-response.md); +it is research for after the tag, not scope. + +## Tag-day artefact checks - are the things we publish true on the day we cut? + +Folded in from the register that was `release-0600-blockers.md`. Scope: `CHANGELOG.adoc` and +`README.adoc` as published. Release mechanics stay in [`release-0.6.0.0.md`](release-0.6.0.0.md); +the tracker is astubbs#197. + +- **Master must be green, and several lanes are known to lie or to fail on their own.** The + autopsy that omits fleet violations, the perf lane's wall-clock deadline, the codecov flags that + are not like-for-like, and the broker container's undiagnosable exit. The churn scenario's + thirty-second no-progress window was settled by replay and widened to the measured 60s in + astubbs#499 (every firing watched past detection drained; the 60s value is borrowed from the + revoke scenario and its sufficiency was measured on one desktop, not the runner), and the same + sweep left one survivor of that class armed on that scenario, the rebalance-dwell bound, which has + fired on a docs-only commit. The Lincheck lane's job timeout went from 20 to 60 minutes in the + same PR: its cost is a fixed budget that cannot stop early, and hosted-runner speed varied twofold + on a clock rather than a commit. Each has its own note; read the flake register and those notes + before believing a red or a green on the day. +- **The package rename shipped (astubbs#294); keep the release notes honest about it.** The + `== 0.6.0.0` changelog section is rebuilt from the commit log when the tag is cut, and generation + cannot notice that it dropped a claim the current text makes. After regenerating, confirm the + opening paragraph and the `=== Breaking` bullet still name **both** the Maven `groupId` and the + Java packages every import names, not just the `groupId`. Reasoning and the Apache 2.0 analysis: + [`docs/plans/2026-08-11-001-refactor-package-rename-plan.md`](../plans/2026-08-11-001-refactor-package-rename-plan.md). +- **Recheck the documentation data after tiers 1 and 2 land.** The published claim is "every known + **critical** defect resolved and evidenced". Nothing verifies it automatically - + `bin/check-docs-data.sh` checks structure only, on purpose. `docs/data/module-maturity.yaml` is + only half conditional: each shipped module carries a bare `maturity: production-use` and, + separately, a `support_posture` line that is qualified ("when the release validation passes"). + Whether the bare value is a claim the still-open confluentinc#857 items falsify, or a label the + posture line conditions, is the owner's call - start from + `grep -n 'maturity:\|support_posture' docs/data/module-maturity.yaml`, not from "already + conditional". A first pass on 2026-09-05 established the state and changed no value; it did + correct a stale claim in `docs/data/roadmap.yaml`'s `known-defects-cleared` entry (it said + astubbs#29 was unmerged). The staged Streams and Connect rows in + `docs/data/staging/module-maturity-rows.yaml` and the records in `docs/features/staging/` stay + staged: under the bug-release decision no module PR is in the queue, and each moves with the PR + that lands its module. +- **The release page must carry the curated notes.** `release.yml` already builds a notes file from + the `CHANGELOG.adoc` section (astubbs#72) - the 2026-09-07 vet of the old blockers note was right + that "the body is empty" was never the whole story - but its heading match is exact and the + section is headed `== 0.6.0.0 (unreleased)`, so it matches nothing and falls back to generated + notes - so the body is posted by hand on the day (tier 3), and astubbs#199, which fixes the match, + follows the tag. The rest of astubbs#197's triage list has been picked + up: the magic-byte hazard in astubbs#217, the load-factor WARN in astubbs#201, and MDC in + astubbs#205 (`MdcPropagation` on master captures and restores the caller's context; the + 2026-09-08 vet that called the gap "real" grepped for a name the class does not use). The + tracker's own checklist boxes lag the work. +- **Three `3.9.1` references, and only one was wrong.** The CI description that named the default + Kafka version was fixed in astubbs#272 by dropping the number. The `bin/ci-build.sh 3.9.1` command + examples in `AGENTS.md` and in `src/docs/README_TEMPLATE.adoc` (which reaches the published + README) demonstrate that the script takes a version argument and assert nothing about CI's + default. Do not "fix" either. +- **After it ships:** the mirrors that describe 0.6.0.0 in the future tense need the real + coordinate (`gh issue list -R astubbs/parallel-consumer --label 0.6.0.0` finds them); + astubbs#186 and astubbs#195 close with a pointer to the release (astubbs#188 already is); one + announcing comment each on upstream confluentinc#880, confluentinc#885 and confluentinc#907, the + deliberate exception to one-backlink-per-issue; the `issue-response-*.md` drafts are posted in the + same sweep; and astubbs#197, the tracking handle, closes with the tag. + +Context worth inheriting on the day: + +- **`README.adoc` is generated - never hand-edit it.** Edit `src/docs/README_TEMPLATE.adoc` and + regenerate with `./mvnw -N asciidoc-template:build`. A PR that touches only the template has + silently not changed the published README. +- **`CHANGELOG.adoc`'s `== 0.6.0.0` section is working text until astubbs#498 merges** - that PR + rewrites it from the commit log as the release notes (tier 3), so until then do not quote it as + the release notes, and when agents work in parallel exactly one holds that file; it is the + highest-collision file in the repo. Anything that merges after astubbs#498 with a release-note + line has to be folded into the section by hand before the tag. +- **The README's trademark wording claims nothing it does not have.** The 2026-08-11 branding + rename put "KAFKA ... has been licensed for use by Antony Stubbs and contributors" at the top of + the README and in the attribution section - the Foundation's boilerplate for a licence nobody + holds. astubbs#495 removes the top note and rewrites the attribution sentence as nominative use: + a registered mark of the Foundation, an independent library that works with Apache Kafka, no + affiliation and no endorsement. On the day: reread the attribution section against the + Foundation's third-party naming guidance, and confirm no "licensed" claim has crept back in. +- **A dependency version in prose drifts silently.** The `3.9.1`/`3.9.2` mismatch came from a + Dependabot group bump moving `kafka.version` after the note was written. Re-read the + `=== Dependencies` section against `pom.xml` immediately before cutting, not weeks earlier. + +## Delete when + +The tag is cut. Migrate first: the family and data-loss dispositions above go into the release note +text and `docs/data/roadmap.yaml`'s `known-defects-cleared` entry; the "context worth inheriting" +bullets go to [`docs/releasing.md`](../releasing.md) if it does not already carry them; the +upstream survey's residue goes to +[`upstream-coverage-completeness.md`](upstream-coverage-completeness.md) if any of it is still +unanswered after the sweep. diff --git a/docs/inflight/release-when-is-v6-good-enough.md b/docs/inflight/release-when-is-v6-good-enough.md deleted file mode 100644 index d6101fb271..0000000000 --- a/docs/inflight/release-when-is-v6-good-enough.md +++ /dev/null @@ -1,78 +0,0 @@ -# When do we ship v6? The "enough is enough" decision, not the blocker list - - - - - -**Deliberately its own file, not a section inside -[`release-0.6.0.0.md`](release-0.6.0.0.md).** A section is invisible until someone opens that file; -a note gets its own line in the session-start index. This question needs to be *met*, not looked up -- so it is filed where an agent trips over it. - -The other two release notes answer different questions and neither answers this one: -[`release-0.6.0.0.md`](release-0.6.0.0.md) is the content and the breaking-change record; -[`release-0600-blockers.md`](release-0600-blockers.md) is correctness of the artefacts we are about -to publish. **Both answer "is it ready?". This one asks "is it enough?"** - which is a judgement, not -a checklist, and no gate will ever go red for it. - -## The tension, stated so it can be argued with - -**People are more likely to look at a first release than a second.** For a revived fork that is -sharper than usual: the attention comes once, when the project visibly comes back to life. A second -release does not get a second launch. - -Which creates real pressure to cram v6 - to make the one release anyone definitely looks at carry -everything worth seeing. That pressure is why this note exists rather than a bare "ship when the -blockers close": the failure mode is not shipping something broken, it is **never shipping**, with -each addition individually justified. - -## What resolves it - -**Announce the roadmap alongside the release.** If people hear what is coming, the first release -does not have to be the only thing they see. That decouples "what ships in v6" from "what people -learn about the project", which is what the cramming instinct was really protecting. - -The roadmap data already exists (`docs/data/roadmap.yaml`, `docs/features/`), so this is a -publishing decision rather than new work - which is exactly why it can be decided rather than built. - -## The date, set 2026-08-24 - -**Target: Wednesday 26 August 2026**, and it is the fork announcement rather than a routine tag - the -roadmap publishes alongside it, which is the resolution above being taken rather than deferred. Every -piece of work in flight now is to be judged against that launch: not "is this good?" but "does this -have to be in the thing people look at once?" - -**It is gated on the bugs that are already open, not on scope.** Anything not fixing one of those is -arguing to be in a release it does not block - which is the cramming instinct this note exists to -name. The bar the date sets is therefore narrower than the one under "Still open": those questions -remain live, but a proposal that cannot point at a currently-open bug does not need them answered to -be declined. - -A date makes the failure mode concrete. Until now the risk was never shipping, with each addition -individually justified; with a date the risk becomes shipping the date and quietly dropping the -announcement or the roadmap, which are the parts that make the release cost less than it looks. - -**2026-09-07: the date passed and nothing shipped.** Recorded rather than rewritten, because the -paragraph above is what was decided on 2026-08-24 and the failure it names is the one that happened. -Twelve days after the target the pom is still `0.6.0.0-SNAPSHOT`, there is no `v0.6.0.0` tag, the -quarantine registry is non-empty so `release.yml`'s guard would refuse the cut anyway, and the -roadmap announcement the date was really for has not gone out. The call this note asks for is -therefore still unmade, and it is now unmade *past* its own deadline - which is evidence for the -note's own thesis, not against it. - -## Still open - -- **What is the actual bar for v6?** "Stability release" is stated in `release-0.6.0.0.md` under - *"This release is a stability release, and that is the point"*. Is that the whole bar, or does - something else have to be true? -- **Which currently-open items are genuinely v6, and which are v6 only because they are finished?** - A thing being ready is not a reason to ship it in this release. -- **Does the roadmap announcement have to be simultaneous with the release**, or can it precede it - and take some of the pressure off sooner? - -Nothing here is blocked on engineering. It is blocked on the call. - -**High priority, and it needs a conversation rather than a PR.** Flagged as needing discussion by -the owner on 2026-08-19, explicitly NOT as work to fold into whatever PR is open at the time - a -scope judgement decided in passing, inside a branch about something else, is exactly how the -cramming happens. Take it on its own. diff --git a/docs/inflight/upstream-161-reactor-scheduler-rationale.md b/docs/inflight/upstream-161-reactor-scheduler-rationale.md index 80307d65e2..f5ad8467af 100644 --- a/docs/inflight/upstream-161-reactor-scheduler-rationale.md +++ b/docs/inflight/upstream-161-reactor-scheduler-rationale.md @@ -55,8 +55,8 @@ while it is open, not in the root README. ## The answer to post, then close -astubbs#161 is not on the 0.6.0.0 blocker register in -[`release-0600-blockers.md`](release-0600-blockers.md); its `0.6.0.0` label groups it with the other +astubbs#161 is not on the 0.6.0.0 tag-day checks in +[`release-v6-scope.md`](release-v6-scope.md); its `0.6.0.0` label groups it with the other question mirrors to answer around the release. Post this and close, keeping the existing labels: > Good question, and the answer changed after you filed this. diff --git a/docs/inflight/upstream-items-with-no-fix-and-no-response.md b/docs/inflight/upstream-items-with-no-fix-and-no-response.md new file mode 100644 index 0000000000..a7b75aeb16 --- /dev/null +++ b/docs/inflight/upstream-items-with-no-fix-and-no-response.md @@ -0,0 +1,80 @@ +# Upstream items with no fix PR and no prepared response + + + + + +Surveyed on 2026-09-08 for the v6 burn-down and moved out of +[`release-v6-scope.md`](release-v6-scope.md) on 2026-09-09, because nothing in it gates the release; +it is what the after-it-ships sweep and the next release's triage start from. + + +Every upstream open issue carries a fork reply from the 2026-08-05 mirror sweep pointing at its +mirror, so nothing upstream is silent. What follows is what has **no fix PR, open or merged, and no +draft response beyond that pointer**. Reproduce the survey rather than trusting this list: join +`gh issue list -R confluentinc/parallel-consumer --state open`, the mirrors +(`gh issue list -R astubbs/parallel-consumer --state all --label upstream-mirror`), fork PRs citing +`confluentinc#N` (`gh pr list -R astubbs/parallel-consumer --state all --json title,body`), the +manifest `src/docs/development/upstream-map.yaml`, and `scripts/upstream-sweep.sh --audit`. +[`upstream-coverage-completeness.md`](upstream-coverage-completeness.md) owns the standing +obligation; this section is one dated pass at it, kept here because the pre-release sweep is when +these get answered. + +**Bugs with no fix PR:** + +- confluentinc#843 (astubbs#178) - same key on two threads across a rebalance. A contract question, + wait-for-info; [`core-178-key-order-across-a-rebalance.md`](core-178-key-order-across-a-rebalance.md). +- confluentinc#546 (astubbs#162) - truncating state; the replay branch is refuted (astubbs#484, merged), + the false-truncation WARN is decided (INFO, no truncation branch) and being built on its own PR. +- confluentinc#551 (astubbs#164) - batching not as expected; the fork verified the over-request as + astubbs#311, no PR. +- confluentinc#887 (astubbs#189) - a poison record re-forms the identical batch on every retry; + manifest says none. +- confluentinc#777 (astubbs#173) - settled as by-design; the documentation reply and the grace-period + decision are what remain. +- confluentinc#597 (astubbs#166, mirror closed as fixed) - the poller-death residual above. +- confluentinc#803 (astubbs#44) - has astubbs#408, addressed on paper only until it merges. + +**Feature requests with nothing behind them** (no branch, PR or note beyond the mirror): + +- API surface: confluentinc#78 executor customisation, confluentinc#170 `CompletableFuture`, + confluentinc#520 safe consumer-API exposure, confluentinc#782 seek to offset, confluentinc#860 + managed-executor params, confluentinc#879 no-commit option. +- Error handling: confluentinc#304, confluentinc#391 and confluentinc#550 - deserialization failures, + the largest cluster of user asks with no design; + [`core-163-poll-path-has-no-error-seam.md`](core-163-poll-path-has-no-error-seam.md) confirms there + is no seam. confluentinc#718 terminate processing. +- Batching and ordering: confluentinc#314 combine queues across partitions, confluentinc#560 min + batch plus max wait (roadmap: ideated), confluentinc#902 freshest record per key, confluentinc#321 + large-message chunking. +- Performance: confluentinc#322 disk-backed produce queue, confluentinc#394 least-loaded broker, + confluentinc#540 per-partition backpressure. +- Docs and examples: confluentinc#171 Spring Boot example, confluentinc#178 fan-out with DLQ, + confluentinc#180 vert.x POST, confluentinc#115 tombstones javadoc. + +Two mirror labels overstate coverage: confluentinc#314 and confluentinc#394 carry `pr-available` on +their mirrors, and no fork PR cites either. + +**Upstream open PRs with no fork action or comment:** + +- confluentinc#915 batch construction strategy - manifest none; the roadmap's batch-composition + decision is pending. A contributor is waiting on this one. +- confluentinc#867 Vert.x 5 major - nothing in the fork. +- confluentinc#908 virtual threads - the fork went its own way in astubbs#360 and replied on the + issue, never on the contributor's PR. +- confluentinc#918, confluentinc#919, confluentinc#920, confluentinc#901 - each absorbed by fork work + (the log-noise fixes, `docs/building.md`, dropping the licence plugin), and none of the four PRs + has a comment saying so. + +**Unanswered conversations:** + +- confluentinc#894 got a follow-up on 2026-09-01 asking where interactive replay should live. Partly + vendor marketing; the only unanswered direct question upstream. +- Upstream discussions with zero replies - `scripts/upstream-sweep.sh --audit` lists them; + [`upstream-discussions-unanswered.md`](upstream-discussions-unanswered.md) defers them to after v6. + +**Drafted and waiting, not gaps:** the `issue-response-*.md` drafts and the astubbs#337 drafts for +confluentinc#894. [`upstream-tell-809-833-the-hang-is-fixed.md`](upstream-tell-809-833-the-hang-is-fixed.md) +is stale in one respect: both reports already carry the 2026-08-05 fork reply, though neither has +been told the fixes merged. + diff --git a/docs/plans/2026-08-11-001-refactor-package-rename-plan.md b/docs/plans/2026-08-11-001-refactor-package-rename-plan.md index 0ca7eeade2..131b10072f 100644 --- a/docs/plans/2026-08-11-001-refactor-package-rename-plan.md +++ b/docs/plans/2026-08-11-001-refactor-package-rename-plan.md @@ -11,7 +11,7 @@ the rename was run in a throwaway clone and thrown away with it; the real run co **Expires:** expired on execution. Kept because the licence analysis (§2), the wire-format finding (§4.1) and the traps in §5 are the reasoning behind the tool, not a plan anyone still has to follow. **Ledger entry:** [`docs/inflight/branch-package-rename.md`](../inflight/branch-package-rename.md) -**Release gate:** [`docs/inflight/release-0600-blockers.md`](../inflight/release-0600-blockers.md) +**Release gate:** `docs/inflight/release-0600-blockers.md` - folded into `docs/inflight/release-v6-scope.md` on 2026-09-08; the version this plan cited is `git show 2c874ecac:docs/inflight/release-0600-blockers.md` **Prior art:** none. `docs/plans/`, `docs/solutions/`, `docs/inflight/`, [`docs/refactoring.md`](../refactoring.md) and the issue tracker (all states) were searched for a package rename before this was written and returned nothing. The adjacent work that exists is the diff --git a/docs/refactoring.md b/docs/refactoring.md index a451bc594d..091a4796f8 100644 --- a/docs/refactoring.md +++ b/docs/refactoring.md @@ -544,6 +544,13 @@ cosmetic - see the last bullet.* comparison" analysis-only code once the encoding choice is settled. `question sneaky throws usage` / `enforce max uncommitted`: `sneaky throws` IO handling; missing `max-uncommitted < Short.MAX` bound. +- **astubbs#480 leaves the codec's consumer dependency where it was.** Its first revision bounded + every decoded run and bitset by a blocking `consumer.endOffsets(...)` round trip inside the + rebalance callback; the rework moved the check off the wire entirely. The codec now only passes + the committed offset into `PartitionState`, which settles the loaded map's claim lazily at its + first poll batch against a watermark `ConsumerManager` reconstructs without blocking + (`position` plus `currentLag`, on the thread that owns the consumer). So the split above does not + inherit a ground-truth lookup: the plausibility check already lives outside the codec. - **The cached-and-shared instance is still only safe by the schedule, not by construction.** Since confluentinc#892 / astubbs#57 the instance is *cached and shared* (per-partition diff --git a/docs/solutions/documentation-gaps/competitor-comparison-docs-must-cite-the-primary-spec.md b/docs/solutions/documentation-gaps/competitor-comparison-docs-must-cite-the-primary-spec.md index 2f565aabd9..dabdd9b365 100644 --- a/docs/solutions/documentation-gaps/competitor-comparison-docs-must-cite-the-primary-spec.md +++ b/docs/solutions/documentation-gaps/competitor-comparison-docs-must-cite-the-primary-spec.md @@ -285,7 +285,7 @@ leaves half the table stale. has since been sharpened. - astubbs#222 -- the same move in a different medium: having established what the library provides over the competitor, make the advantage *measurable* rather than merely asserted. -- `docs/inflight/release-0600-blockers.md` -- the sibling concern for version claims: "are the things +- `docs/inflight/release-0600-blockers.md` (folded into `docs/inflight/release-v6-scope.md` on 2026-09-08; the cited version is `git show 2c874ecac:docs/inflight/release-0600-blockers.md`) -- the sibling concern for version claims: "are the things 0.6.0.0 publishes true on the day we cut it?" Same class (nothing tests prose), different trigger (a fact changed underneath static text, rather than text that was under-sourced when written). - `docs/inflight/docs-site.md` -- parks the KIP-932 chapter as future work and points at diff --git a/src/docs/development/upstream-map.yaml b/src/docs/development/upstream-map.yaml index f8f035d07d..8393b77a93 100644 --- a/src/docs/development/upstream-map.yaml +++ b/src/docs/development/upstream-map.yaml @@ -1249,7 +1249,7 @@ entries: - id: bug-546-bootstrap-truncation-warning group: rebalance-stability summary: The "Truncating state" warning on assignment - three defects behind one string, all three now settled here - fork: {branches: [fix/162-offset-reset-replay-branch, fix/162-absent-commit-data-warns], prs: [484, 494], fork_issue: 162, status: in-progress} + fork: {branches: [fix/162-offset-reset-replay-branch, fix/162-absent-commit-data-warns], prs: [484, 494], fork_issue: 162, status: merged} upstream: {repo: confluentinc/parallel-consumer, issues: [546], prs: [563], related: [489, 545], status: open, last_checked: 2026-09-09} adoc_anchor: null notes: >