dashboard: 3-column layout — swarm / 0per4t0r 1n / m3ss4g3s

regroups the 7 stacked sections into three semantic columns
backed by a CSS grid (single column under 1400px, 3 columns
above). column headers are sticky so vertical scrolling
inside a column doesn't lose context.

- SW4RM (left, slightly wider): containers + kept-state +
  spawn-agent form + meta-input update form. all
  swarm-mutating operator knobs live here.
- 0PER4T0R 1N (middle): mind-questions + pending approvals.
  the two things waiting on operator action.
- M3SS4G3S (right): operator-inbox + msg-flow tail + the
  @-mention compose box. broker traffic in one place.

spawn form moves out of renderApprovals into static HTML
under sw4rm; renderApprovals no longer injects it.

cosmetic: per-section h2/divider replaced with smaller cyan
sub-heads + a dashed underline so each column reads as one
cohesive unit instead of seven competing banners. body
max-width grows 70em → 110em to actually use the new
horizontal real estate.
This commit is contained in:
müde 2026-05-16 03:47:16 +02:00
parent 266c2c7a77
commit 74ba8a63e1
3 changed files with 112 additions and 60 deletions

View file

@ -17,53 +17,83 @@
<span id="notif-status" class="meta" hidden></span>
</div>
<h2>◆ C0NTAINERS ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<div id="containers-section">
<p class="meta">loading…</p>
</div>
<div class="columns">
<!-- ── SW4RM ─────────────────────────────────────────────────
Live + dormant agents, plus the operator-driven knobs that
change the swarm itself: spawn-new-agent form, meta flake
input bumps.
───────────────────────────────────────────────────────────── -->
<section class="dash-col" aria-labelledby="col-swarm">
<h2 id="col-swarm" class="col-head">◆ SW4RM ◆</h2>
<h2>◆ K3PT ST4T3 ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<div id="tombstones-section">
<p class="meta">loading…</p>
</div>
<h3 class="sub-head">containers</h3>
<div id="containers-section">
<p class="meta">loading…</p>
</div>
<h2>◆ M1ND H4S QU3STI0NS ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<div id="questions-section">
<p class="meta">loading…</p>
</div>
<h3 class="sub-head">kept state</h3>
<div id="tombstones-section">
<p class="meta">loading…</p>
</div>
<h2>◆ 0PER4T0R 1NB0X ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<div id="inbox-section">
<p class="meta">loading…</p>
</div>
<h3 class="sub-head">spawn agent</h3>
<form method="POST" action="/request-spawn" class="spawnform" data-async>
<input name="name"
placeholder="new agent name (≤9 chars)"
maxlength="9" required autocomplete="off">
<button type="submit" class="btn btn-spawn">◆ R3QU3ST SP4WN</button>
</form>
<h2>◆ P3NDING APPR0VALS ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<div id="approvals-section">
<p class="meta">loading…</p>
</div>
<h3 class="sub-head">update meta inputs</h3>
<p class="meta">checkbox per input; submitting runs <code>nix flake update</code> in <code>/meta/</code> and rebuilds affected agents (sequentially).</p>
<div id="meta-inputs-section">
<p class="meta">loading…</p>
</div>
</section>
<h2>◆ M3T4 1NPUTS ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p class="meta">select inputs to <code>nix flake update</code> in <code>/meta/</code>. selected agents rebuild in sequence after the lock bump; manager learns each outcome via the usual <code>rebuilt</code> system event.</p>
<div id="meta-inputs-section">
<p class="meta">loading…</p>
</div>
<!-- ── 0PER4T0R 1N ───────────────────────────────────────────
Things waiting on the operator to decide — questions the
manager surfaced via ask_operator and config-change
proposals from the manager's request_apply_commit / spawn.
───────────────────────────────────────────────────────────── -->
<section class="dash-col" aria-labelledby="col-operator-in">
<h2 id="col-operator-in" class="col-head">◆ 0PER4T0R 1N ◆</h2>
<h2>◆ MESS4GE FL0W ◆</h2>
<div class="divider">══════════════════════════════════════════════════════════════</div>
<p class="meta">live tail — newest at the top. tap on every <code>send</code> / <code>recv</code> through the broker. compose below: <code>@name</code> picks the recipient (sticky until you @ someone else); <code>tab</code> completes.</p>
<div id="msgflow" class="msgflow"><span class="meta">connecting…</span></div>
<div id="op-compose" class="op-compose">
<span id="op-compose-prompt" class="op-compose-prompt">@—&gt;</span>
<textarea id="op-compose-input" class="op-compose-input"
placeholder="@agent message… (enter sends, shift+enter newline, tab completes @-mention)"
rows="1" autocomplete="off"></textarea>
<div id="op-compose-suggest" class="op-compose-suggest" hidden></div>
<h3 class="sub-head">m1nd has questions</h3>
<div id="questions-section">
<p class="meta">loading…</p>
</div>
<h3 class="sub-head">pending approvals</h3>
<div id="approvals-section">
<p class="meta">loading…</p>
</div>
</section>
<!-- ── M3SS4G3S ──────────────────────────────────────────────
Broker traffic: the operator's inbox (messages addressed
to `operator`) and the live message flow tail. Compose
box at the bottom — @name picks the recipient, sticky.
───────────────────────────────────────────────────────────── -->
<section class="dash-col" aria-labelledby="col-messages">
<h2 id="col-messages" class="col-head">◆ M3SS4G3S ◆</h2>
<h3 class="sub-head">operator inbox</h3>
<div id="inbox-section">
<p class="meta">loading…</p>
</div>
<h3 class="sub-head">message flow</h3>
<p class="meta">live tail — newest at the top; each row is one broker event. compose below: <code>@name</code> picks the recipient (sticky until you @ someone else); <code>tab</code> completes.</p>
<div id="msgflow" class="msgflow"><span class="meta">connecting…</span></div>
<div id="op-compose" class="op-compose">
<span id="op-compose-prompt" class="op-compose-prompt">@—&gt;</span>
<textarea id="op-compose-input" class="op-compose-input"
placeholder="@agent message… (enter sends, shift+enter newline, tab completes @-mention)"
rows="1" autocomplete="off"></textarea>
<div id="op-compose-suggest" class="op-compose-suggest" hidden></div>
</div>
</section>
</div>
<footer>