feat(cli): add bridge conventions and link from actor errors

Surfaces the actor naming rules (adm-/agt-/atm- prefixes, legacy class
aliases) so users hitting a ConfigError have an in-CLI way to read the
spec without grepping the wiki.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-16 23:21:37 +02:00
parent 28ecef121e
commit de984736ca
2 changed files with 36 additions and 2 deletions

View File

@@ -633,3 +633,35 @@ def catalog_show(
if b.target in cat.targets:
t = cat.targets[b.target]
typer.echo(f"Target: {t.description or t.id} ({t.kind})")
_CONVENTIONS_TEXT = """\
Actor Naming Conventions (from AccessManagementDirective.md §2)
Every actor declared under `actors:` in ~/.config/bridge/tunnels.yaml must have
a `class` field, and the actor name must start with the class-specific prefix:
class prefix purpose
----- ------ ------------------------------------------------------------
adm adm- Human operator (interactive shell when needed)
agt agt- LLM-powered autonomous agent (Claude Code, etc.)
atm atm- Deterministic script / cron job / pipeline
Legacy class aliases (deprecated, still accepted with a warning):
human -> adm
automation -> atm
Examples:
adm-bernd: { class: adm, description: Bernd Worsch }
agt-claude-coulombcore: { class: agt, description: Claude Code on CoulombCore }
atm-backup-daily: { class: atm, description: Nightly DB backup }
Full specification:
<ops-bridge repo>/wiki/AccessManagementDirective.md
"""
@app.command()
def conventions():
"""Show the actor naming conventions enforced by tunnels.yaml."""
typer.echo(_CONVENTIONS_TEXT)

View File

@@ -137,7 +137,8 @@ def _parse_actor_type(name: str, raw_class: str) -> ActorType:
except ValueError:
raise ConfigError(
f"Actor '{name}' has unknown class '{raw_class}'; "
f"must be one of: adm, agt, atm (or legacy: human, automation)"
f"must be one of: adm, agt, atm (or legacy: human, automation). "
f"Run `bridge conventions` for the full naming rules."
)
@@ -153,7 +154,8 @@ def _parse_actors(raw: dict) -> Dict[str, ActorInfo]:
if not name.startswith(required_prefix):
raise ConfigError(
f"Actor '{name}' has type '{actor_type.value}' but name must start "
f"with '{required_prefix}' (got '{name}')"
f"with '{required_prefix}' (got '{name}'). "
f"Run `bridge conventions` for the full naming rules."
)
actors[name] = ActorInfo(
name=name,