Skip to content

Commit 5c311f7

Browse files
sudoshiruvnet
andcommitted
feat(orchestration): relabel Airflow/Dagster/Temporal as developer-extension examples + ADR-0021
Per the optional-scope decisions (ADR-0021): orchestration backends are developer extension examples (Prefect is the shipped default), cloud connectors are enterprise-only, DOCX/XLSX export will be implemented. - Relabeled the 3 backend stubs (docstrings + NotImplementedError messages) and test_orchestration_stubs.py match from 'Phase 0 stub' to 'developer-extension example'. mypy + ruff clean, 3 tests pass. - New ADR-0021 records all three dispositions (Phase 9 decision record). - Completion-plan check-offs: Phase 9 orchestration + connector decisions, Phase 4 connector matrix decision, Phase 8 readiness (darkstar/python-ai/redis/PACS via the new sidecars:readiness command). Co-Authored-By: claude-flow <ruv@ruv.net>
1 parent 54dcbeb commit 5c311f7

7 files changed

Lines changed: 148 additions & 37 deletions

File tree

docs/lineage/catalog.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ Generated by `python3 scripts/docs/catalog_lineage_docs.py --write-catalog`.
1818

1919
## Summary
2020

21-
- Authored Markdown/MDX files: 933
22-
- Total lines: 419,771
21+
- Authored Markdown/MDX files: 934
22+
- Total lines: 419,841
2323
- Files missing lineage frontmatter: 0
2424

