CI (prd-number-check) rejects unnumbered prd-new-*.md on merge to main.
Rename docs/prds/prd-new-trusted-agent-forge-identity.md to
0082-trusted-agent-forge-identity.md (0081 is claimed by #517/#519) and
update the in-repo 'PRD prd-new-trusted-agent-forge-identity' citations to
'PRD 0082'.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Implements PRD prd-new-trusted-agent-forge-identity. Moves author identity
and named forge configurations onto the trusted, host-only agent definition,
and lets a bottle repository optionally associate a git-gate repo with one of
the agent's forge aliases.
- Agent-owned identity: new `author` (name/email) and `forge-accounts`
(alias -> canonical Gitea /api/v1 origin + host `token_secret` ref) on the
agent manifest. `author` populates the bottle's git user.name/user.email.
- Remove `git-gate.user` from both agents and bottles; fail with a migration
pointer to `author`. `git-gate` is no longer accepted on an agent.
- Bottle git-gate repos gain optional `forge: <alias>`, resolved against the
selected agent's forge-accounts at composition (fail-closed on unknown).
- Fail-closed Gitea API URL validation (https, no userinfo/query/fragment,
/api/v1 base, host lowercased, trailing slash normalized, host dedup).
- Proxy-held credential: synthesize one inspected, token-authenticated egress
route per referenced forge alias, scoped to the origin + API prefix. The
token is resolved from the host env at launch into the egress proxy only —
never the bottle env, prompt, gitconfig, or workspace.
- Generated, non-secret forge workflow guidance appended to the agent prompt
for associated repos (API base, branch-backed PR flow, AGit-ref prohibition,
mutation verification); omitted when no repo declares a forge.
- Agents become home-only: cwd `.bot-bottle/agents` no longer contributes,
overrides, or is selectable; warned-and-ignored like cwd bottles.
- Docs: README examples, PRD 0011 supersession note, manifest schema docstring.
- Tests: new test_forge_identity suite; legacy git-gate.user/cwd tests updated
to the agent-owned identity model.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
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>
Per-bottle `git config --global user.name` / `user.email` pair
so the agent's commits inside the bottle land with a known
identity rather than the agent image's default (no user, or
whatever the image dropped in).
Schema:
git_user:
name: "Eric Bauerfeld"
email: "eric+claude@dideric.is"
Either field can be set independently — name-only / email-only
configs are valid and apply just the field that's set. An
explicit `git_user:` block with both fields empty dies at parse
time rather than silently no-op'ing; an omitted block is the
no-op path (default GitUser is empty, provisioner skips).
Parse-time validation:
- Unknown sub-keys die (e.g., typo of `username`).
- Non-string name/email dies.
- Both-empty dies (half-finished edit hint).
11 unit tests in `test_manifest_git_user.py`; 653 unit tests pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>