feat(manifest): trusted agent forge identity and guidance
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>
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
"""Manifest dataclasses (PRD 0011 layout).
|
||||
|
||||
Reads the per-file manifest tree:
|
||||
Reads the per-file manifest tree (home-only —
|
||||
PRD prd-new-trusted-agent-forge-identity):
|
||||
|
||||
$HOME/.bot-bottle/bottles/<name>.md — one bottle per file
|
||||
$HOME/.bot-bottle/agents/<name>.md — home-resident agents
|
||||
$CWD/.bot-bottle/agents/<name>.md — cwd-supplied agents
|
||||
$HOME/.bot-bottle/agents/<name>.md — agents
|
||||
|
||||
Each file is Markdown with YAML frontmatter. The frontmatter holds
|
||||
the structured config (see schema below); for agents the body is
|
||||
@@ -15,27 +15,38 @@ Bottle schema (frontmatter):
|
||||
extends: <bottle-name> # optional (PRD 0025)
|
||||
env: { <NAME>: <env-entry>, ... }
|
||||
git-gate: # optional (PRD 0047)
|
||||
user: { name: <str>, email: <str> } # optional
|
||||
repos: { <name>: <git-gate-entry>, ... } # optional
|
||||
# git-gate-entry keys: url, key, host_key, forge
|
||||
# `forge`: optional alias into the selected agent's forge-accounts
|
||||
egress: { routes: [ <egress-route>, ... ] }
|
||||
# route keys: host, matches, auth, role, dlp
|
||||
supervise: <bool> # optional (default true)
|
||||
nested_containers: <bool> # optional (default false)
|
||||
|
||||
Agent schema (frontmatter):
|
||||
bottle: <bottle-name> # required
|
||||
bottle: <bottle-name> # optional
|
||||
skills: [ <skill-name>, ... ] # optional
|
||||
git-gate:
|
||||
user: { name: <str>, email: <str> } # optional; overlays bottle
|
||||
author: # optional; agent git identity
|
||||
name: <str> # required when author is present
|
||||
email: <str> # required when author is present
|
||||
forge-accounts: # optional; alias -> forge account
|
||||
<alias>:
|
||||
url: <https Gitea /api/v1 base>
|
||||
auth: { type: token, token_secret: <host env var name> }
|
||||
# Claude Code subagent passthrough fields — accepted, ignored:
|
||||
name, description, model, color, memory
|
||||
|
||||
`author` populates the bottle's git user.name/user.email; `forge-accounts`
|
||||
maps a forge alias to a Gitea API origin plus a host token reference. Identity
|
||||
is agent-owned — `git-gate` is no longer accepted on an agent (git-gate.user
|
||||
moved to `author`; git-gate.repos is bottle-only).
|
||||
|
||||
The agent file's Markdown body is the system prompt (stripped).
|
||||
Unknown top-level frontmatter keys raise ManifestError with a hint.
|
||||
|
||||
Bottles can ONLY live under $HOME. A bottles/ dir under $CWD is a
|
||||
warn at load time and contributes nothing. The trust boundary is
|
||||
expressed as filesystem layout rather than resolver logic.
|
||||
Both bottles and agents can ONLY live under $HOME. An agents/ or bottles/
|
||||
dir under $CWD is a warn at load time and contributes nothing. The trust
|
||||
boundary is expressed as filesystem layout rather than resolver logic.
|
||||
|
||||
Two types are exported:
|
||||
|
||||
@@ -66,6 +77,11 @@ if TYPE_CHECKING:
|
||||
from .agent import ManifestAgent, ManifestAgentProvider
|
||||
from .bottle import ManifestBottle
|
||||
from .egress import EGRESS_AUTH_SCHEMES, ManifestEgressConfig, ManifestEgressRoute
|
||||
from .forge import (
|
||||
ManifestAuthor,
|
||||
ManifestForgeAccount,
|
||||
ResolvedForgeAssociation,
|
||||
)
|
||||
from .git import ManifestGitEntry, ManifestGitUser, ManifestKeyConfig
|
||||
|
||||
|
||||
@@ -81,6 +97,9 @@ _LAZY_MODULES: dict[str, str] = {
|
||||
"EGRESS_AUTH_SCHEMES": "egress",
|
||||
"ManifestEgressRoute": "egress",
|
||||
"ManifestEgressConfig": "egress",
|
||||
"ManifestAuthor": "forge",
|
||||
"ManifestForgeAccount": "forge",
|
||||
"ResolvedForgeAssociation": "forge",
|
||||
"ManifestGitEntry": "git",
|
||||
"ManifestGitUser": "git",
|
||||
"ManifestKeyConfig": "git",
|
||||
@@ -115,4 +134,7 @@ __all__ = [
|
||||
"EGRESS_AUTH_SCHEMES",
|
||||
"ManifestEgressRoute",
|
||||
"ManifestEgressConfig",
|
||||
"ManifestAuthor",
|
||||
"ManifestForgeAccount",
|
||||
"ResolvedForgeAssociation",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user