From f19707042d611308ddbfcfb812f508f25b76a35d Mon Sep 17 00:00:00 2001
From: Pratyush Sharma <56130065+pratyush618@users.noreply.github.com>
Date: Sun, 12 Jul 2026 19:20:58 +0530
Subject: [PATCH 1/4] docs: surface pub/sub, locks, mesh, predicates in Python
capabilities
---
.../content/docs/python/getting-started/capabilities.mdx | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/docs/content/docs/python/getting-started/capabilities.mdx b/docs/content/docs/python/getting-started/capabilities.mdx
index 21ba0fd0..5c9c9d65 100644
--- a/docs/content/docs/python/getting-started/capabilities.mdx
+++ b/docs/content/docs/python/getting-started/capabilities.mdx
@@ -11,6 +11,7 @@ import {
CalendarClock,
Activity,
Plug,
+ Network,
} from "lucide-react";
taskito ships a broad feature set out of the box. If you're evaluating it — or
@@ -66,7 +67,13 @@ These are the capabilities most often assumed absent. They aren't.
icon={}
title="Extensibility"
href="/python/guides/extensibility"
- description="Pluggable serializers, per-task middleware, a fully async API, and Postgres or Redis backends."
+ description="Pluggable serializers, per-task middleware, enqueue predicates, argument interception, a fully async API, and Postgres or Redis backends."
+ />
+ }
+ title="Distribution"
+ href="/python/guides/core/pubsub"
+ description="Topic pub/sub fan-out to independent subscribers, distributed locks, a decentralized work-stealing mesh, and streaming partial results."
/>
From ed08962d1d683192b735eabb9ddba6ba44711772 Mon Sep 17 00:00:00 2001
From: Pratyush Sharma <56130065+pratyush618@users.noreply.github.com>
Date: Sun, 12 Jul 2026 19:20:58 +0530
Subject: [PATCH 2/4] docs: add circuit breakers to Java capabilities
---
docs/content/docs/java/getting-started/capabilities.mdx | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/content/docs/java/getting-started/capabilities.mdx b/docs/content/docs/java/getting-started/capabilities.mdx
index 02201f7a..cd844e74 100644
--- a/docs/content/docs/java/getting-started/capabilities.mdx
+++ b/docs/content/docs/java/getting-started/capabilities.mdx
@@ -26,6 +26,7 @@ core — pick a backend, describe tasks, run workers.
|---|---|
| Retries with backoff curves (`RetryPolicy`), dead-letter queue | [Retries](/java/guides/reliability/retries) · [Dead-letter](/java/guides/reliability/dead-letter) |
| Per-attempt timeouts | [Timeouts](/java/guides/reliability/timeouts) |
+| Circuit breakers (`CircuitBreakerConfig`) | [Circuit breakers](/java/guides/reliability/circuit-breakers) |
| Idempotent enqueue (`uniqueKey`) | [Idempotency](/java/guides/reliability/idempotency) |
| Distributed locks | [Locks](/java/guides/reliability/locks) |
| At-least-once delivery | [Guarantees](/java/guides/reliability/guarantees) |
From 819bfbd32abb72b10db0f0ed378a3e59311d81a3 Mon Sep 17 00:00:00 2001
From: Pratyush Sharma <56130065+pratyush618@users.noreply.github.com>
Date: Sun, 12 Jul 2026 19:30:08 +0530
Subject: [PATCH 3/4] docs: add Java structured-notes guide
---
.../docs/java/guides/observability/meta.json | 2 +-
.../docs/java/guides/observability/notes.mdx | 109 ++++++++++++++++++
2 files changed, 110 insertions(+), 1 deletion(-)
create mode 100644 docs/content/docs/java/guides/observability/notes.mdx
diff --git a/docs/content/docs/java/guides/observability/meta.json b/docs/content/docs/java/guides/observability/meta.json
index c6d9beae..ac58e2a4 100644
--- a/docs/content/docs/java/guides/observability/meta.json
+++ b/docs/content/docs/java/guides/observability/meta.json
@@ -1 +1 @@
-{ "title": "Observability", "pages": ["monitoring", "logging"] }
+{ "title": "Observability", "pages": ["monitoring", "logging", "notes"] }
diff --git a/docs/content/docs/java/guides/observability/notes.mdx b/docs/content/docs/java/guides/observability/notes.mdx
new file mode 100644
index 00000000..c6b266e1
--- /dev/null
+++ b/docs/content/docs/java/guides/observability/notes.mdx
@@ -0,0 +1,109 @@
+---
+title: Structured Notes
+description: "Attach a bounded map of annotations to a job at enqueue time — capped at 15 fields, dashboard-rendered."
+---
+
+`notes` is a structured annotation field on every job — a small map (at most
+**15** top-level keys) you attach when enqueuing and read back from the job.
+Unlike `metadata`, which is a free-form JSON string blob, `notes` is validated
+when you build the enqueue options and rendered by the dashboard as a key/value
+table.
+
+## When to use `notes` vs `metadata`
+
+| | `notes` | `metadata` |
+|---|---|---|
+| Type at enqueue | `Map` | `String` (pre-encoded JSON) |
+| Top-level fields | ≤ 15 | unbounded |
+| Validation | At build time | None |
+| Dashboard render | Key/value table | Raw JSON dump |
+| Survives DLQ retry | Yes | Yes |
+| Best for | User-visible annotations | Operational/debug context |
+
+Use **`notes`** for short, user-readable annotations a human or the dashboard
+would want to scan: customer IDs, business-priority reasons, short comments. Use
+**`metadata`** when you need to attach an opaque JSON blob without size
+constraints (trace IDs, request envelopes, etc.).
+
+## Writing notes
+
+Pass a `Map` to `notes(...)` on the enqueue-options builder:
+
+```java
+import org.byteveda.taskito.task.EnqueueOptions;
+import java.util.Map;
+
+String id = taskito.enqueue(processOrder, order, EnqueueOptions.builder()
+ .notes(Map.of(
+ "customer_id", "cus_abc",
+ "tier", "gold",
+ "priority_reason", "VIP onboarding"))
+ .build());
+```
+
+Passing `null` clears any previously set notes. The map is validated and
+canonically encoded to JSON at `build()` time, so an invalid map fails fast
+before the job is enqueued.
+
+## Reading notes back
+
+`Job` carries the raw JSON string on `notes`, plus a parsed view via
+`notesMap()`:
+
+```java
+import org.byteveda.taskito.model.Job;
+import java.util.Map;
+import java.util.Optional;
+
+Optional