# Changelog
## Unreleased
## 0.4.0.0 — 2026-07-11
### Breaking Changes
* `KirokuAdapterConfig` and `KirokuConsumerGroupConfig` gain a
`queueCapacity` field, defaulting to 16 in the smart constructors.
* Requires `shibuya-core >=0.8 && <0.9` (was `>=0.7`) and `kiroku-store ^>=0.3`.
### Fixed
* Adapter subscriptions now rely on Kiroku's default lossless
`PauseAndResume` overflow policy instead of pinning fail-fast
`DropSubscription`.
* `guardKirokuHandlerWith` and `guardKirokuHandler` convert synchronous handler
exceptions into finalized ack decisions so Kiroku workers are not abandoned
mid-ack. `kirokuConsumerGroupProcessors` applies the default guard
automatically.
* `Adapter.source` now has regression coverage for EP-1's termination contract:
clean shutdown ends the stream normally, while a worker crash is rethrown to
the stream consumer.
* `kirokuConsumerGroupProcessors` now throws `InvalidConsumerGroup` for
non-positive group sizes before opening subscriptions, and cleans up already
created member adapters if a later member fails during construction.
* The package description and Haddocks describe the ack-coupled bridge instead
of the obsolete no-op ack behavior.
### Known Limitations
* `shibuya-core` still needs upstream fixes for finalize-on-exception in its
supervised processor and for propagating ingester stream failures from the
supervised runner. The adapter-side guard is defensive and remains correct
after those fixes land.
## 0.3.0.0 — 2026-06-05
### Changed
- Require `shibuya-core >=0.7 && <0.8`. `Envelope` now carries a
`headers :: Maybe Headers` field; `toEnvelope` sets it to `Nothing`,
because Kiroku events carry no ordered, raw broker headers. W3C trace
context continues to be surfaced via `traceContext` from event metadata.
## 0.2.0.0 — 2026-05-31
### Breaking Changes
#### Shibuya 0.6 and OpenTelemetry 1.0 semantics
* The adapter now targets `shibuya-core >=0.6 && <0.7` and
`hs-opentelemetry-api ^>=1.0`.
* `Envelope.attributes` now also carries current OpenTelemetry messaging
semantic-convention attributes for the Kiroku source:
`messaging.system = "kiroku"` and `messaging.destination.name` set to the
subscription name. These override Shibuya's framework defaults on the
per-message process span while preserving the existing `kiroku.*` attributes.
#### Ack decisions now drive Kiroku checkpointing (plan 40)
* The adapter bridges through `kiroku-store`'s ack-coupled
`subscriptionAckStream`: each event blocks the Kiroku worker until the Shibuya
handler's `AckDecision` is finalized, so the decision drives Kiroku
checkpointing per event. Previously `AckRetry` / `AckDeadLetter` were no-ops.
* `AckOk` — checkpoint past the event.
* `AckRetry delay` — redeliver the same event after `delay`, bounded by the
subscription's retry policy, then dead-letter on exhaustion.
* `AckDeadLetter reason` — record the event in `kiroku.dead_letters` (reason
translated to a Kiroku-native `DeadLetterReason`) and advance past it.
* `AckHalt` — cancels the subscription (unchanged).
* The envelope `attempt` now reports the zero-based redelivery count.
* `Shibuya.Adapter.Kiroku.Convert` exposes `toIngestedAck` (replacing
`toIngested`), `toKirokuResult`, and `toKirokuDeadLetterReason`.
### New Features
#### Kiroku identity on envelope attributes for end-to-end tracing (MasterPlan 6 EP-5)
* `Envelope.attributes` (previously always empty) is now populated with the
kiroku identity so it appears on Shibuya's per-message span:
`kiroku.subscription.name`, `kiroku.event.type`, `kiroku.event.global_position`,
and — for a consumer-group member — `kiroku.consumer_group.member`. Combined
with `kiroku-otel`'s native subscription spans, a single trace is followable
from a kiroku subscription into Shibuya's processing; the keys match on both
sides.
* `Shibuya.Adapter.Kiroku.Convert` exposes `KirokuEnvelopeAttrs`; `toEnvelope`
and `toIngestedAck` take it. `kirokuAdapter` derives the subscription name and
member from its config, so the single-adapter and consumer-group paths are both
covered. No `shibuya-core` change; the ack-handle logic and trace-context
propagation are unchanged.
#### `defaultKirokuAdapterConfig` smart constructor
* `defaultKirokuAdapterConfig name target` builds a `KirokuAdapterConfig` with
recommended defaults (batch size 100, buffer 256, no consumer group,
`AllEventTypes`, no selector); override individual fields with record-update or
a generic-lens label (`& #eventTypeFilter .~ …`). Prefer it over a full record
literal so a future field is inherited at its default automatically — mirrors
`defaultConsumerGroupConfig` and `kiroku-store`'s `defaultSubscriptionConfig`.
* `KirokuAdapterConfig` and `KirokuConsumerGroupConfig` now derive `Generic`,
enabling generic-lens label access/update of their fields.
#### Consumer groups as a single partitioned subscription (plan 42)
* `kirokuConsumerGroupProcessors` — present a whole kiroku consumer group as one
`PartitionedInOrder` unit: a single call yields `N` named `QueueProcessor`s
(one member adapter each, `ProcessorId "<name>-member-<m>"`), each pinned to
`(PartitionedInOrder, Serial)`. Replaces the manual `mapM mkMemberAdapter
[0..N-1]` wiring.
* `KirokuConsumerGroupConfig` + `defaultConsumerGroupConfig` — describe a whole
group (subscription name, target, group size, batch size, buffer size, and a
per-member `Concurrency` that must be `Serial`).
* `consumerGroupPolicy` — map a requested per-member `Concurrency` onto the
validated group policy `(PartitionedInOrder, Serial)`, reusing Shibuya's own
`validatePolicy` so `Ahead`/`Async` are rejected early with
`InvalidPolicyCombo` before any subscription opens.
* No `shibuya-core` changes: the helper only consumes existing exports.
#### Event-type filter and selector forwarding (plan 43)
* `KirokuAdapterConfig` and `KirokuConsumerGroupConfig` gain an `eventTypeFilter`
field (`AllEventTypes` / `OnlyEventTypes (Set EventType)`, default
`AllEventTypes`), forwarded into the underlying subscription so the adapter
delivers only the chosen event types. Filtering is worker-side, ahead of the
ack-coupled bridge, so a filtered-out event never reaches the Shibuya handler,
is never retried or dead-lettered, and the checkpoint still advances past it.
`EventTypeFilter (..)` is re-exported.
* Both config records also gain an optional `selector :: Maybe (RecordedEvent ->
Bool)` field (default `Nothing`) — the opaque escape hatch for filtering on a
property the type set cannot express (payload, metadata, correlation ids). It
composes with `eventTypeFilter` as a logical AND and is applied worker-side
with the same no-stall / checkpoint-advances guarantee. For a consumer group
the same predicate is applied to every member.
## 0.1.0.0 — 2026-05-23
### New Features
* Initial release.
* `kirokuAdapter` — create a Shibuya `Adapter es RecordedEvent` from a
Kiroku store handle and subscription configuration.
* `KirokuAdapterConfig` — subscription name, target, batch size, and
TBQueue buffer size.
* Ack semantics: AckOk/AckRetry/AckDeadLetter are no-ops (checkpoint
managed by Kiroku); AckHalt cancels the subscription.
* `Shibuya.Adapter.Kiroku.Convert` — RecordedEvent to Envelope mapping.