refactor(manifest): split Manifest into ManifestIndex + Manifest single-value type
lint / lint (push) Failing after 1m42s
test / unit (pull_request) Successful in 35s
test / integration (pull_request) Successful in 18s

Manifest now holds exactly one agent and one effective bottle (with
git_user overlay already applied). The old multi-agent/bottle
collection is renamed ManifestIndex. BottleSpec.manifest starts as
ManifestIndex from the CLI and becomes Manifest after _validate()
calls load_for_agent(); all provisioning code downstream reads
spec.manifest.agent / spec.manifest.bottle instead of indexing by name.
This commit is contained in:
2026-06-23 00:56:30 +00:00
parent cd93fc71f7
commit fa0a5fbb9c
41 changed files with 330 additions and 308 deletions
+5 -5
View File
@@ -5,7 +5,7 @@ from __future__ import annotations
import argparse
from ..log import info
from ..manifest import Manifest
from ..manifest import ManifestIndex
from ._common import PROG, USER_CWD
@@ -14,12 +14,12 @@ def cmd_info(argv: list[str]) -> int:
parser.add_argument("name", help="agent name defined in bot-bottle.json")
args = parser.parse_args(argv)
names = Manifest.resolve(USER_CWD)
names = ManifestIndex.resolve(USER_CWD)
names.require_agent(args.name)
manifest = names.load_for_agent(args.name)
agent = manifest.agents[args.name]
bottle = manifest.bottle_for(args.name)
agent = manifest.agent
bottle = manifest.bottle
env_names = list(bottle.env.keys())
prompt_first_line = agent.prompt.splitlines()[0] if agent.prompt else ""
@@ -32,7 +32,7 @@ def cmd_info(argv: list[str]) -> int:
f"first line: {prompt_first_line or '(empty)'}"
)
info(f"bottle : {agent.bottle}")
identity = manifest.git_identity_summary(args.name)
identity = manifest.git_identity_summary()
if identity:
info(f" git identity : {identity}")
if bottle.git:
+2 -2
View File
@@ -7,7 +7,7 @@ import os
import sys
from ..backend import enumerate_active_agents
from ..manifest import Manifest
from ..manifest import ManifestIndex
from ._common import PROG, USER_CWD
_ANSI_COLOR_CODES: dict[str, str] = {
@@ -40,7 +40,7 @@ def cmd_list(argv: list[str]) -> int:
args = parser.parse_args(argv)
if args.scope == "available":
manifest = Manifest.resolve(USER_CWD)
manifest = ManifestIndex.resolve(USER_CWD)
for name in manifest.all_agent_names:
print(name)
return 0
+2 -2
View File
@@ -20,7 +20,7 @@ import argparse
from ..backend import BottleSpec
from ..bottle_state import read_metadata
from ..log import die
from ..manifest import Manifest
from ..manifest import ManifestIndex
from ._common import PROG, USER_CWD
from .start import _launch_bottle
@@ -42,7 +42,7 @@ def cmd_resume(argv: list[str]) -> int:
f"check ~/.bot-bottle/state/ or run `cli.py start` to create a new bottle"
)
manifest = Manifest.resolve(USER_CWD)
manifest = ManifestIndex.resolve(USER_CWD)
manifest.require_agent(metadata.agent_name)
spec = BottleSpec(
+2 -2
View File
@@ -33,7 +33,7 @@ from ..bottle_state import (
)
# from ..backend.docker.capability_apply import snapshot_transcript
from ..log import info
from ..manifest import Manifest
from ..manifest import ManifestIndex
from ._common import PROG, USER_CWD, read_tty_line
from . import tui
@@ -62,7 +62,7 @@ def cmd_start(argv: list[str]) -> int:
dry_run = args.dry_run or os.environ.get("BOT_BOTTLE_DRY_RUN") == "1"
manifest = Manifest.resolve(USER_CWD)
manifest = ManifestIndex.resolve(USER_CWD)
agent_name: str | None = args.name
if agent_name is None: