diff --git a/docs/prds/0025-bottle-extends.md b/docs/prds/0025-bottle-extends.md index ad19db4..413d1dd 100644 --- a/docs/prds/0025-bottle-extends.md +++ b/docs/prds/0025-bottle-extends.md @@ -39,6 +39,41 @@ trust boundary*: only `$HOME` bottles can declare it, only `$HOME` bottles can be its target. Cloned repos still cannot author bottle-equivalent config. +## Alternatives considered + +The question raised in issue #88 was *where composition should live*. +Three points in that design space, recorded here so the decision +stands on its own without the issue thread: + +1. **Duplicate bottles (status quo).** Copy `dev.md` to `staging.md` + and edit. Zero new mechanism, but every shared field drifts: a + route added to `dev` is silently missing from `staging`. This is + the pain that prompted #88. + +2. **Agent-side `bottle_config:` override (the original #88 + proposal).** Let an agent file carry an inline block that merges + over its referenced bottle. Ergonomically attractive — one file, + no second bottle — but it **breaks the trust boundary**: agent + files can come from `$CWD/.bot-bottle/agents/` in a cloned repo, so + a clone could redeclare egress routes, env mappings, and git + remotes — i.e. grant itself bottle-equivalent authority over + credentials and network egress. The home-only-bottle invariant + exists precisely to stop this. + +3. **Bottle-side `extends:` (chosen).** Move composition to the + bottle layer, where it inherits the home-only property for free: + only `$HOME` bottles can declare `extends:`, and only `$HOME` + bottles can be its target. Identical duplication relief to option + 2, none of its trust erosion. The cost is that an override requires + a (home-owned) child bottle rather than an inline agent block — + which is the *point*: the override authority stays in `$HOME`. + +`extends:` wins because it solves the duplication pain entirely on the +trusted side of the agent-vs-bottle boundary. (PRD 0027 later lifts a +deliberately narrow, non-credential field — `git.user` — to the agent +layer, on the separate reasoning that commit identity is not a +capability; egress, credentials, and remotes stay bottle-only.) + ## Goals / Success Criteria - Add `extends: ` to the bottle frontmatter schema. @@ -58,9 +93,9 @@ bottle-equivalent config. ## Non-goals -- **No agent-side `bottle_config:`.** That's the design issue #88 - considered and weighed against; this PRD is the alternative - picked in the issue's design discussion. Don't reintroduce it. +- **No agent-side `bottle_config:`.** Option 2 under "Alternatives + considered" — weighed and rejected on trust grounds. Don't + reintroduce it. - **No additive list merges** (e.g., `routes: append` keyword). The `extends:` design uses full-replace for list-valued fields (see "Merge rules"); if a use case shows up that genuinely @@ -167,7 +202,7 @@ Bottles continue to be loaded from `$HOME/.bot-bottle/bottles/` only (`Manifest.from_md_dirs` is unchanged). The `extends:` field references another file in that same directory. No cwd-readable file gains the ability to declare or modify bottle config — the -attack surface from issue #88's comment thread stays closed. +attack surface from option 2 ("Alternatives considered") stays closed. If a future change ever introduces cwd-loaded bottles, the `extends:` resolver should be gated to forbid a `$CWD` bottle