docs(plan): DR-3 — Temporal deferred to v1.0 multi-tenant ADR; v0.2 PR #2/#3 sequenced
Adds DR-3 to the v4 r1 plan and rewires §1 + §23 to reflect that the v0.x
release line ships zero Temporal code.
Rationale (DR-3 detail in §22):
- v3 and early v4 r1 drafts had Temporal as the canonical durable-workflow
layer (M5-Py). For 1-user 1-machine CLI/REPL/web-GUI workloads, the same
durability guarantee is reachable with (1) LangGraph AsyncPostgresSaver
(already in deps after v0.2 PR #1) + (2) RunPhaseRow / LlmCallRow state
machine per-commit (already in models) + (3) sweep_orphan_runs at startup
(already in recovery.py).
- Temporal server + worker + deterministic-workflow rules are weight without
proportional payoff at this scale. The decision becomes meaningful only
when v1.0 introduces multi-tenant / multi-machine fanout.
- temporalio NOT added to my-deepagent/pyproject.toml. No apps/worker/.
Patches:
- §1.7 (new): "Workflow Orchestration: NOT USED in v0.x. Deferred to v1.0
multi-tenant ADR (DR-3)." Explains the LangGraph + DB + sweep replacement
path and points at §23 for the v0.2 sequencing.
- §22 DR-3 (new): full decision record with rationale, scope, and the
supersede statement against earlier "M5-Py: Temporal worker NEXT" wording.
- §23 v4 kickoff matrix:
- v0.2 PR #1 row → DONE (e21a524).
- v0.2 PR #2a (new): LangGraph AsyncPostgresSaver engine wiring.
- v0.2 PR #2b (new): `mydeepagent runs resume <id>` real implementation.
- v0.2 PR #3 (new): FastAPI + SSE + minimal Web GUI.
- M5-Py → DEFERRED to v1.0+ per DR-3.
- M8-Py → absorbed into v0.2 PR #3 (no separate apps/api dir; FastAPI
lives inside my-deepagent/src/my_deepagent/api/).
Open question (recorded in DR-3): v1.0 ADR will compare Temporal vs Hatchet
vs in-house Postgres-based workflow runner.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
23
docs/plan.md
23
docs/plan.md
@@ -145,7 +145,18 @@ class BackendConfig(BaseModel, frozen=True):
|
|||||||
- Body validation via the same pydantic v2 models used elsewhere.
|
- Body validation via the same pydantic v2 models used elsewhere.
|
||||||
- WebSocket remains deferred unless SSE fails under transcript volume.
|
- WebSocket remains deferred unless SSE fails under transcript volume.
|
||||||
|
|
||||||
## 2. Directory Layout
|
### 1.7 Workflow Orchestration
|
||||||
|
|
||||||
|
- **NOT USED in v0.x. Deferred to v1.0 multi-tenant ADR (DR-3).**
|
||||||
|
- v3 / earlier v4 r1 drafts named `temporalio` here. After v0.1.0 shipped
|
||||||
|
and the OpenRouter E2E path was proven, single-user single-machine durable
|
||||||
|
resume turned out to be reachable with **LangGraph `AsyncPostgresSaver`
|
||||||
|
checkpoint + DB phase-state machine + `sweep_orphan_runs`** — all of
|
||||||
|
which already exist in the v0.2 codebase. The Temporal server + worker +
|
||||||
|
determinism rules are weight that v1.0's multi-tenant decision can
|
||||||
|
re-evaluate; in the meantime, `temporalio` is **not** in
|
||||||
|
`my-deepagent/pyproject.toml`, no worker process, no `apps/worker/`.
|
||||||
|
- See DR-3 below + §23 v0.2 row matrix for the migration replacement.
|
||||||
|
|
||||||
v4 r1 collapses the v3 multi-package monorepo into a single `my-deepagent/`
|
v4 r1 collapses the v3 multi-package monorepo into a single `my-deepagent/`
|
||||||
project. The TS `apps/`, `packages/`, `tests/`, `scripts/` trees were deleted
|
project. The TS `apps/`, `packages/`, `tests/`, `scripts/` trees were deleted
|
||||||
@@ -1924,6 +1935,7 @@ M5+:
|
|||||||
|----|----------|-----------|--------|
|
|----|----------|-----------|--------|
|
||||||
| DR-1 | **v3 → v4 major bump: delete TS monorepo, rewrite in Python on LangChain `deepagents`.** | (1) Claude/Anthropic direct API cost is prohibitive for a single-user toolchain. (2) OpenRouter cost-tuned models (DeepSeek, etc.) require a multi-turn, tool-using agent harness; `deepagents` is Python-only with no 1:1 TS port. (3) Switching languages is shorter than reimplementing the harness. | Step 0 (commit `0e61b2d`) deleted `apps/`, `packages/`, `tests/`, `scripts/`, pnpm/tsconfig metadata. The Python rewrite lives at `my-deepagent/` and reached Step 15 (real OpenRouter E2E PASS, ~$0.05/run) before the v3 codebase was removed. CC-39's separate `OpenRouterAdapter` is replaced by `my_deepagent.session.build_agent` (deepagents 0.6.1 with LocalShellBackend + SafetyShellMiddleware). v3 CC counters frozen; v4 begins its own series. Recovery: `git checkout pre-python-rewrite -- <path>`. |
|
| DR-1 | **v3 → v4 major bump: delete TS monorepo, rewrite in Python on LangChain `deepagents`.** | (1) Claude/Anthropic direct API cost is prohibitive for a single-user toolchain. (2) OpenRouter cost-tuned models (DeepSeek, etc.) require a multi-turn, tool-using agent harness; `deepagents` is Python-only with no 1:1 TS port. (3) Switching languages is shorter than reimplementing the harness. | Step 0 (commit `0e61b2d`) deleted `apps/`, `packages/`, `tests/`, `scripts/`, pnpm/tsconfig metadata. The Python rewrite lives at `my-deepagent/` and reached Step 15 (real OpenRouter E2E PASS, ~$0.05/run) before the v3 codebase was removed. CC-39's separate `OpenRouterAdapter` is replaced by `my_deepagent.session.build_agent` (deepagents 0.6.1 with LocalShellBackend + SafetyShellMiddleware). v3 CC counters frozen; v4 begins its own series. Recovery: `git checkout pre-python-rewrite -- <path>`. |
|
||||||
| DR-2 | **SQLite for v0.1.0; Postgres migration scheduled as v0.2 PR #1, ahead of M8-Py FastAPI.** | The v4 r1 first draft suggested Postgres should re-enter "with Temporal." That was wrong: Temporal (M5-Py) does not write to the `my-deepagent` ORM tables — it has its own backing store. The real trigger for Postgres is *a second writer on `runs` / `run_phases` / `llm_calls`*, which first appears with FastAPI (M8-Py) and the eventual web GUI. Until then, SQLite WAL handles single-process concurrent reads fine and saves new users a Docker prerequisite at install time. | Migration sequencing: v0.2 PR #1 = "stop writers → `alembic downgrade base` against SQLite → regenerate baseline against Postgres → adjust JSON column types / partial-unique-index syntax / UPSERT for the Postgres dialect → add `pg_isready` doctor check." M5-Py (Temporal) can be implemented on either SQLite or Postgres my-deepagent DB; the order (v0.2-PR-1 → M5-Py → M8-Py) is chosen for stack consistency, not necessity. Supersedes the "Postgres parked indefinitely" wording from earlier v4 r1 drafts. |
|
| DR-2 | **SQLite for v0.1.0; Postgres migration scheduled as v0.2 PR #1, ahead of M8-Py FastAPI.** | The v4 r1 first draft suggested Postgres should re-enter "with Temporal." That was wrong: Temporal (M5-Py) does not write to the `my-deepagent` ORM tables — it has its own backing store. The real trigger for Postgres is *a second writer on `runs` / `run_phases` / `llm_calls`*, which first appears with FastAPI (M8-Py) and the eventual web GUI. Until then, SQLite WAL handles single-process concurrent reads fine and saves new users a Docker prerequisite at install time. | Migration sequencing: v0.2 PR #1 = "stop writers → `alembic downgrade base` against SQLite → regenerate baseline against Postgres → adjust JSON column types / partial-unique-index syntax / UPSERT for the Postgres dialect → add `pg_isready` doctor check." M5-Py (Temporal) can be implemented on either SQLite or Postgres my-deepagent DB; the order (v0.2-PR-1 → M5-Py → M8-Py) is chosen for stack consistency, not necessity. Supersedes the "Postgres parked indefinitely" wording from earlier v4 r1 drafts. |
|
||||||
|
| DR-3 | **Temporal deferred to v1.0 multi-tenant ADR. v0.x ships zero Temporal code.** | v3 and early v4 r1 drafts had Temporal as the canonical durable-workflow layer (M5-Py). For 1-user 1-machine CLI/REPL/web-GUI workloads, the same durability guarantee is reachable with (1) LangGraph `AsyncPostgresSaver` (already in deps, v0.2 PR #1) + (2) `RunPhaseRow` / `LlmCallRow` state machine per-commit (already in models) + (3) `sweep_orphan_runs` at startup (already in `recovery.py`). Temporal server + worker + deterministic-workflow rules + `apps/worker/` are weight without proportional payoff at this scale. The decision to add Temporal becomes meaningful only when v1.0 introduces multi-tenant / multi-machine fanout. | M5-Py row in §23 marked **DEFERRED v1.0+**. `temporalio` is NOT added to `my-deepagent/pyproject.toml`. No `apps/worker/`. v0.2 PR #2 implements `runs resume` via the LangGraph + DB state machine path (see §23 row). Supersedes "M5-Py: Temporal worker NEXT" in earlier v4 r1 drafts. Open question for v1.0 ADR: Temporal vs Hatchet vs in-house Postgres-based workflow runner. |
|
||||||
|
|
||||||
### Future Open Questions
|
### Future Open Questions
|
||||||
|
|
||||||
@@ -1970,6 +1982,9 @@ v4 r1 order (Python, status as of v0.1.0):
|
|||||||
| Step 14 | TUI recovery (M7-Py) | DEFERRED — not in v0.1.0 |
|
| Step 14 | TUI recovery (M7-Py) | DEFERRED — not in v0.1.0 |
|
||||||
| Step 15 | End-to-end real OpenRouter integration test | DONE (`733c9be`) |
|
| Step 15 | End-to-end real OpenRouter integration test | DONE (`733c9be`) |
|
||||||
| Step 0-purge | Delete v3 TS monorepo per DR-1 | DONE (`0e61b2d`) |
|
| Step 0-purge | Delete v3 TS monorepo per DR-1 | DONE (`0e61b2d`) |
|
||||||
| v0.2 PR #1 | **Postgres migration** — Alembic baseline regen against Postgres 16; SQLite removed. Triggered by upcoming M8-Py multi-process writes, sequenced *before* M8-Py for a clean cut. Adds `pg_isready` doctor check; `mydeepagent doctor` no longer offers SQLite fast-path. | PLANNED (next) |
|
| v0.2 PR #1 | **Postgres migration** — Alembic baseline regen against Postgres 16; SQLite moved to dev-only (test). `psycopg`/`asyncpg`/`langgraph-checkpoint-postgres` in prod, `aiosqlite` in dev. Dialect-aware `insert_for` upsert helper. Live E2E PASS on Postgres. | DONE (`e21a524`) |
|
||||||
| M5-Py | Temporal worker (`apps/worker`). Temporal server uses its own backing DB (separate Postgres `temporal` namespace) and does not touch `my-deepagent`'s ORM tables, so M5-Py works on either SQLite or Postgres my-deepagent DB. Targeted post-v0.2-PR-1 for stack consistency. | PLANNED |
|
| v0.2 PR #2a | **LangGraph `AsyncPostgresSaver` engine wiring**. `WorkflowEngine.run()` opens a saver context once; `_run_phase` forwards `checkpointer=saver` to `build_agent` and passes `config={"configurable": {"thread_id": f"run:{run_id}:phase:{phase_id}"}}` to `agent.ainvoke`. Foundation for v0.2 PR #2b. | PLANNED |
|
||||||
| M8-Py | FastAPI + SSE (`apps/api`). Requires Postgres (see §1.3 trigger table). | PLANNED |
|
| v0.2 PR #2b | **`mydeepagent runs resume <id>` real implementation**. `existing_run_id` branch in `WorkflowEngine.run`, RunBindingRow + workflow_templates.definition reload, first-non-completed-phase resume via LangGraph thread replay. 5 integration scenarios. Closes v0.1.0 KNOWN LIMIT. | PLANNED |
|
||||||
|
| v0.2 PR #3 | **FastAPI + SSE + minimal Web GUI** (`mydeepagent serve`). vanilla HTML/JS/CSS, no build system. read+write run routes, SSE stream (0.5s polling, v0.3 NOTIFY upgrade ADR), Korean-only UI, `--host 127.0.0.1` enforced. Manual browser verification end-to-end. | PLANNED |
|
||||||
|
| M5-Py | Temporal worker (`apps/worker`). | **DEFERRED to v1.0+ per DR-3.** Single-user durable resume is reachable with the LangGraph + DB + sweep_orphan_runs stack now landing in v0.2 PR #2. Re-evaluate when multi-tenant / multi-machine ADR opens at v1.0. |
|
||||||
|
| M8-Py | Standalone `apps/api` package. | **Absorbed into v0.2 PR #3.** No separate apps/api directory; FastAPI lives inside `my-deepagent/src/my_deepagent/api/`. M8-Py row retained as historical marker. |
|
||||||
|
|||||||
Reference in New Issue
Block a user