refactor: repo reorganization for clearer separation of concerns #477

Merged
didericis merged 30 commits from refactor/repo-reorg into fix/db-off-data-plane-469 2026-07-24 19:24:56 -04:00
11 changed files with 47 additions and 84 deletions
Showing only changes of commit 3e2cbcab88 - Show all commits
+2 -2
View File
@@ -29,7 +29,7 @@ from ..git_gate import GitGate, GitGatePlan
from ..log import die
from ..manifest import Manifest, ManifestBottle
from ..supervisor.plan import SupervisePlan
from ..orchestrator.supervisor.supervise import Supervise
from ..orchestrator.supervisor import Supervisor
from . import BottleSpec
@@ -102,7 +102,7 @@ def prepare_supervise(bottle: ManifestBottle, slug: str) -> SupervisePlan | None
return None
supervise_dir = supervise_state_dir(slug)
supervise_dir.mkdir(parents=True, exist_ok=True)
return Supervise().prepare(slug, supervise_dir)
return Supervisor().prepare(slug, supervise_dir)
def merge_provision_env_vars(provision: AgentProvisionPlan) -> AgentProvisionPlan:
+1 -4
View File
@@ -5,10 +5,7 @@ from __future__ import annotations
from datetime import datetime, timezone
from pathlib import Path
try:
from .store.config_store import ConfigStore
except ImportError:
from config_store import ConfigStore # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from .store.config_store import ConfigStore
class StaleImageError(Exception):
+4 -10
View File
@@ -6,16 +6,10 @@ import os
import sqlite3
from pathlib import Path
try:
from ...supervisor.types import Proposal, Response
from ...paths import host_db_path
from ...store.db_store import DbStore
from ...store.migrations import TableMigrations
except ImportError:
from supervisor.types import Proposal, Response # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from paths import host_db_path # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from db_store import DbStore # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from migrations import TableMigrations # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from ...supervisor.types import Proposal, Response
from ...paths import host_db_path
from ...store.db_store import DbStore
from ...store.migrations import TableMigrations
class QueueStore(DbStore):
+27 -5
View File
@@ -1,10 +1,10 @@
"""The orchestrator's view of the supervise plane.
Bundles the orchestrator-owned supervise surface: the queue/audit I/O and diff
rendering (`queue`) and the `Supervise` lifecycle (`supervise`). For
convenience it re-exports the neutral vocabulary (`bot_bottle.supervisor`'s
types + `SupervisePlan`) so orchestrator-side callers — service, CLI, tests —
import from one place.
rendering (`queue`), and the `Supervisor` lifecycle (host-side database
staging). For convenience it re-exports the neutral vocabulary
(`bot_bottle.supervisor`'s types + `SupervisePlan`) so orchestrator-side
callers — service, CLI, tests — import from one place.
The data plane must NOT import this package; it imports `bot_bottle.supervisor`
(neutral) directly and reaches the queue over the control-plane RPC.
@@ -12,8 +12,12 @@ The data plane must NOT import this package; it imports `bot_bottle.supervisor`
from __future__ import annotations
from abc import ABC
from pathlib import Path
from ...supervisor.types import * # noqa: F401,F403 — re-export the neutral vocabulary
from ...supervisor.plan import SupervisePlan
from ..store.store_manager import StoreManager
from .queue import (
archive_all_proposals,
archive_proposal,
@@ -31,4 +35,22 @@ from .queue import (
write_proposal,
write_response,
)
from .supervise import Supervise
class Supervisor(ABC):
"""Per-bottle supervise lifecycle. Encapsulates host-side database staging;
the gateway's start/stop lifecycle is backend-specific.
`prepare` migrates the orchestrator's `bot-bottle.db` and returns the
neutral `SupervisePlan`. It touches the orchestrator store manager, so it
lives here rather than in the neutral `bot_bottle.supervisor` package; the
backend (which drives launch) may import it — backend → orchestrator is an
allowed direction, unlike gateway → orchestrator."""
def prepare(self, slug: str, stage_dir: Path) -> SupervisePlan:
"""Stage the host database. Returns the plan; `internal_network` must be
set by the launch step before .start runs."""
del stage_dir
mgr = StoreManager.instance()
mgr.migrate()
return SupervisePlan(slug=slug, db_path=mgr.db_path)
@@ -1,36 +0,0 @@
"""The `Supervise` lifecycle — host-side database staging (PRD 0013 / 0070).
`Supervise.prepare` migrates the orchestrator's `bot-bottle.db` and returns the
neutral `SupervisePlan`. It touches the orchestrator store manager, so it lives
here rather than in the neutral `bot_bottle.supervisor` package; the backend
(which drives launch) may import it — backend → orchestrator is an allowed
direction, unlike gateway → orchestrator.
"""
from __future__ import annotations
from abc import ABC
from pathlib import Path
from ..store.store_manager import StoreManager
from ...supervisor.plan import SupervisePlan
class Supervise(ABC):
"""Per-bottle supervise daemon. Encapsulates host-side database staging;
the gateway's start/stop lifecycle is backend-specific."""
def prepare(
self,
slug: str,
stage_dir: Path,
) -> SupervisePlan:
"""Stage the host database. Returns the plan; `internal_network` must be
set by the launch step before .start runs."""
del stage_dir
mgr = StoreManager.instance()
mgr.migrate()
return SupervisePlan(
slug=slug,
db_path=mgr.db_path,
)
+4 -10
View File
@@ -5,16 +5,10 @@ from __future__ import annotations
import sqlite3
from pathlib import Path
try:
from ..supervisor.types import AuditEntry
from ..paths import host_db_path
from .db_store import DbStore
from .migrations import TableMigrations
except ImportError:
from supervisor.types import AuditEntry # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from paths import host_db_path # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from db_store import DbStore # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from migrations import TableMigrations # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from ..supervisor.types import AuditEntry
from ..paths import host_db_path
from .db_store import DbStore
from .migrations import TableMigrations
class AuditStore(DbStore):
+3 -8
View File
@@ -4,14 +4,9 @@ from __future__ import annotations
from pathlib import Path
try:
from .db_store import DbStore
from .migrations import TableMigrations
from ..paths import host_db_path
except ImportError:
from db_store import DbStore # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from migrations import TableMigrations # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from paths import host_db_path # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from .db_store import DbStore
from .migrations import TableMigrations
from ..paths import host_db_path
DEFAULT_CACHED_IMAGE_STALE_WARNING_DAYS = 1
+1 -4
View File
@@ -6,10 +6,7 @@ import sqlite3
from contextlib import contextmanager
from pathlib import Path
try:
from .migrations import TableMigrations
except ImportError:
from migrations import TableMigrations # type: ignore[import-not-found] # pylint: disable=import-error,no-name-in-module
from .migrations import TableMigrations
class DbVersionError(Exception):
+1 -1
View File
@@ -11,6 +11,6 @@ tier's private code, importable by `bot_bottle.gateway` **and**
status / poll-status constants, and the shared daemon constants.
* `plan` — `SupervisePlan`, the launch-time staging DTO.
The orchestrator-only half (queue I/O, diff rendering, the `Supervise`
The orchestrator-only half (queue I/O, diff rendering, the `Supervisor`
lifecycle) lives under `bot_bottle.orchestrator.supervisor`.
"""
+3 -3
View File
@@ -1,9 +1,9 @@
"""`SupervisePlan` — the launch-time supervise staging DTO.
A pure value type (no store access), so it lives in the neutral package: the
backend builds it at launch and the orchestrator's `Supervise.prepare` returns
backend builds it at launch and the orchestrator's `Supervisor.prepare` returns
it. The behaviour that fills it in — staging the host database — is the
orchestrator's, in `bot_bottle.orchestrator.supervisor.supervise`.
orchestrator's, in `bot_bottle.orchestrator.supervisor.Supervisor`.
"""
from __future__ import annotations
@@ -14,7 +14,7 @@ from pathlib import Path
@dataclass(frozen=True)
class SupervisePlan:
"""Output of `Supervise.prepare`; consumed by `.start`.
"""Output of `Supervisor.prepare`; consumed by `.start`.
`db_path` is the host database bind-mounted into the gateway at
/run/supervise/bot-bottle.db. `internal_network` is empty at prepare time;
+1 -1
View File
@@ -352,7 +352,7 @@ class TestToolConstants(unittest.TestCase):
)
class _StubSupervise(supervise.Supervise):
class _StubSupervise(supervise.Supervisor):
"""Concrete Supervise subclass for testing the prepare template."""
def start(self, plan): # type: ignore