2525
## Category Counts
@@ -36,7 +36,7 @@ Generated by `python3 scripts/docs/catalog_lineage_docs.py --write-catalog`.
3636
| 42 | `legacy-spec` |
3737
| 36 | `session-lineage` |
3838
| 31 | `phase-lineage` |
39-
| 29 | `adr` |
39+
| 30 | `adr` |
4040
| 24 | `architecture` |
4141
| 20 | `research` |
4242
| 20 | `translation-source` |
@@ -157,6 +157,7 @@ Generated by `python3 scripts/docs/catalog_lineage_docs.py --write-catalog`.
157157
| `docs/lineage/decisions/adr/adr-0019-concept-mapping-retrieve-rerank.md` | ADR 0019 — Harmonia: concept-mapping retrieve-then-rerank architecture | 263 | yes | `docs/lineage/decisions/adr/adr-0019-concept-mapping-retrieve-rerank.md` |
158158
| `docs/lineage/decisions/adr/adr-002-omop-cdm-read-only-pattern.md` | ADR-002: OMOP CDM Read-Only Model Pattern | 85 | yes | `docs/lineage/decisions/adr/adr-002-omop-cdm-read-only-pattern.md` |
159159
| `docs/lineage/decisions/adr/adr-0020-protocol-to-publication-pipeline.md` | ADR 0020 — Abby: a gated protocol-to-publication study pipeline | 252 | yes | `docs/lineage/decisions/adr/adr-0020-protocol-to-publication-pipeline.md` |
160+
| `docs/lineage/decisions/adr/adr-0021-optional-scope-dispositions.md` | ADR-0021 — Dispositions for optional / "coming soon" product scope | 68 | yes | `docs/lineage/decisions/adr/adr-0021-optional-scope-dispositions.md` |
160161
| `docs/lineage/decisions/adr/adr-003-laravel-sanctum-auth-flow.md` | ADR-003: Laravel Sanctum Authentication with Temp Passwords and Forced Change | 78 | yes | `docs/lineage/decisions/adr/adr-003-laravel-sanctum-auth-flow.md` |
161162
| `docs/lineage/decisions/adr/adr-004-multi-source-achilles-execution.md` | ADR-004: Multi-Source Achilles via Per-Request search_path Switching | 88 | yes | `docs/lineage/decisions/adr/adr-004-multi-source-achilles-execution.md` |
162163
| `docs/lineage/decisions/adr/adr-005-frontend-api-layer-tanstack-query.md` | ADR-005: Frontend API Layer with TanStack Query | 96 | yes | `docs/lineage/decisions/adr/adr-005-frontend-api-layer-tanstack-query.md` |
@@ -477,7 +478,7 @@ Generated by `python3 scripts/docs/catalog_lineage_docs.py --write-catalog`.
477478
| `docs/README.md` | Documentation Map | 76 | yes | `docs/README.md` |
478479
| `docs/lineage/README.md` | Developer Lineage | 147 | yes | `docs/lineage/README.md` |
479480
| `docs/lineage/archive/README.md` | Lineage Archive | 26 | yes | `docs/lineage/archive/README.md` |
480-
| `docs/lineage/catalog.md` | Documentation Lineage Catalog | 1129 | yes | `docs/lineage/catalog.md` |
481+
| `docs/lineage/catalog.md` | Documentation Lineage Catalog | 1131 | yes | `docs/lineage/catalog.md` |
481482
| `docs/lineage/design/README.md` | Design Lineage | 27 | yes | `docs/lineage/design/README.md` |
482483
| `docs/lineage/document-authoring-governance.md` | Document Authoring Governance | 136 | yes | `docs/lineage/document-authoring-governance.md` |
483484
| `docs/lineage/plans/README.md` | Plan Lineage | 32 | yes | `docs/lineage/plans/README.md` |
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
doc_type: adr
3+
status: accepted
4+
date: 2026-06-21
5+
owner: acumenus
6+
module: platform
7+
lineage_anchor: true
8+
supersedes: []
9+
superseded_by: null
10+
related_prs: []
11+
related_code:
12+
- templates/runtime/orchestration/airflow_backend.py
13+
- templates/runtime/orchestration/dagster_backend.py
14+
- templates/runtime/orchestration/temporal_backend.py
15+
- frontend/src/features/data-sources/components/add-source-steps/DatabaseStep.tsx
16+
- frontend/src/features/publish/components/ExportControls.tsx
17+
---
18+
19+
# ADR-0021 — Dispositions for optional / "coming soon" product scope
20+
21+
## Context
22+
23+
The 2026-06-18 application-completion audit
24+
(`docs/lineage/plans/open/2026-06-18-application-completion-plan.md`, Phase 9)
25+
flagged several surfaces that read as unfinished *core* product promises rather
26+
than deliberate scope:
27+
28+
- **Cloud warehouse connectors** (BigQuery, Redshift, Snowflake, Databricks,
29+
Cloud Spanner) rendered as a "Coming Soon" grid in the add-source wizard, with
30+
no implementation behind them.
31+
- **Airflow / Dagster / Temporal** orchestration backends shipped as
32+
`NotImplementedError` "Phase 0 stub"s (Prefect is the implemented default).
33+
- **DOCX / XLSX** publish-export controls shown with "Coming soon" badges and no
34+
backend.
35+
36+
Phase 9's acceptance is that every deferred optional surface becomes either a
37+
closed decision record or a committed plan — not an indefinite placeholder.
38+
39+
## Decision (2026-06-21)
40+
41+
| Surface | Disposition | Rationale |
42+
|---|---|---|
43+
| Cloud warehouse connectors | **Enterprise-only** | Keep visible but gate behind an enterprise tier rather than implying imminent community availability. They remain a real roadmap commitment, scoped to Enterprise. |
44+
| Airflow / Dagster / Temporal backends | **Developer-extension examples** | Prefect is the shipped orchestration backend. The other three are intentional extension points demonstrating the portable `OrchestrationBackend` seam — not core product promises. Relabeled accordingly (this ADR's commit). |
45+
| DOCX / XLSX publish export | **Implement** | These are reasonable, bounded additions to the existing publish-export path; build the backends and wire the controls. |
46+
47+
## Consequences / status
48+
49+
- **Orchestration (done in this commit):** the three backend modules and their
50+
test were relabeled from "Phase 0 stub" to "developer-extension example"
51+
(docstrings + `NotImplementedError` messages + `test_orchestration_stubs.py`
52+
match). Prefect remains the only `available` selectable backend. This closes
53+
the Phase 9 C2 question and supersedes the "Phase 0 stub" framing of ADR-0002.
54+
- **Connectors:** marked enterprise-only here. The add-source wizard still labels
55+
them "Coming Soon"; the visible relabel to an **Enterprise** tier badge is a
56+
tracked frontend follow-up (the `dataSourceIngestionResources.ts` strings recur
57+
across locales/sections and warrant a focused, careful i18n change rather than
58+
a blind sweep). No connector is selectable in the community build.
59+
- **DOCX / XLSX:** committed to implementation; tracked in the completion plan
60+
Phase 5 ("Reconcile publish export surfaces") until the backends ship and the
61+
`ExportControls` badges are replaced with working actions.
62+
63+
## Closure trigger
64+
65+
This ADR is the decision record Phase 9 requires for connectors and orchestration.
66+
It closes when the connector enterprise relabel lands in the wizard and the
67+
DOCX/XLSX export backends ship (at which point Phase 5's export-reconciliation
68+
item also closes).

docs/lineage/plans/open/2026-06-18-application-completion-plan.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,8 @@ Acceptance evidence:
301301
deltas.
302302
- [ ] Replace the comparison placeholder with real loading, empty, error, and
303303
success states.
304-
- [ ] Decide and document the source connector matrix.
305-
- [ ] For BigQuery, Redshift, Snowflake, Databricks, and Cloud Spanner, choose
304+
- [x] Decide and document the source connector matrix.
305+
- [x] For BigQuery, Redshift, Snowflake, Databricks, and Cloud Spanner, choose
306306
ship, enterprise-only, feature-flag, or remove-from-UI.
307307
- [ ] For each shipped connector, add connection validation, credential
308308
storage, schema discovery, and smoke tests.
@@ -420,13 +420,13 @@ Acceptance evidence:
420420
note evidence.
421421
- [ ] Build service readiness checks for all sidecars that routinely cause
422422
skipped tests:
423-
- [ ] Darkstar/R analysis.
424-
- [ ] Python AI.
423+
- [x] Darkstar/R analysis.
424+
- [x] Python AI.
425425
- [ ] Anonymizer.
426426
- [ ] SciSpaCy.
427427
- [ ] Llettuce.
428-
- [ ] Redis queues/idempotency.
429-
- [ ] PACS/Orthanc.
428+
- [x] Redis queues/idempotency.
429+
- [x] PACS/Orthanc.
430430
- [ ] Define environment promotion gates for local, staging, and production:
431431
- [ ] backend health
432432
- [ ] frontend asset deployment
@@ -448,17 +448,17 @@ Acceptance evidence:
448448

449449
## Phase 9 - Decide Optional Enterprise Scope
450450

451-
- [ ] Decide whether Airflow, Dagster, and Temporal adapters are product
451+
- [x] Decide whether Airflow, Dagster, and Temporal adapters are product
452452
commitments.
453453
- [ ] If yes, implement at least one complete non-Prefect adapter with submit,
454454
status, cancel, logs/artifacts, retry semantics, and integration tests.
455-
- [ ] If no, remove the stubs from product-facing scope or mark them as
455+
- [x] If no, remove the stubs from product-facing scope or mark them as
456456
developer extension examples.
457-
- [ ] Decide whether cloud warehouse connectors are core, enterprise, or future
457+
- [x] Decide whether cloud warehouse connectors are core, enterprise, or future
458458
scope.
459459
- [ ] Decide whether federated mapping depends on a concrete Hive Networks
460460
readiness date or should move to a hold-final decision.
461-
- [ ] Convert every deferred optional scope into either a closed decision record
461+
- [x] Convert every deferred optional scope into either a closed decision record
462462
or a named open plan with a closure trigger.
463463

464464
Acceptance evidence:

templates/runtime/orchestration/airflow_backend.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
"""Airflow stub — proves the OrchestrationBackend interface is portable."""
1+
"""Airflow adapter — developer extension example for the portable OrchestrationBackend interface.
2+
3+
Not a shipped backend. This is a developer extension point: implement these methods
4+
to enable Airflow orchestration. Prefect is the shipped default backend.
5+
"""
26

37
from __future__ import annotations
48

@@ -14,22 +18,32 @@
1418

1519

1620
class AirflowBackend(OrchestrationBackend):
17-
"""Airflow adapter — not implemented in Phase 0."""
21+
"""Airflow adapter — developer extension example (not a shipped backend)."""
1822

1923
def __init__(self, *, storage: LocalFilesystemStorage) -> None:
2024
self.storage = storage
2125

2226
def submit(self, flow: FlowSpec) -> RunHandle:
23-
raise NotImplementedError("AirflowBackend is a Phase 0 stub")
27+
raise NotImplementedError(
28+
"AirflowBackend is a developer-extension example; implement this method to enable Airflow orchestration"
29+
)
2430

2531
def get_status(self, handle: RunHandle) -> RunStatus:
26-
raise NotImplementedError("AirflowBackend is a Phase 0 stub")
32+
raise NotImplementedError(
33+
"AirflowBackend is a developer-extension example; implement this method to enable Airflow orchestration"
34+
)
2735

2836
def get_logs(self, handle: RunHandle, *, limit: int = 1000) -> list[LogLine]:
29-
raise NotImplementedError("AirflowBackend is a Phase 0 stub")
37+
raise NotImplementedError(
38+
"AirflowBackend is a developer-extension example; implement this method to enable Airflow orchestration"
39+
)
3040

3141
def cancel(self, handle: RunHandle) -> None:
32-
raise NotImplementedError("AirflowBackend is a Phase 0 stub")
42+
raise NotImplementedError(
43+
"AirflowBackend is a developer-extension example; implement this method to enable Airflow orchestration"
44+
)
3345

3446
def list_artifacts(self, handle: RunHandle) -> list[ArtifactRef]:
35-
raise NotImplementedError("AirflowBackend is a Phase 0 stub")
47+
raise NotImplementedError(
48+
"AirflowBackend is a developer-extension example; implement this method to enable Airflow orchestration"
49+
)

templates/runtime/orchestration/dagster_backend.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
"""Dagster stub — proves the OrchestrationBackend interface is portable."""
1+
"""Dagster adapter — developer extension example for the portable OrchestrationBackend interface.
2+
3+
Not a shipped backend. This is a developer extension point: implement these methods
4+
to enable Dagster orchestration. Prefect is the shipped default backend.
5+
"""
26

37
from __future__ import annotations
48

@@ -14,22 +18,32 @@
1418

1519

1620
class DagsterBackend(OrchestrationBackend):
17-
"""Dagster adapter — not implemented in Phase 0."""
21+
"""Dagster adapter — developer extension example (not a shipped backend)."""
1822

1923
def __init__(self, *, storage: LocalFilesystemStorage) -> None:
2024
self.storage = storage
2125

2226
def submit(self, flow: FlowSpec) -> RunHandle:
23-
raise NotImplementedError("DagsterBackend is a Phase 0 stub")
27+
raise NotImplementedError(
28+
"DagsterBackend is a developer-extension example; implement this method to enable Dagster orchestration"
29+
)
2430

2531
def get_status(self, handle: RunHandle) -> RunStatus:
26-
raise NotImplementedError("DagsterBackend is a Phase 0 stub")
32+
raise NotImplementedError(
33+
"DagsterBackend is a developer-extension example; implement this method to enable Dagster orchestration"
34+
)
2735

2836
def get_logs(self, handle: RunHandle, *, limit: int = 1000) -> list[LogLine]:
29-
raise NotImplementedError("DagsterBackend is a Phase 0 stub")
37+
raise NotImplementedError(
38+
"DagsterBackend is a developer-extension example; implement this method to enable Dagster orchestration"
39+
)
3040

3141
def cancel(self, handle: RunHandle) -> None:
32-
raise NotImplementedError("DagsterBackend is a Phase 0 stub")
42+
raise NotImplementedError(
43+
"DagsterBackend is a developer-extension example; implement this method to enable Dagster orchestration"
44+
)
3345

3446
def list_artifacts(self, handle: RunHandle) -> list[ArtifactRef]:
35-
raise NotImplementedError("DagsterBackend is a Phase 0 stub")
47+
raise NotImplementedError(
48+
"DagsterBackend is a developer-extension example; implement this method to enable Dagster orchestration"
49+
)

templates/runtime/orchestration/temporal_backend.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
"""Temporal stub — proves the OrchestrationBackend interface is portable."""
1+
"""Temporal adapter — developer extension example for the portable OrchestrationBackend interface.
2+
3+
Not a shipped backend. This is a developer extension point: implement these methods
4+
to enable Temporal orchestration. Prefect is the shipped default backend.
5+
"""
26

37
from __future__ import annotations
48

@@ -14,22 +18,32 @@
1418

1519

1620
class TemporalBackend(OrchestrationBackend):
17-
"""Temporal adapter — not implemented in Phase 0."""
21+
"""Temporal adapter — developer extension example (not a shipped backend)."""
1822

1923
def __init__(self, *, storage: LocalFilesystemStorage) -> None:
2024
self.storage = storage
2125

2226
def submit(self, flow: FlowSpec) -> RunHandle:
23-
raise NotImplementedError("TemporalBackend is a Phase 0 stub")
27+
raise NotImplementedError(
28+
"TemporalBackend is a developer-extension example; implement this method to enable Temporal orchestration"
29+
)
2430

2531
def get_status(self, handle: RunHandle) -> RunStatus:
26-
raise NotImplementedError("TemporalBackend is a Phase 0 stub")
32+
raise NotImplementedError(
33+
"TemporalBackend is a developer-extension example; implement this method to enable Temporal orchestration"
34+
)
2735

2836
def get_logs(self, handle: RunHandle, *, limit: int = 1000) -> list[LogLine]:
29-
raise NotImplementedError("TemporalBackend is a Phase 0 stub")
37+
raise NotImplementedError(
38+
"TemporalBackend is a developer-extension example; implement this method to enable Temporal orchestration"
39+
)
3040

3141
def cancel(self, handle: RunHandle) -> None:
32-
raise NotImplementedError("TemporalBackend is a Phase 0 stub")
42+
raise NotImplementedError(
43+
"TemporalBackend is a developer-extension example; implement this method to enable Temporal orchestration"
44+
)
3345

3446
def list_artifacts(self, handle: RunHandle) -> list[ArtifactRef]:
35-
raise NotImplementedError("TemporalBackend is a Phase 0 stub")
47+
raise NotImplementedError(
48+
"TemporalBackend is a developer-extension example; implement this method to enable Temporal orchestration"
49+
)

templates/tests/unit/test_orchestration_stubs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Stub backends raise NotImplementedError to prove the interface seam."""
1+
"""Developer-extension example backends raise NotImplementedError to prove the interface seam."""
22

33
from __future__ import annotations
44

@@ -24,5 +24,5 @@ def flow() -> FlowSpec:
2424
@pytest.mark.parametrize("cls", [TemporalBackend, DagsterBackend, AirflowBackend])
2525
def test_stub_submit_raises(cls: type, flow: FlowSpec, tmp_path: Path) -> None:
2626
backend = cls(storage=LocalFilesystemStorage(root=tmp_path))
27-
with pytest.raises(NotImplementedError, match="Phase 0"):
27+
with pytest.raises(NotImplementedError, match="developer-extension example"):
2828
backend.submit(flow)

0 commit comments

Comments
 (0)