feat(#986): dedicated logs page with build/agent/system sub-tabs

Add /logs.html as a standalone page (same back-link pattern as flow.html):
- BUILD tab: all-agents build log history via new GET /api/build-logs endpoint
- AGENT tab: per-container journald viewer with agent selector + unit filter
- SYSTEM tab: host-side hive-c0re.service logs via new GET /api/journal-host endpoint

Remove inline log drill-ins from SW4RM container rows (buildJournalTrigger
and buildBuildLogsTrigger) — log viewing now lives on the dedicated page.

flow.html: strip the full dashboard tabbar, replace with a simple back link
matching the new logs page chrome.

index.html: add L0GS tab link to /logs.html in the tab strip.

Backend additions:
- build_logs::list_recent_all — cross-agent query (newest first, cap 100)
- GET /api/build-logs — all-agents variant backed by list_recent_all
- GET /api/journal-host — host journald (no -M container flag), restricted
  to allow-listed units (hive-c0re.service)
This commit is contained in:
iris 2026-06-01 19:11:47 +02:00
commit 0b15cad93f
9 changed files with 534 additions and 299 deletions

View file

@ -2,11 +2,14 @@
//
// dist/index.html served by the Rust router at GET /
// dist/flow.html served at GET /flow.html
// dist/logs.html served at GET /logs.html
// dist/static/tabs.js /index.html entry — tab renderers +
// tab routing + refreshState
// dist/static/flow.js /flow.html entry — broker terminal +
// operator inbox + @-mention composer
// dist/static/{tabs,flow}.js.map source map siblings
// dist/static/logs.js /logs.html entry — build/agent/system
// log viewer sub-tabs
// dist/static/{tabs,flow,logs}.js.map source map siblings
// dist/static/dashboard.css served at /static/dashboard.css
// (@import resolved from @hive/shared)
//
@ -35,7 +38,7 @@ mkdirSync(staticDir(''), { recursive: true });
// follow-up once asset sizes warrant it). esbuild writes each entry
// to `static/<name>.js` based on the entryPoint basename.
await build({
entryPoints: [src('tabs.js'), src('flow.js')],
entryPoints: [src('tabs.js'), src('flow.js'), src('logs.js')],
outdir: staticDir(''),
bundle: true,
format: 'esm',
@ -78,7 +81,7 @@ await build({
logLevel: 'info',
});
for (const html of ['index.html', 'flow.html']) {
for (const html of ['index.html', 'flow.html', 'logs.html']) {
copyFileSync(src(html), dist(html));
}