Skip to content

Story 5.3: Phase 2/3 roadmap + async and framework design intent (docs only) - #20

Merged
usmanabbas7 merged 2 commits into
dev-branchfrom
feat/story-5-3-async-and-framework-roadmap
Apr 28, 2026
Merged

Story 5.3: Phase 2/3 roadmap + async and framework design intent (docs only)#20
usmanabbas7 merged 2 commits into
dev-branchfrom
feat/story-5-3-async-and-framework-roadmap

Conversation

@usmanabbas7

Copy link
Copy Markdown
Collaborator

Summary

  • Implements Story 5.3 per its own framing — "drafted to record design intent, not to ship code". Implementing the async public API (AsyncCore / AsyncContext) and the three framework helper distributions (convert-sdk-django, convert-sdk-fastapi, convert-sdk-flask) remains gated on explicit Phase 3 sign-off.
  • Adds two new docs (docs/roadmap.md, docs/async.md) and forward-references in 4 existing docs.
  • Records a per-module forward-compatibility audit confirming the MVP carries no sync-only entrenchment that would block the async surface.
  • No code changes. Sync-first MVP is unaffected.

What landed (docs only)

docs/roadmap.md — Phase 1 (MVP shipped), Phase 2 (long-running service support; auto-refresh shipped, durable storage / retry tuning / structured logging guide planned), Phase 3 (async public API + framework integrations + OpenTelemetry, all planned). Tracks shipped vs planned status against the architecture's deferral discipline and the PRD's Module Phase Table.

docs/async.md — Phase 3 design intent in detail:

  • The architecture's five frozen rules for the sync-async coexistence model (parallel API not replacement; shared evaluation core; async transport adapter via httpx.AsyncClient; DataStore stays sync with AsyncDataStore added in parallel; SDK never owns the event loop).
  • A per-module forward-compatibility audit table covering every MVP file. Verdict + notes per module. Bottom line: no MVP module needs to change to enable async.
  • Confirmation that public method names already reserve async flexibilityrun_experience / run_feature / track_conversion / refresh_now / close work as-is for both surfaces; AsyncCore.aclose() follows the asyncio convention.
  • Framework integration plan — separate distributions; core stays framework-free per NFR13; minimum helper provisions; deprecation policy.
  • Cross-SDK contract reuse — Story 3.5 parity vectors and Story 4.3 diagnostic field contract apply unchanged to async output.
  • Open questions — async transport boundary (AsyncClient adapter vs to_thread() wrapper), DataStore Protocol shape, async event-bus — flagged as Phase-3-sign-off decisions rather than pre-empted.

Forward referencesdocs/index.md gains a "Looking ahead" table; docs/migration-from-javascript.md, docs/migration-from-rest.md, and docs/extending.md each gain a brief "Future async / framework support" note. The REST migration guide also notes that today's async-Python users can call the sync SDK from async code via asyncio.to_thread() until the async surface ships.

Audit findings (summary)

