Fix/pod public html bind mount (#30)

* feat(pods/admin): root admin alias, default-caps cleanup, pod rebuild script

- auth: add `root` as an admin-console route alias (alongside admin/sysop);
  still gated by $AGENTBBS_ADMINS — the name confers nothing on its own.
- pods: drop the now-redundant tuneApt apt-sandbox hack. Rootless podman keeps
  its default capability set, so apt/chown/su work without disabling the
  download sandbox.
- scripts/rebuild-pods.sh: recreate all member pods (keeps home volumes) so
  they pick up the current container profile on next `ssh pod@`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(arcade,ui): 80s arcade classics + shared menu theme

Arcade games (PRD §5.1), generalizing the sandboxed-PTY DOOM path into an
external-game registry: Space Invaders (nInvaders), Pac-Man (pacman4console),
Tetris (tint/vitetris), Moon Patrol (moon-buggy). Binaries resolve from
assets/bin, PATH, then /usr/games, so a distro install or a hand-built binary
lights each game up; missing games are skipped with a discovery hint. Installed
on the host via `scripts/fetch-assets.sh --arcade` (apt), wired into setup.sh
behind FETCH_ARCADE (default on).

UI: new shared ui.Theme.MenuItem widget (accent cursor + badge, description
shown only for the focused row) adopted by the hub and arcade menus; the hub
groups rows under Features/Sessions headers and the arcade under
DOOM/ARCADE/BUILT-IN.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-06-15 08:06:32 -07:00 committed by GitHub
parent 362b47fdde
commit e0a267e343
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 539 additions and 138 deletions

View file

@ -18,6 +18,7 @@ import (
"github.com/profullstack/agentbbs/internal/games"
"github.com/profullstack/agentbbs/internal/plugin"
"github.com/profullstack/agentbbs/internal/store"
"github.com/profullstack/agentbbs/internal/ui"
)
// Plugin is the AgentGames hub entry.
@ -52,12 +53,12 @@ const (
)
var (
title = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#4ade80"))
dim = lipgloss.NewStyle().Foreground(lipgloss.Color("241"))
cursor = lipgloss.NewStyle().Foreground(lipgloss.Color("#4ade80"))
head = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#60a5fa"))
warn = lipgloss.NewStyle().Foreground(lipgloss.Color("203"))
frame = lipgloss.NewStyle().Padding(1, 2)
title = lipgloss.NewStyle().Bold(true).Foreground(ui.Green)
dim = ui.Dim
cursor = lipgloss.NewStyle().Bold(true).Foreground(ui.Green)
head = lipgloss.NewStyle().Bold(true).Foreground(ui.Blue)
warn = ui.Danger
frame = ui.Frame
)
var actions = []string{"Ladder", "Replays", "Play vs bot"}
@ -302,7 +303,7 @@ func (m *model) View() string {
case scPlay:
body, help = m.viewPlay()
}
out := title.Render("AgentGames") + "\n\n" + body + "\n" + dim.Render(help)
out := title.Render("AgentGames") + "\n\n" + body + "\n" + ui.KeyBar(help)
if m.note != "" {
out += "\n" + m.note
}
@ -393,7 +394,7 @@ func (m *model) viewPlay() (string, string) {
func (m *model) row(i int) string {
if i == m.cursor {
return cursor.Render("> ")
return cursor.Render(" ")
}
return " "
}