Commit Graph

5 Commits

Author SHA1 Message Date
didericis-claude 4cf2cfc55d test: update test suite for git-gate manifest redesign (PRD 0047)
- fixtures.py: fixture_with_git_dict uses git-gate.repos + url/identity/host_key
- test_manifest_git: rewrite to use git-gate.repos; replace duplicate-name
  test (names = dict keys, always unique) with two-repos-different-hosts test
- test_manifest_git_user: _manifest → git-gate.user; update error message assertions
- test_manifest_agent_git_user: git → git-gate throughout; repos rejection test
- test_manifest_extends: git.remotes/git.user → git-gate.repos/git-gate.user
- test_provision_git: IP test updated — no host alias, single insteadOf
- test_compose: git.remotes → git-gate.repos + new field names
- test_docker_provision_git_user: git.user → git-gate.user
- test_git_gate: inline manifest dict updated to git-gate.repos
- test_smolmachines_provision: git_json → git_gate_json; remove _remote_host
2026-06-02 23:59:34 -04:00
didericis-claude 847baa84be refactor(manifest): raise ManifestError instead of die()
test / unit (pull_request) Successful in 36s
test / integration (pull_request) Successful in 59s
Review feedback on #102: a manifest that can't be read should raise an
exception, not call die() (a SystemExit). That SystemExit was the whole
reason the dashboard had to special-case Die.

manifest.py now raises ManifestError (a plain Exception) for every
validation failure. The CLI dispatcher catches it and prints+exits 1
(same UX as before); the dashboard catches it with a normal
`except ManifestError` and degrades to a status-line warning. Manifest
tests assert on ManifestError + its message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 00:15:15 -04:00
didericis-codex c08b09dc9f refactor!: rename project to bot-bottle
Assisted-by: Codex
2026-05-28 17:56:14 -04:00
didericis-codex 59ee32cc8d refactor(manifest): key git config by host
test / unit (pull_request) Successful in 33s
test / integration (pull_request) Successful in 42s
2026-05-28 00:49:34 -04:00
didericis-claude a5c8b4e7b2 feat(manifest): bottle composition via \extends:\ resolver (PRD 0025, #88)
test / unit (pull_request) Successful in 27s
test / integration (pull_request) Successful in 39s
Add an optional `extends: <bottle-name>` field to bottle
frontmatter. Two-pass load:

  1. Collect raw frontmatter for every bottle file.
  2. Recursively resolve each name into a merged Bottle via
     `_resolve_one_bottle` + `_merge_bottles`.

Merge rules (per PRD 0025):

- env: dict merge, child wins on key collision
- git: full replace if child declares `git:`
- git_user: per-field overlay (child's non-empty fields win)
- egress: full replace if child declares `egress:`
- supervise: full replace if child declares `supervise:`

List-valued fields full-replace because partial merge is
ambiguous (ordering matters, name collisions ambiguous); env is
dict-merge because dict-keyed override is the natural shape.
git_user overlays per-field so a parent can declare just the
name and a child can add just the email.

Cycles / self-extends / missing-parent / non-string `extends:`
all die at parse with a pointer that includes the chain (cycles)
or the available names (missing parent). Resolution is cached
per-name so a diamond reference graph doesn't reparse the same
parent N times.

Both load paths threaded:
- `_load_bottles_from_dir` (md files) — collect raws, then
  resolve.
- `Manifest.from_json_obj` (JSON / test fixtures) — same.

Tests (24, in `test_manifest_extends.py`):
- Leaf without extends parses unchanged
- Child inherits parent unchanged when child only declares
  `extends:`
- env: disjoint union, collision (child wins), child-omits
- git: replace, omit, explicit-empty-clears-parent
- egress: same shape (replace, inherit)
- git_user: parent-only, child-overrides-both, partial fields
- 3-step chain (grandparent → parent → child)
- Errors: missing parent, self-extends, 2-node cycle, 3-node
  cycle, non-string extends

685 unit tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-27 23:30:40 -04:00