docs: renumber PRD 0081 -> 0083 across the reconcile chunk

Follows the base PR's renumber (0081 was already taken; main is on 0082). Update
every `PRD 0081` reference in the gateway-attach code, tests, and ADR 0006, plus
ADR 0006's link to the PRD file. No behaviour change.

Refs #516, #519.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 15:15:44 +00:00
committed by didericis
parent 6f3b221823
commit 31b6724a52
21 changed files with 28 additions and 28 deletions
+1 -1
View File
@@ -528,7 +528,7 @@ class BottleBackend(ABC, Generic[PlanT, CleanupT, AttachTargetT]):
def attach_bottled_agents_to_gateway(self) -> None:
"""Reconcile every running bottle against the freshly-(re)booted gateway
on the cold-boot bring-up path (PRD 0081). The shared flow + fail-hard
on the cold-boot bring-up path (PRD 0083). The shared flow + fail-hard
policy live in `gateway_attach`; backends override only the three
primitives below (ADR 0006)."""
from .gateway_attach import reconcile_running_bottles
+1 -1
View File
@@ -54,7 +54,7 @@ class DockerBottleBackend(BottleBackend["DockerBottlePlan", "DockerBottleCleanup
def __init__(self, *, infra: "DockerInfraService | None" = None) -> None:
# The infra service whose gateway just cold-booted, passed in on the
# bring-up reconcile path (PRD 0081) so `_gateway_attach_resources`
# bring-up reconcile path (PRD 0083) so `_gateway_attach_resources`
# reads THAT gateway's CA rather than a fresh default-named service —
# otherwise a non-default instance (an isolated integration test's
# `-itest-` gateway) reads the default `bot-bottle-orch-gateway`, which
+1 -1
View File
@@ -272,7 +272,7 @@ class DockerGateway(Gateway):
if self._control_network:
self._connect_control_network()
# (Re)created a fresh container — signal a cold boot so the caller
# reconciles running bottles against it (PRD 0081).
# reconciles running bottles against it (PRD 0083).
return True
def _connect_control_network(self) -> None:
+1 -1
View File
@@ -147,7 +147,7 @@ class DockerInfraService(InfraService):
)
# A (re)created gateway container minted/mounted its CA afresh and lost
# every bottle's per-bottle state; reconcile the already-running bottles
# against it (PRD 0081). Skipped when a healthy current gateway was left
# against it (PRD 0083). Skipped when a healthy current gateway was left
# untouched — no cold boot, nothing to reconcile.
if cold_booted:
from .backend import DockerBottleBackend
+2 -2
View File
@@ -83,7 +83,7 @@ def running_agent_containers(
) -> list[str]:
"""Every running agent container on the gateway `network` (the gateway
itself excluded) — the bottles the bring-up reconcile attaches to the fresh
gateway (PRD 0081). Raises `OSError` if `docker` can't be run (fail hard: a
gateway (PRD 0083). Raises `OSError` if `docker` can't be run (fail hard: a
reconcile that can't list its bottles must not look like "no bottles")."""
proc = run_docker([
"docker", "network", "inspect", "--format",
@@ -98,7 +98,7 @@ def running_agent_containers(
def push_ca_to_container(container: str, ca_pem: str) -> None:
"""(Re)attach one running agent container to the current gateway: replace
its trusted gateway CA with `ca_pem` and rebuild its trust store via
`docker cp` + `docker exec` (PRD 0081). Unconditional install — there is one
`docker cp` + `docker exec` (PRD 0083). Unconditional install — there is one
gateway, so no fingerprint match is needed.
Fail hard: raises `InfraLaunchError` (naming the container) on any failure —
+1 -1
View File
@@ -73,7 +73,7 @@ class FirecrackerInfraService(InfraService):
# The fresh gateway rootfs minted a new CA and lost every bottle's
# git-gate/token state; reconcile the already-running bottles against
# it so a gateway rebuild doesn't silently break their egress
# (PRD 0081). Cold-boot only — the adopt fast-paths above never reach
# (PRD 0083). Cold-boot only — the adopt fast-paths above never reach
# here, so a healthy current gateway is left untouched.
if cold_booted:
from .backend import FirecrackerBottleBackend
@@ -90,7 +90,7 @@ def persist_env_var_secret(private_key: Path, guest_ip: str, secret: str) -> Non
def attach_ca_to_agent_vm(run_dir: Path, ca_pem: str) -> None:
"""(Re)attach one running agent VM (identified by its `run_dir`) to the
current gateway: replace its trusted gateway CA with `ca_pem` and rebuild
its trust store over SSH (PRD 0081). Unconditional install — there is one
its trust store over SSH (PRD 0083). Unconditional install — there is one
gateway, so no fingerprint match is needed. Bare-pipe input keeps the cert
off argv.
+2 -2
View File
@@ -1,4 +1,4 @@
"""The shared gateway-attach reconcile flow (PRD 0081).
"""The shared gateway-attach reconcile flow (PRD 0083).
`BottleBackend.attach_bottled_agents_to_gateway()` delegates here so every
backend reconciles running bottles against a freshly-booted gateway *the same
@@ -21,7 +21,7 @@ if TYPE_CHECKING:
@dataclass(frozen=True)
class GatewayAttachResources:
"""Everything a running bottle needs to (re)attach to the current gateway on
a cold boot (PRD 0081). Gathered once per reconcile and handed to every
a cold boot (PRD 0083). Gathered once per reconcile and handed to every
bottle. The CA now; egress secrets and git-gate state join as the reconcile
grows (#516)."""
@@ -112,7 +112,7 @@ class MacosGateway(Gateway):
Always returns True: this recreates the gateway container unconditionally
(a cold boot), so the caller reconciles running bottles against it
(PRD 0081)."""
(PRD 0083)."""
self._orchestrator_url = orchestrator_url
self._gateway_token = gateway_token
# Fail closed on a missing policy source or token: the resolver-only data
+1 -1
View File
@@ -142,7 +142,7 @@ class MacosInfraService(InfraService):
url, orchestrator.mint_gateway_token())
# A (re)created gateway container minted/mounted its CA afresh and lost
# every bottle's per-bottle state; reconcile the already-running bottles
# against it (PRD 0081). Skipped when a healthy current gateway was left
# against it (PRD 0083). Skipped when a healthy current gateway was left
# untouched — no cold boot, nothing to reconcile.
if cold_booted:
from .backend import MacosContainerBottleBackend
@@ -99,7 +99,7 @@ def ensure_gateway(
def running_agent_containers() -> list[str]:
"""Every running agent container's name — the bottles the bring-up reconcile
attaches to the fresh gateway (PRD 0081). Raises `EnumerationError` if the
attaches to the fresh gateway (PRD 0083). Raises `EnumerationError` if the
live set can't be determined (fail hard rather than reconcile a partial
set)."""
return [f"{CONTAINER_NAME_PREFIX}{agent.slug}" for agent in enumerate_active()]
@@ -108,7 +108,7 @@ def running_agent_containers() -> list[str]:
def push_ca_to_container(name: str, ca_pem: str) -> None:
"""(Re)attach one running agent container to the current gateway: replace
its trusted gateway CA with `ca_pem` and rebuild its trust store via
`container cp` + `container exec` (PRD 0081). Unconditional install there
`container cp` + `container exec` (PRD 0083). Unconditional install there
is one gateway, so no fingerprint match is needed.
Fail hard: raises `InfraLaunchError` (naming the container) on any failure
+1 -1
View File
@@ -133,7 +133,7 @@ class Gateway(abc.ABC):
so its mitmproxy minted a fresh CA and lost its per-bottle state), False
when a healthy current gateway was left untouched. The bring-up flow
uses this as the cold-boot signal that gates the running-bottle
reconcile (`attach_bottled_agents_to_gateway`, PRD 0081)."""
reconcile (`attach_bottled_agents_to_gateway`, PRD 0083)."""
@abc.abstractmethod
def is_running(self) -> bool:
@@ -15,7 +15,7 @@ macOS-container). Cross-backend operations can be expressed two ways:
concrete method and each backend overrides small **primitives** it calls.
Form 1 gives each backend total freedom, which is exactly the problem: the three
implementations drift. The bring-up reconcile (PRD 0081) first shipped as form 1
implementations drift. The bring-up reconcile (PRD 0083) first shipped as form 1
and immediately diverged — each backend re-implemented "gather CA → list running
bottles → push to each", and one backend's copy silently skipped failures while
another's aborted, an inconsistency caught only in review (#519). The behaviour
@@ -37,7 +37,7 @@ method that:
- delegates only the irreducibly backend-specific steps to `@abstractmethod`
primitives with narrow, well-typed signatures.
The first application is `attach_bottled_agents_to_gateway()` (PRD 0081): the
The first application is `attach_bottled_agents_to_gateway()` (PRD 0083): the
base gathers resources once, attempts every running bottle, and raises an
aggregate `InfraLaunchError` if any failed; backends supply only
`_gateway_attach_resources()`, `_running_bottles()`, and
@@ -60,6 +60,6 @@ operations whose *shape* should be uniform, not about banning abstract methods.
## Links
- PRD 0081 (`docs/prds/0081-reprovision-gateway-state-on-bringup.md`).
- PRD 0083 (`docs/prds/0083-reprovision-gateway-state-on-bringup.md`).
- Review that prompted this: PR #519.
- `bot_bottle/backend/base.py` (`BottleBackend.attach_bottled_agents_to_gateway`).
+1 -1
View File
@@ -85,7 +85,7 @@ class TestRuntimeModuleSizes(unittest.TestCase):
def test_backend_contract_does_not_absorb_preparation_logic(self) -> None:
# base.py holds the backend *contract*; implementation lives elsewhere.
# The cap is a tripwire against absorbing preparation/impl logic, not a
# ban on new contract surface — bumped 580->615 for the PRD 0081
# ban on new contract surface — bumped 580->615 for the PRD 0083
# gateway-attach contract (delegator + 3 abstract primitives; the flow
# itself lives in backend/gateway_attach.py, not here).
caps = {
@@ -162,7 +162,7 @@ class TestFirecrackerReprovision(unittest.TestCase):
class TestAttachFlow(unittest.TestCase):
"""PRD 0081 / #519 review: the base backend owns the reconcile flow and
"""PRD 0083 / #519 review: the base backend owns the reconcile flow and
fails hard gather resources, attempt every running bottle, then raise an
aggregate if any failed (never silently skip)."""
@@ -208,7 +208,7 @@ class TestAttachFlow(unittest.TestCase):
class TestFirecrackerAttachPrimitive(unittest.TestCase):
"""PRD 0081: attach_ca_to_agent_vm pushes the current gateway CA into one
"""PRD 0083: attach_ca_to_agent_vm pushes the current gateway CA into one
running agent VM over SSH, failing hard."""
def _run_dir(self, root: Path, ip: str = "10.243.0.3") -> Path:
+1 -1
View File
@@ -70,7 +70,7 @@ class TestDockerInfraService(unittest.TestCase):
def test_cold_boot_reconciles_running_bottles(self) -> None:
# A (re)created gateway (connect returns True) triggers the bring-up
# reconcile so running bottles re-trust the fresh gateway (PRD 0081).
# reconcile so running bottles re-trust the fresh gateway (PRD 0083).
self.gw.connect_to_orchestrator.return_value = True
self.svc.ensure_running()
self.attach.assert_called_once_with()
+1 -1
View File
@@ -63,7 +63,7 @@ class TestFirecrackerGatewayConnect(unittest.TestCase):
patch.object(infra_vm, "push_secret") as push:
cold_booted = gw.connect_to_orchestrator(_ORCH_URL, _TOKEN)
# The VM is booted fresh here (cold-boot path only), so it always
# signals a cold boot → the caller reconciles running bottles (PRD 0081).
# signals a cold boot → the caller reconciles running bottles (PRD 0083).
self.assertTrue(cold_booted)
# Booted on the gateway link with the gateway role; the orchestrator's
# guest IP (parsed off the URL) rides the cmdline as bb_orch.
+1 -1
View File
@@ -49,7 +49,7 @@ _ATTACH = (
class TestEnsureRunning(unittest.TestCase):
def setUp(self) -> None:
# The cold-boot branch reconciles running bottles against the fresh
# gateway (PRD 0081). Stub it so these composition tests stay isolated
# gateway (PRD 0083). Stub it so these composition tests stay isolated
# from SSH; the wiring itself is asserted in test_cold_boot_reconciles*.
ap = patch(_ATTACH)
self.attach = ap.start()
+1 -1
View File
@@ -46,7 +46,7 @@ class TestMacosGatewayConnect(unittest.TestCase):
def test_connect_signals_cold_boot(self) -> None:
# The container is recreated unconditionally, so connect always signals
# a cold boot → the caller reconciles running bottles (PRD 0081).
# a cold boot → the caller reconciles running bottles (PRD 0083).
run = Mock(return_value=_proc())
with patch(f"{_GW}.container_mod") as mod, \
patch(f"{_GW}.host_gateway_ca_dir", return_value=Path("/ca")):
+1 -1
View File
@@ -58,7 +58,7 @@ class TestInfraEnsureRunning(unittest.TestCase):
def test_cold_boot_reconciles_running_bottles(self) -> None:
# A (re)created gateway (connect returns True) triggers the bring-up
# reconcile so running bottles re-trust the fresh gateway (PRD 0081).
# reconcile so running bottles re-trust the fresh gateway (PRD 0083).
self.gw.connect_to_orchestrator.return_value = True
with patch(f"{_INFRA}.ensure_networks"):
self.svc.ensure_running()
+2 -2
View File
@@ -90,7 +90,7 @@ class TestDockerGateway(unittest.TestCase):
self.assertEqual([], [c for c in calls if c[:2] == ["docker", "run"]])
self.assertEqual([], [c for c in calls if c[:2] == ["docker", "rm"]])
# A healthy current gateway left untouched is not a cold boot — the
# bring-up flow skips the running-bottle reconcile (PRD 0081).
# bring-up flow skips the running-bottle reconcile (PRD 0083).
self.assertFalse(cold_booted)
def test_ensure_running_recreates_when_image_is_stale(self) -> None:
@@ -113,7 +113,7 @@ class TestDockerGateway(unittest.TestCase):
self.assertEqual(1, len([c for c in calls if c[:2] == ["docker", "run"]]))
self.assertTrue(any(c[:2] == ["docker", "rm"] for c in calls))
# A recreated container minted/mounted its CA afresh — a cold boot that
# triggers the running-bottle reconcile (PRD 0081).
# triggers the running-bottle reconcile (PRD 0083).
self.assertTrue(cold_booted)
def test_ensure_running_starts_the_singleton_when_absent(self) -> None: