refactor(manifest): consolidate the manifest modules into a bot_bottle.manifest package
tracker-policy-pr / check-pr (pull_request) Failing after 11s
test / integration-docker (pull_request) Successful in 20s
lint / lint (push) Successful in 59s
test / unit (pull_request) Successful in 2m10s
test / integration-firecracker (pull_request) Successful in 3m29s
test / coverage (pull_request) Successful in 38s
test / publish-infra (pull_request) Has been skipped

Move the nine root-level manifest modules into a bot_bottle/manifest/ package,
dropping the redundant manifest_ prefix: the facade (manifest.py) becomes the
package __init__ and keeps re-exporting Manifest / ManifestIndex and the piece
types, while manifest_<x>.py become manifest/<x>.py (agent, bottle, egress,
extends, git, loader, schema, util).

Because the facade stays the package __init__, the ~13 callers that import
`from bot_bottle.manifest import ...` are unchanged; only direct-piece imports
move to `bot_bottle.manifest.<name>`. Inside the package, intra-manifest
imports drop the prefix and the non-manifest siblings (log, yaml_subset,
agent_provider) move to `..`.

No behavior change; full unit suite green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-24 13:04:39 -04:00
parent d7a58e52fd
commit a845cba925
15 changed files with 47 additions and 47 deletions
+1 -1
View File
@@ -380,7 +380,7 @@ def _peek_agent_bottle(manifest: ManifestIndex, agent_name: str) -> str:
return manifest.agents[agent_name].bottle
return ""
from ..manifest_loader import scan_agent_names
from ..manifest.loader import scan_agent_names
from ..yaml_subset import YamlSubsetError, parse_frontmatter
home_agents = scan_agent_names(manifest.home_md / "agents")
+1 -1
View File
@@ -49,7 +49,7 @@ def get_provisioner(
GiteaDeployKeyProvisioner,
)
return GiteaDeployKeyProvisioner(token=token, api_url=api_url)
from .manifest_util import ManifestError
from .manifest.util import ManifestError
raise ManifestError(
f"unknown provisioned_key provider: {provider!r}; "
f"available: gitea"
@@ -63,25 +63,25 @@ from dataclasses import dataclass, field, replace
from pathlib import Path
from typing import Mapping
from .log import warn
from .manifest_util import ManifestError, as_json_object
from .manifest_agent import ManifestAgent, ManifestAgentProvider
from .manifest_bottle import ManifestBottle
from .manifest_egress import (
from ..log import warn
from .util import ManifestError, as_json_object
from .agent import ManifestAgent, ManifestAgentProvider
from .bottle import ManifestBottle
from .egress import (
EGRESS_AUTH_SCHEMES,
ManifestEgressConfig,
ManifestEgressRoute,
)
from .manifest_extends import merge_bottles_runtime, resolve_bottles
from .manifest_git import ManifestGitEntry, ManifestGitUser, ManifestKeyConfig
from .manifest_loader import (
from .extends import merge_bottles_runtime, resolve_bottles
from .git import ManifestGitEntry, ManifestGitUser, ManifestKeyConfig
from .loader import (
check_stale_json,
load_bottle_chain_from_dir,
scan_agent_names,
scan_bottle_names,
)
from .manifest_schema import validate_agent_frontmatter_keys
from .yaml_subset import YamlSubsetError, parse_frontmatter
from .schema import validate_agent_frontmatter_keys
from ..yaml_subset import YamlSubsetError, parse_frontmatter
# Re-export everything that callers currently import from this module.
__all__ = [
@@ -5,10 +5,10 @@ from __future__ import annotations
from dataclasses import dataclass, field
from typing import cast
from .agent_provider import PROVIDER_TEMPLATES
from .manifest_util import ManifestError, as_json_object
from .manifest_git import ManifestGitUser
from .manifest_schema import AGENT_MODEL_KEYS, is_valid_entity_name
from ..agent_provider import PROVIDER_TEMPLATES
from .util import ManifestError, as_json_object
from .git import ManifestGitUser
from .schema import AGENT_MODEL_KEYS, is_valid_entity_name
@dataclass(frozen=True)
@@ -1,13 +1,13 @@
"""The `ManifestBottle` value type.
Split out of `manifest.py` so the `extends:`/loader resolvers can import it
without a circular dependency: `manifest.py` imports those resolvers, while
they only need this value type. Everything here depends on leaf modules
(`manifest_util`, `manifest_agent`, `manifest_egress`, `manifest_git`,
`manifest_schema`), so this module sits at the bottom of the manifest layer.
Split out of the package facade (`manifest/__init__.py`) so the `extends:`/
loader resolvers can import it without a circular dependency: the facade
imports those resolvers, while they only need this value type. Everything here
depends on leaf modules (`util`, `agent`, `egress`, `git`, `schema`), so this
module sits at the bottom of the manifest layer.
`manifest.py` re-exports `ManifestBottle`, so existing
`from .manifest import ManifestBottle` callers are unaffected.
The facade re-exports `ManifestBottle`, so existing
`from bot_bottle.manifest import ManifestBottle` callers are unaffected.
"""
from __future__ import annotations
@@ -15,11 +15,11 @@ from __future__ import annotations
from dataclasses import dataclass, field
from typing import Mapping
from .manifest_util import ManifestError, as_json_object
from .manifest_agent import ManifestAgentProvider
from .manifest_egress import ManifestEgressConfig
from .manifest_git import ManifestGitEntry, ManifestGitUser, parse_git_gate_config
from .manifest_schema import BOTTLE_KEYS
from .util import ManifestError, as_json_object
from .agent import ManifestAgentProvider
from .egress import ManifestEgressConfig
from .git import ManifestGitEntry, ManifestGitUser, parse_git_gate_config
from .schema import BOTTLE_KEYS
__all__ = ["ManifestBottle"]
@@ -6,7 +6,7 @@ import re
from dataclasses import dataclass
from typing import cast
from .manifest_util import ManifestError, as_json_object
from .util import ManifestError, as_json_object
EGRESS_AUTH_SCHEMES = ("Bearer", "token")
@@ -2,10 +2,10 @@
from __future__ import annotations
from .manifest_bottle import ManifestBottle
from .manifest_egress import ManifestEgressConfig, validate_egress_routes
from .manifest_git import ManifestGitUser, parse_git_gate_config
from .manifest_util import ManifestError, as_json_object
from .bottle import ManifestBottle
from .egress import ManifestEgressConfig, validate_egress_routes
from .git import ManifestGitUser, parse_git_gate_config
from .util import ManifestError, as_json_object
def _overlay_declared_bool(
@@ -5,7 +5,7 @@ from __future__ import annotations
import re
from dataclasses import dataclass
from .manifest_util import ManifestError, as_json_object
from .util import ManifestError, as_json_object
# Shell-safe characters for git-gate repo names. Names are embedded in
# the generated entrypoint shell script (shlex.quote is the primary
@@ -4,15 +4,15 @@ from __future__ import annotations
from pathlib import Path
from .log import warn
from .manifest_bottle import ManifestBottle
from .manifest_extends import resolve_bottles
from .manifest_schema import (
from ..log import warn
from .bottle import ManifestBottle
from .extends import resolve_bottles
from .schema import (
entity_name_from_path,
validate_bottle_frontmatter_keys,
)
from .manifest_util import ManifestError
from .yaml_subset import YamlSubsetError, parse_frontmatter
from .util import ManifestError
from ..yaml_subset import YamlSubsetError, parse_frontmatter
def check_stale_json(dir_path: Path, md_dir: Path, label: str) -> None:
@@ -68,7 +68,7 @@ def _validate_frontmatter_keys(
keys: object,
allowed_keys: frozenset[str],
) -> None:
from .manifest_util import ManifestError
from .util import ManifestError
key_set = set(keys) # type: ignore
unknown = key_set - allowed_keys # type: ignore