Skip to content

feat(package-events): queue-backed delivery, payload schemas, and subscription filters - #1229

Merged
kody-bot merged 2 commits into
mainfrom
cursor/package-events-queued-dispatch-1f86
Aug 5, 2026
Merged

kody-bot merged 2 commits into
mainfrom
cursor/package-events-queued-dispatch-1f86

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Aug 4, 2026 •

Copy link
Copy Markdown
Owner

What

Package-emitted events (kody.emits + events.dispatch) move from synchronous in-request fan-out to durable, queue-backed delivery, and gain payload contracts and working subscription filters.

  • Queued-only delivery. events.dispatch validates the event and enqueues it on a new kody-package-events-dispatch Queue (with -dlq dead-letter queue), returning { topic, source, idempotencyKey, status: "enqueued" } immediately. The old synchronous fan-out (and its per-subscriber return payload) is removed. The Queue consumer resolves the emitting user's subscribers at delivery time and invokes handlers with the existing exactly-once idempotency keys, so Queue redelivery replays instead of re-running. Pre-execution infrastructure failures retry (3 attempts, then DLQ); terminal handler failures ack and stay visible in run records. Consumer concurrency is capped at 16.
  • Inline fallback where the queue binding is absent (local dev, preview) or when an enqueue fails, through the same consumer code path — matching how SCHEDULED_DISPATCH_QUEUE degrades. The fallback reports status: "delivered_inline" so callers can tell durable enqueue from best-effort inline delivery.
  • payloadSchema on kody.emits entries. Optional, documented JSON Schema subset (packages/shared/src/json-schema-subset.ts); unsupported keywords fail package checks at publish time, payloads are validated at dispatch time, and schemas project into search/detail so subscribers can discover payload shapes. Payloads are capped at 64 KiB canonical JSON (Queue message headroom).
  • Subscription filters now apply to package-emitted topics: every filter key must be present in the payload with a canonically-equal JSON value, otherwise the subscriber is skipped. Platform topics keep their existing dispatcher-defined behavior.
  • Cycle protection across the queue boundary. The message carries the nested invocation depth, so emit chains (A emits → B's handler emits → …) share the same max-8-hop budget as packages.invoke chains and cannot loop forever.
  • Provisioning. tools/ci/production-resources.ts ensures the new queue pair on deploy, exactly like the existing dispatch queues; production-queue-resources.ts enforces the wrangler config shape.

Deliberately not included

A publish-time topic→subscriber D1 index was considered and deferred: manifest loads are commit-keyed and cached per isolate, every existing platform dispatcher uses the same delivery-time scan, and queued delivery already moves that scan off the emitter's request path. Adding a D1 migration right after the migration squash was not worth the marginal win.

Testing

  • New unit tests: JSON-schema-subset validator, queue message parsing (including userId isolation and trimming), consumer ack/retry semantics, queue routing, manifest payloadSchema validation and projection, dispatch enqueue contract (declared-topic gate, schema gate, size cap, depth cap), delivery fan-out with replay, filters gating, inline fallback status, and retryable-infrastructure classification.
  • npm run validate run locally (format, lint, typecheck, migrations/guardrail checks, MCP tests, e2e, 1837 unit tests).
  • CodeRabbit review feedback fully addressed (inline status honesty, additionalProperties semantics, consumer concurrency cap, fixture staleness, parser coverage).
System recap — adds a new primitive (high risk)

Mode: recap · Base: main @ bde1cc1e · Head: 7a9d1898

Classification: adds — introduces the package-events-dispatch-queue primitive (Cloudflare Queue + consumer for package-emitted events) and extends the saved-packages manifest contract with kody.emits[].payloadSchema.

Primitives touched

Primitive Group Impact
package-events-dispatch-queue storage adds — new queue + DLQ, producer in events.dispatch, consumer fan-out in subscription-dispatch.ts
saved-packages assistant extends — kody.emits[].payloadSchema (JSON Schema subset), filters applied for package-emitted topics
platform-feedback-dispatch-queue storage composes — queue-handler routing gains one case; provisioning tool extended alongside
email-delivery-queue storage composes — shared provisioning tool file only, no behavior change
webhooks assistant composes — shared package-registry root only, no webhook behavior change

System map

A package export calls events.dispatch, which enqueues on the new package-events queue; the consumer fans out to same-user subscription handlers with exactly-once idempotency.

Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).

flowchart LR
	packageRuntime["package-runtime<br/>Package runtime"]:::untouched
	packageEventsQueue["package-events-dispatch-queue<br/>Package events dispatch queue"]:::added
	savedPackages["saved-packages<br/>Saved packages"]:::extended
	runRecords["run-records<br/>Run records"]:::untouched
	packageRuntime -->|"events.dispatch → validate payloadSchema, enqueue message"| packageEventsQueue
	packageEventsQueue -->|"consumer: resolve kody.subscriptions + filters at delivery"| savedPackages
	packageEventsQueue -->|"invoke subscription handlers (exactly-once ledger)"| runRecords
	classDef touched fill:#1a7f37,color:#fff
	classDef extended fill:#9a6700,color:#fff
	classDef added fill:#cf222e,color:#fff
	classDef untouched fill:#57606a,color:#fff
Loading

Before / after

before: events.dispatch → sync fan-out in-request → { subscribers[], delivered, failed }
after:  events.dispatch → validate (schema, 64KiB cap, depth) → Queue (DLQ, retries, concurrency 16)
        → consumer fan-out (filters, exactly-once) → { status: "enqueued" | "delivered_inline" }

Invariants

  • per-user-isolation: delivery remains strictly same-user; the queue message carries the emitting userId and subscriber resolution is scoped to it.
  • no-per-event-shared-writes: no new per-event D1 writes; durability comes from the Queue, and per-delivery history stays in the per-user RunLog DO ledger.
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features
    • Added durable delivery for package-emitted events, including retries and dead-letter handling.
    • Added payload schema validation, size limits, subscription filters, deduplication, and local fallback delivery.
    • Event dispatch now reports when delivery has been queued.
  • Documentation
    • Documented event topics, payload schemas, subscriptions, delivery behavior, retries, and setup.
  • Bug Fixes
    • Improved handling and classification of retryable infrastructure failures.
  • Tests
    • Expanded coverage for validation, filtering, queue delivery, retries, and failure scenarios.

…scription filters

Package-emitted events (kody.emits / events.dispatch) now enqueue on a new
kody-package-events-dispatch Queue (with DLQ) instead of synchronously
fanning out inside the emitting request. The consumer resolves same-user
subscribers at delivery time, applies subscription filters (exact-match on
top-level payload values), invokes handlers with the existing exactly-once
idempotency keys, retries pre-execution infrastructure failures, and acks
terminal handler failures. Environments without the queue binding (local
dev, preview) deliver inline through the same consumer code path.

kody.emits entries gain an optional payloadSchema (documented JSON Schema
subset, validated at publish and dispatch time), payloads are capped at
64 KiB, and event chains carry the nested invocation depth across the
queue boundary so emit cycles terminate. Production CI provisions the new
queue pair like the existing dispatch queues.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Package-emitted events now support validated JSON Schema payloads, filters, durable queue delivery, idempotent subscriber handling, retries, dead-letter queues, and inline fallback delivery. Worker routing and production resource provisioning support the new package-events queue.

Changes

Package event delivery

