Commit Graph

4 Commits

Author SHA1 Message Date
didericis-claude 3c0d2fb66f refactor(backend): base owns the gateway-attach flow, fail hard (0081 review)
lint / lint (push) Successful in 1m1s
test / unit (pull_request) Successful in 1m5s
tracker-policy-pr / check-pr (pull_request) Successful in 10s
test / integration-docker (pull_request) Failing after 1m30s
test / coverage (pull_request) Has been skipped
Addresses review on #519 (@didericis 6143 + the fail-hard direction over the
codex skip).

Base owns the flow (6143 / ADR 0006). `attach_bottled_agents_to_gateway()` is
now a concrete method on `BottleBackend` that delegates to
`gateway_attach.reconcile_running_bottles`; backends override only three
primitives — `_gateway_attach_resources()`, `_running_bottles()`,
`_attach_bottle_to_gateway()`. The shared control flow + error policy live in
one place so a backend can't drift onto a bespoke loop or a silent skip. Keeps
the reconcile flow + `GatewayAttachResources` out of `backend/base.py` (the
size guardrail) in a dedicated `backend/gateway_attach.py`. New ADR 0006 records
the "shared behaviour in the base backend, subclasses override primitives"
theme.

Fail hard, never skip (the maintainer's direction over the codex review's
skip). Any attach failure now aborts bring-up instead of being logged and
skipped: a bottle that silently can't reach the fresh gateway (its egress just
starts failing TLS) is worse than a loud failure. Every bottle is attempted and
the failures are raised together (aggregate `InfraLaunchError`) so one bring-up
surfaces the full blast radius. Resource gathering (the CA fetch) also fails
hard. PRD 0081 goal + design updated to match (reversed from the earlier
"tolerate per-bottle failures" draft).

Bumps the base.py guardrail cap 580->600 for the new contract surface (the
delegator + 3 abstract primitives); the flow itself lives in gateway_attach.py.

Refs #516, #519.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 01:50:06 +00:00
didericis 7e9ad8a78d Merge main into fix/db-off-data-plane-469
tracker-policy-pr / check-pr (pull_request) Successful in 13s
test / integration-docker (pull_request) Successful in 35s
test / unit (pull_request) Successful in 47s
lint / lint (push) Successful in 57s
test / integration-firecracker (pull_request) Successful in 3m35s
test / coverage (pull_request) Successful in 32s
test / publish-infra (pull_request) Has been skipped
Brings in main's 8 commits — #470 (backend-agnostic CI guards: BackendStatus
enum, quiet status(), is_backend_available/is_backend_ready, tests/_backend.py
skip_unless_backend) plus firecracker status() readiness checks (kvm/kernel/
dropbear/mke2fs).

Reconciled #470's additions into the reorg'd backend structure:
  * BackendStatus enum + the status(*, quiet=) ABC signature -> backend/base.py
  * is_backend_available / is_backend_ready -> backend/selection.py
  * exposed all three through the lazy backend facade (__init__).
Integration-test conflicts were our control_plane->orchestrator renames vs
main's skip_unless_docker -> skip_unless_backend swap: kept our refactored
import paths + main's guard. Repointed main's new is_backend_* tests to patch
selection._backends (our moved home) instead of the facade.

pyright: 0 errors. Full unit suite green (2272).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 21:35:58 -04:00
didericis 466f4ee13a Merge main into fix/db-off-data-plane-469
tracker-policy-pr / check-pr (pull_request) Successful in 13s
test / integration-docker (pull_request) Successful in 34s
test / unit (pull_request) Successful in 49s
lint / lint (push) Successful in 57s
test / integration-firecracker (pull_request) Successful in 3m29s
test / coverage (pull_request) Successful in 20s
test / publish-infra (pull_request) Has been skipped
Brings in the two commits main gained: #472 (CLI cleanup — remove `info`,
split `list active` into a top-level `active`, simplify `list`) and the
terminology glossary. #472 was written against the old flat cli/ layout,
so its semantics are reconciled into the reorg'd cli/commands/ structure:

  * new `active` command lives at cli/commands/active.py, registered in
    the lazy registry and listed in `help` (not left at the flat path).
  * `info` removed: deleted cli/commands/info.py, dropped from the
    registry and `help`.
  * `list` simplified to list-available-only, using the reorg's
    os.getcwd()/constants.PROG conventions.
  * the `list active` -> `active` doc wording applied to the backend
    docstrings that our split moved into base.py / selection.py.

Our reorg wins for the fully-rewritten dispatcher (cli/__init__ shim,
backend facade). pyright: 0 errors. Full unit suite green (2243).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 19:35:49 -04:00
didericis 3e62f31d8b refactor(backend): split the heavy backend/__init__ into base + selection, thin the package init
tracker-policy-pr / check-pr (pull_request) Successful in 12s
test / integration-docker (pull_request) Successful in 38s
test / unit (pull_request) Successful in 52s
lint / lint (push) Successful in 1m1s
test / integration-firecracker (pull_request) Successful in 3m33s
test / coverage (pull_request) Successful in 17s
test / publish-infra (pull_request) Has been skipped
backend/__init__.py eagerly imported the whole framework (manifest, egress,
git-gate, env, workspace, agent-provider), so importing ANY backend.* submodule
paid ~32 modules just to run the package init. Split it:

  - backend/base.py     — the abstract contract (BottleSpec, BottlePlan,
                          BottleCleanupPlan, ExecResult, ActiveAgent, Bottle,
                          BottleImages, BottleBackend). Carries the framework
                          imports; loaded only when a caller needs the contract.
  - backend/selection.py — backend registry / selection / enumeration
                          (get_bottle_backend, _get_backends, _auto_select_backend,
                          has_backend, known_backend_names, enumerate_active_agents).
                          Concrete backends still imported lazily inside.
  - backend/__init__.py  — thin: a __getattr__ that resolves the public names
                          from those submodules on first access (+ a TYPE_CHECKING
                          block for checkers). Existing `from bot_bottle.backend
                          import X` and patch.object call-sites keep working.

`import bot_bottle.backend` drops from 32 -> 2 bot_bottle modules. Repointed the
backend-selection test's patch targets to the `selection` module (the functions
reference each other there now; the FirecrackerBottleBackend class-method
patches are unchanged — same class object).

Note: backend.docker.util is still heavy because backend/docker/__init__ eagerly
imports DockerBottleBackend — slimming the three sub-package inits is the
follow-up that makes the leaves cheap.

Full unit suite green (2243).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 15:47:29 -04:00