Module Verdict
evaluation/*, domain/* ✅ ready (pure compute)
tracking/payloads.py, tracking/conversions.py ✅ ready
diagnostics.py, errors.py, events.py ✅ ready
adapters/storage/in_memory.py, adapters/events/in_memory_event_bus.py ✅ ready (thread-safe; usable from async via asyncio.to_thread())
tracking/queue.py ✅ ready (thread-safe queue, can be reused under async)
ports/transport.py, ports/storage.py ➕ extend (add AsyncTransport / AsyncDataStore siblings)
adapters/transport/httpx_transport.py ➕ sibling (add HttpxAsyncTransport)
config_loader/loader.py, config_loader/refresh.py ➕ sibling
core.py, context.py ➕ sibling (AsyncCore, AsyncContext)

No MVP module needs to change to enable async. The seams above are "add a sibling", never "rewrite". The architecture's preparation work paid off.

Out-of-scope (gated on Phase 3 sign-off)

Per Story 5.3's Critical Warning #1"Do not ship any of this story's code as part of the MVP release. Opening it for implementation requires explicit Phase 3 sign-off." — the following are explicitly NOT in this PR:

  • src/convert_sdk/asyncio/ package implementation
  • src/convert_sdk/adapters/transport/httpx_async_transport.py adapter
  • convert-sdk-django, convert-sdk-fastapi, convert-sdk-flask separate distributions
  • Parity-fixture replays through the async surface
  • Async-aware test harness

These are recorded in docs/async.md as planned shape; opening any of them requires explicit sign-off.

Test plan

  • CI runs against this PR; lint, type-check, pytest matrix, bounds-check, changelog-fragment, and build are green (no code changes — only docs and one CHANGELOG fragment).
  • Manual: review docs/async.md for design completeness against the architecture's "deliberately deferred" list.
  • Manual: confirm forward-reference notes are non-confusing for users on the migration paths.

Story tracking

  • Story file (ai-driven-product-dev repo): 5-3-add-planned-expansion-surfaces-for-async-and-framework-integrations.md — status flipped backlogreview with full Dev Agent Record covering the audit verdicts and the explicit out-of-scope list.
  • Sprint status: epic-5 stays in-progress; story 5-3 backlogreview.

🤖 Generated with Claude Code

…intent

Story 5.3 — per its own framing, this is a design-intent + audit story,
not an implementation story. Implementing AsyncCore/AsyncContext and
the three framework helper distributions (convert-sdk-django,
convert-sdk-fastapi, convert-sdk-flask) remains gated on explicit
Phase 3 sign-off.

What landed (docs only):

docs/roadmap.md — Phase 1 (MVP shipped), Phase 2 (long-running service
support; auto-refresh shipped today, durable storage / retry tuning /
structured logging guide planned), Phase 3 (async public API +
framework integrations + OpenTelemetry, all planned).

docs/async.md — Phase 3 design intent. Records the architecture's
five frozen rules for the sync-async coexistence model (parallel API
not replacement; shared evaluation core; async transport adapter;
DataStore stays sync with AsyncDataStore added in parallel; SDK never
owns the event loop). Includes a per-module forward-compatibility
audit table covering every MVP file. Bottom line: no MVP module needs
to change to enable async — the architecture's "MVP must not be
async-hostile" preparation work was effective. Public method names
(run_experience, run_feature, track_conversion, refresh_now, close)
already work as-is for both surfaces. Framework helpers ship as
separate distributions; core stays framework-free per NFR13. Open
questions (async transport boundary, DataStore Protocol shape, async
event-bus) are flagged as Phase-3-sign-off decisions rather than
pre-empted.

Forward references — docs/index.md gains a "Looking ahead" table;
docs/migration-from-javascript.md, docs/migration-from-rest.md, and
docs/extending.md each gain a brief "Future async / framework
support" note pointing at the new roadmap and async docs.

No code changes. Sync-first MVP is unaffected; all release gates green
(227 tests pass, project coverage 94.03%, evaluation/ 97.84%, parity
7/7).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request adds documentation for the project's roadmap and async design intent, specifically introducing docs/roadmap.md and docs/async.md. These documents outline a phased expansion plan and the architectural strategy for maintaining a sync-first MVP while preparing for parallel async support. Feedback was provided to resolve a contradiction in docs/async.md regarding the AsyncDataStore protocol definition.

Comment thread docs/async.md Outdated
Comment on lines +178 to +180
- **DataStore Protocol shape**: a separate `AsyncDataStore` Protocol
vs. a dual-protocol convention (one Protocol, two suites of
methods — e.g., `load_context_state` / `aload_context_state`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

This open question appears to contradict one of the 'Five frozen rules for the async surface' (rule #4 on line 65), which states that AsyncDataStore will be a new sibling Protocol. Questioning the fundamental shape of the protocol here could be confusing for readers.

To improve consistency, I suggest rephrasing this point to focus on the implementation details of the AsyncDataStore protocol, rather than questioning its existence as a separate protocol. This would better align with the 'frozen' nature of the rules established earlier in the document.

Suggested change
- **DataStore Protocol shape**: a separate `AsyncDataStore` Protocol
vs. a dual-protocol convention (one Protocol, two suites of
methods — e.g., `load_context_state` / `aload_context_state`).
- **DataStore Protocol details**: What should be the exact method signatures within the `AsyncDataStore` Protocol? Should they mirror the sync `DataStore` methods with an `a` prefix (e.g., `aload_context_state`), or is there a better convention to follow?

The adversarial review of PR #20 surfaced four documentation issues:

1. The forward-compatibility audit table marked the in-memory event
   bus, in-memory data store, and tracking queue as "✅ ready" with
   notes that walked the verdict back. From an async caller these
   modules block the event loop unless wrapped — they are "➕ wrap",
   not "drop-in async-ready." Verdict legend now distinguishes
   ✅ ready (reusable verbatim from a coroutine), ➕ sibling (add a
   parallel async class), and ➕ wrap (reach it through an async
   adapter or to_thread()).

2. The Open Questions section listed "Async transport boundary" as
   undecided while the rest of the doc described HttpxAsyncTransport
   as a concrete plan. The section is rewritten to identify which
   leanings are firm and which axes are still open at Phase 3 sign-off,
   plus a fourth open question (executor sizing for the to_thread()
   fallback) that the original list omitted.

3. The "Looking ahead" panel in docs/index.md placed AsyncCore /
   AsyncContext examples one click away from new users. The header
   now explicitly reads "planned, not yet shipped" with a paragraph
   warning readers that the symbols are not importable today.

4. The migration-from-REST guide recommended asyncio.to_thread() as
   the bridge for async hosts but did not mention that to_thread runs
   on the bounded default executor (min(32, cpu_count + 4) workers
   on CPython). A FastAPI service receiving hundreds of concurrent
   requests can serialise SDK calls behind that cap. A warning
   admonition and an executor-resize recipe are added.

The aclose() naming choice is now justified explicitly (the asyncio
convention is to spell shutdown methods with the a* prefix; reusing
the sync name would mislead readers about what is awaitable).

No code changes; sync-first MVP is unaffected. 204 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@usmanabbas7
usmanabbas7 merged commit 5e5c1f1 into dev-branch Apr 28, 2026
20 checks passed
@abbaseya
abbaseya deleted the feat/story-5-3-async-and-framework-roadmap branch June 18, 2026 16:37
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.

1 participant