Implements the manifest surface for the signed-commits & audit-attribution
PRD (#423, PR #480): a bottle opts into per-activation commit signing with
git-gate:
signing:
enabled: true
- New ManifestGitSigning value type (frozen, enabled: bool = False) parsed
under git-gate.signing; unknown sub-keys and non-bool `enabled` die with
targeted errors. parse_git_gate_config now returns (repos, user, signing).
- ManifestBottle gains git_signing; defaults to off, so bottles that omit
the block are unchanged.
- Bottle-only: git-gate.signing on an agent is rejected by the existing
agent-level non-`user` guard (like git-gate.repos).
- extends/runtime merges thread git_signing with an enable-wins overlay
(a child enabling signing wins; omitting inherits the parent), mirroring
the git_user non-empty-wins overlay.
- Facade exports ManifestGitSigning.
Tests: tests/unit/test_manifest_git_signing.py (parse, validation,
agent-level rejection, extends overlay). Full unit suite green.
This is the first stacked chunk; signing pipeline, gate signature check,
and control-plane verification + audit tables follow per the PRD.
Issue: #423
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>