Layer / File(s) Summary
Payload contracts and event metadata
packages/shared/src/json-schema-subset.ts, packages/shared/src/json-schema-subset.node.test.ts, packages/worker/src/package-registry/*, packages/worker/src/package-events/dispatch-queue-*
Adds recursive JSON Schema subset validation, emitted-event payload schemas, payload projections, and validated queue message parsing and enqueue helpers.
Dispatch validation and subscriber delivery
packages/worker/src/package-invocations/subscription-dispatch.ts, packages/worker/src/package-invocations/service.ts, packages/worker/src/package-invocations/infrastructure-codes.ts, packages/worker/src/package-invocations/admin-package-subscriptions.ts, packages/worker/src/package-invocations/service.node.test.ts
Validates topics, payloads, filters, payload size, and invocation depth. Dispatch returns an enqueued status, delivers through the queue when available, and uses inline fallback otherwise. Subscriber outcomes and retryable infrastructure failures are handled explicitly.
Queue consumption and worker routing
packages/worker/src/package-events/dispatch-queue.ts, packages/worker/src/queue-handler.ts, packages/worker/src/queue-handler.node.test.ts, packages/worker/wrangler.jsonc, packages/worker/worker-configuration.d.ts, docs/contributing/setup-manifest.md, docs/guides/package-subscriptions.md
Processes package-event batches, acknowledges invalid or terminal messages, retries unexpected failures, routes the queue in the worker, and configures production retries and dead-letter handling.
Production queue resources
tools/ci/production-queue-resources.ts, tools/ci/production-queue-resources.node.test.ts, tools/ci/production-resources.ts, docs/contributing/architecture/primitives.yaml
Validates, provisions, reports, and exports the package-events queue and dead-letter queue resources.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PackageRuntime
  participant SubscriptionDispatch
  participant PackageEventsQueue
  participant QueueHandler
  participant SubscriberInvocation
  PackageRuntime->>SubscriptionDispatch: events.dispatch(topic, payload, idempotencyKey)
  SubscriptionDispatch->>PackageEventsQueue: enqueue validated event message
  PackageEventsQueue->>QueueHandler: deliver queue batch
  QueueHandler->>SubscriberInvocation: deliverPackageEvent(message)
  SubscriberInvocation-->>QueueHandler: delivery result or retryable error
Loading

Possibly related PRs

  • kentcdodds/kody#478: Introduced the foundational package event dispatch runtime extended by this PR.
  • kentcdodds/kody#1053: Added related idempotency and subscription dispatch mechanisms used by queued event delivery.
  • kentcdodds/kody#1209: Modified related package subscription delivery and queue resource paths.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main changes: queue-backed package-event delivery, payload schemas, and subscription filters.
Description check ✅ Passed The description explains intent, summarizes the changes, documents testing, and includes system impact details despite using a non-template heading for the summary.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/package-events-queued-dispatch-1f86

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kody-bot
kody-bot marked this pull request as ready for review August 4, 2026 23:48
@github-actions

github-actions Bot commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-1229.kody-a99.workers.dev

Worker: kody-pr-1229
D1: kody-pr-1229-db
KV: kody-pr-1229-oauth-kv

Mocks:

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/worker/src/package-invocations/subscription-dispatch.ts (1)

376-408: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

The result reports status: 'enqueued' after inline delivery.

The inline branch runs when no queue binding exists or when queue.send throws. The return value still reports 'enqueued'. Callers and package authors then cannot tell a durable enqueue from a best-effort inline fan-out, and an enqueue failure is invisible to them. Report the actual outcome instead.

♻️ Proposed change
 			if (!enqueued) {
@@
 				if (input.waitUntil) {
 					input.waitUntil(inlineDelivery)
 				} else {
 					await inlineDelivery
 				}
 			}
 			return {
 				topic: request.topic,
 				source: {
 					type: 'package',
 					packageId: packageContext.packageId,
 					kodyId: packageContext.kodyId,
 				},
 				idempotencyKey: request.idempotencyKey,
-				status: 'enqueued',
+				status: enqueued ? 'enqueued' : 'delivered_inline',
 			}

Update the PackageEventTools['dispatch'] return type to include the new status value.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/package-invocations/subscription-dispatch.ts` around
lines 376 - 408, Update the dispatch flow around
deliverPackageEventWithToolFactories so inline delivery returns the new
non-enqueued status instead of 'enqueued', while preserving 'enqueued' for
successful queue sends. Extend PackageEventTools['dispatch'] and any related
result types to include the new status value, and ensure queue-send failures
report the inline outcome rather than masking the failure.
🧹 Nitpick comments (6)
packages/shared/src/json-schema-subset.ts (1)

277-283: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

additionalProperties: false is ignored when properties is absent.

The check requires properties to be present. A schema like { type: 'object', additionalProperties: false } therefore accepts any keys. Standard JSON Schema rejects every property in that case. Treat a missing properties as an empty property set.

♻️ Proposed change
-		const properties = isPlainObject(schema['properties'])
-			? schema['properties']
-			: null
-		if (properties) {
+		const properties = isPlainObject(schema['properties'])
+			? schema['properties']
+			: {}
+		{
 			for (const [key, propertySchema] of Object.entries(properties)) {
 				if (!(key in value) || !isPlainObject(propertySchema)) continue
 				errors.push(
 					...listJsonSchemaSubsetValueErrors(
 						propertySchema,
 						value[key],
 						`${path}.${key}`,
 					),
 				)
 			}
 		}
-		if (schema['additionalProperties'] === false && properties) {
+		if (schema['additionalProperties'] === false) {
 			for (const key of Object.keys(value)) {
 				if (!(key in properties)) {
 					errors.push(`${path} has unexpected property "${key}".`)
 				}
 			}
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/json-schema-subset.ts` around lines 277 - 283, Update the
additionalProperties validation in the object-schema checking logic so
additionalProperties: false treats a missing properties definition as an empty
allowed-property set. Ensure every key in the value is reported as unexpected
when properties is absent, while preserving the existing behavior when
properties is provided.
packages/worker/src/package-events/dispatch-queue-producer.ts (1)

69-74: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Decide whether enqueuePackageEventDispatch should be the producer API.

enqueuePackageEventDispatch is only exported from dispatch-queue-producer.ts; the dispatch path constructs a PackageEventsDispatchQueueMessage and calls PACKAGE_EVENTS_DISPATCH_QUEUE.send(message) directly. Call this helper from the dispatch path or remove it if the direct send path is intentional.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/package-events/dispatch-queue-producer.ts` around lines
69 - 74, Resolve the unused producer API around enqueuePackageEventDispatch:
either update the dispatch path to call this helper when sending the
PackageEventsDispatchQueueMessage, or remove the helper and its export if direct
PACKAGE_EVENTS_DISPATCH_QUEUE.send usage is intentional. Keep a single
consistent producer path.
packages/worker/src/queue-handler.node.test.ts (1)

65-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use the exported queue-name constant for consistency.

Line 66 uses scheduledDispatchQueueName, but Line 65 hardcodes 'kody-package-events-dispatch'. Import packageEventsDispatchQueueName from #worker/package-events/dispatch-queue-names.ts to match the surrounding cases.

♻️ Proposed change
-	const packageEventsBatch = createBatch('kody-package-events-dispatch')
+	const packageEventsBatch = createBatch(packageEventsDispatchQueueName)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/queue-handler.node.test.ts` at line 65, Update the
packageEventsBatch setup to use the exported packageEventsDispatchQueueName
constant instead of the hardcoded queue-name string, importing it from
`#worker/package-events/dispatch-queue-names.ts` and preserving the existing
createBatch flow.
packages/worker/src/package-invocations/service.node.test.ts (1)

1327-1357: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The manifest mutation leaves the sourceFiles fixture stale.

seedRuntimeDispatchPackages serializes each manifest into sourceFiles at the time it builds the map ('package.json': JSON.stringify(manifests.get('source-gateway')), Line 824). Lines 1338-1351 mutate gatewayManifest.kody.emits after that snapshot exists. loadPackageManifestBySourceId reads the live object and sees payloadSchema, but loadPackageSourceBySourceId returns the stale package.json text without it.

The test passes today only because dispatch validation reads the manifest through loadPackageManifestBySourceId. If dispatch later resolves the manifest from source files, this test stops validating payloadSchema and still passes.

Pass the emitted-event declaration into the seeding helper, or re-serialize sourceFiles after mutating the manifest, so both loaders agree.

♻️ Proposed fix: re-serialize the source file after mutation
 test('package runtime dispatch validates payloads against the declared payloadSchema', async () => {
 	const db = createDatabase()
-	const { manifests } = seedRuntimeDispatchPackages()
+	const { manifests, sourceFiles } = seedRuntimeDispatchPackages()
 	const gatewayManifest = manifests.get('source-gateway') as {
 		kody: {
 			emits?: Record<
 				string,
 				{ description: string; payloadSchema?: Record<string, unknown> }
 			>
 		}
 	}
 	gatewayManifest.kody.emits = {
 		'`@kentcdodds/discord.message.created`': {
 			description: 'A Discord message was created.',
 			payloadSchema: {
 				type: 'object',
 				properties: {
 					messageId: { type: 'string', minLength: 1 },
 					channelId: { type: 'string' },
 				},
 				required: ['messageId'],
 				additionalProperties: false,
 			},
 		},
 	}
+	const gatewayFiles = sourceFiles.get('source-gateway')
+	if (gatewayFiles) {
+		gatewayFiles['package.json'] = JSON.stringify(gatewayManifest)
+	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/package-invocations/service.node.test.ts` around lines
1327 - 1357, After mutating gatewayManifest.kody.emits in the payload-schema
dispatch test, re-serialize the updated source-gateway manifest into its
corresponding sourceFiles package.json entry before creating the runtime event
tools. Ensure loadPackageManifestBySourceId and loadPackageSourceBySourceId both
observe the same emitted-event declaration.
packages/worker/wrangler.jsonc (1)

320-322: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider a max_concurrency cap on this consumer.

Each package event can invoke several subscriber handlers, and every handler load runs a dynamic Worker isolate. Without max_concurrency, Cloudflare scales this consumer freely, so a burst of emitted events can multiply into a large number of concurrent isolate loads and subrequests.

The kody-scheduled-dispatch consumer at Line 315 already caps concurrency at 16 for comparable per-message work. The sibling dispatch queues omit the cap, so this is a deliberate choice to confirm rather than a defect.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/wrangler.jsonc` around lines 320 - 322, Confirm the intended
concurrency policy for the consumer configuration containing max_batch_size,
max_batch_timeout, and max_retries; if it should match kody-scheduled-dispatch,
add a max_concurrency setting capped at 16, otherwise leave the current
configuration unchanged.
packages/worker/src/package-events/dispatch-queue.node.test.ts (1)

123-157: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a rejection case for a blank userId.

The parser rejects a non-string or blank userId. userId selects which user's subscribed packages receive the event, so it is the field that enforces per-user isolation across the queue boundary. The current cases cover topic, idempotencyKey, payload, source, and invokeDepth, but not userId.

Also consider asserting that the parser trims values, because the equality check at Line 124 uses an already-trimmed fixture.

As per coding guidelines: "Every signed-in user must have a fully isolated personal assistant".

💚 Proposed additional cases
 	expect(
 		parsePackageEventsDispatchQueueMessage(createMessageBody({ topic: ' ' })),
 	).toBeNull()
+	expect(
+		parsePackageEventsDispatchQueueMessage(createMessageBody({ userId: '  ' })),
+	).toBeNull()
+	expect(
+		parsePackageEventsDispatchQueueMessage(createMessageBody({ userId: 42 })),
+	).toBeNull()
+	expect(
+		parsePackageEventsDispatchQueueMessage(
+			createMessageBody({ userId: ' user-123 ', topic: ' topic.a ' }),
+		),
+	).toMatchObject({ userId: 'user-123', topic: 'topic.a' })
 	expect(
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/package-events/dispatch-queue.node.test.ts` around lines
123 - 157, Add a malformed-body assertion in the test "package events queue
message parsing rejects malformed bodies" that passes a blank userId to
parsePackageEventsDispatchQueueMessage and expects null; also add coverage for
surrounding whitespace to verify the parser trims accepted userId values, while
preserving the existing trimmed-fixture equality assertion.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/worker/src/package-invocations/subscription-dispatch.ts`:
- Around line 376-408: Update the dispatch flow around
deliverPackageEventWithToolFactories so inline delivery returns the new
non-enqueued status instead of 'enqueued', while preserving 'enqueued' for
successful queue sends. Extend PackageEventTools['dispatch'] and any related
result types to include the new status value, and ensure queue-send failures
report the inline outcome rather than masking the failure.

---

Nitpick comments:
In `@packages/shared/src/json-schema-subset.ts`:
- Around line 277-283: Update the additionalProperties validation in the
object-schema checking logic so additionalProperties: false treats a missing
properties definition as an empty allowed-property set. Ensure every key in the
value is reported as unexpected when properties is absent, while preserving the
existing behavior when properties is provided.

In `@packages/worker/src/package-events/dispatch-queue-producer.ts`:
- Around line 69-74: Resolve the unused producer API around
enqueuePackageEventDispatch: either update the dispatch path to call this helper
when sending the PackageEventsDispatchQueueMessage, or remove the helper and its
export if direct PACKAGE_EVENTS_DISPATCH_QUEUE.send usage is intentional. Keep a
single consistent producer path.

In `@packages/worker/src/package-events/dispatch-queue.node.test.ts`:
- Around line 123-157: Add a malformed-body assertion in the test "package
events queue message parsing rejects malformed bodies" that passes a blank
userId to parsePackageEventsDispatchQueueMessage and expects null; also add
coverage for surrounding whitespace to verify the parser trims accepted userId
values, while preserving the existing trimmed-fixture equality assertion.

In `@packages/worker/src/package-invocations/service.node.test.ts`:
- Around line 1327-1357: After mutating gatewayManifest.kody.emits in the
payload-schema dispatch test, re-serialize the updated source-gateway manifest
into its corresponding sourceFiles package.json entry before creating the
runtime event tools. Ensure loadPackageManifestBySourceId and
loadPackageSourceBySourceId both observe the same emitted-event declaration.

In `@packages/worker/src/queue-handler.node.test.ts`:
- Line 65: Update the packageEventsBatch setup to use the exported
packageEventsDispatchQueueName constant instead of the hardcoded queue-name
string, importing it from `#worker/package-events/dispatch-queue-names.ts` and
preserving the existing createBatch flow.

In `@packages/worker/wrangler.jsonc`:
- Around line 320-322: Confirm the intended concurrency policy for the consumer
configuration containing max_batch_size, max_batch_timeout, and max_retries; if
it should match kody-scheduled-dispatch, add a max_concurrency setting capped at
16, otherwise leave the current configuration unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f49479d-dd0a-46a0-91f4-09460c703bd5

📥 Commits

Reviewing files that changed from the base of the PR and between bde1cc1 and e13b67a.

📒 Files selected for processing (24)
  • docs/contributing/architecture/primitives.yaml
  • docs/contributing/setup-manifest.md
  • docs/guides/package-subscriptions.md
  • packages/shared/src/json-schema-subset.node.test.ts
  • packages/shared/src/json-schema-subset.ts
  • packages/worker/src/package-events/dispatch-queue-names.ts
  • packages/worker/src/package-events/dispatch-queue-producer.ts
  • packages/worker/src/package-events/dispatch-queue.node.test.ts
  • packages/worker/src/package-events/dispatch-queue.ts
  • packages/worker/src/package-invocations/admin-package-subscriptions.ts
  • packages/worker/src/package-invocations/infrastructure-codes.ts
  • packages/worker/src/package-invocations/service.node.test.ts
  • packages/worker/src/package-invocations/service.ts
  • packages/worker/src/package-invocations/subscription-dispatch.ts
  • packages/worker/src/package-registry/manifest.node.test.ts
  • packages/worker/src/package-registry/manifest.ts
  • packages/worker/src/package-registry/types.ts
  • packages/worker/src/queue-handler.node.test.ts
  • packages/worker/src/queue-handler.ts
  • packages/worker/worker-configuration.d.ts
  • packages/worker/wrangler.jsonc
  • tools/ci/production-queue-resources.node.test.ts
  • tools/ci/production-queue-resources.ts
  • tools/ci/production-resources.ts

Report delivered_inline when dispatch falls back past the queue, apply
additionalProperties: false with an absent properties set, drop the unused
enqueue helper, cap the queue consumer at 16 concurrent invocations, keep
mutated manifest fixtures in sync with their serialized source snapshots,
and cover userId parsing/trimming in the queue message parser.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kody-bot
kody-bot merged commit 2b8bf8e into main Aug 5, 2026
10 checks passed
@kody-bot
kody-bot deleted the cursor/package-events-queued-dispatch-1f86 branch August 5, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants