Repository navigation
Closed
Labels
Description
impl(dashboard): slice 3 — pluggable pages (DNS register first), comments everywhere, agent/session identity registry
Owner direction (Drew, 2026-10-25). Builds on slice 2 (#898) — start after #898 merges. The dashboard's primary purpose stays project management, but it also becomes our general operational dashboard. Three workstreams:
1. Pluggable pages + home-page dropdown
- The home page gets a page dropdown/select: pages are registered entries, not hard-coded routes.
- Adding a page should be quick: a small module + one manifest entry (title, route, data source). Document the recipe in the repo README so a new page is a ~30-minute job.
- First page: the DNS/domain register (from impl(dns-registry): recurring DNS backup job, renewal/cost tracking, dashboard view of the domain register #902): renders the register (renewal-sorted; next-renewal, completely-unused, and unused-but-earmarked views; per-domain cost/renewal/plan/review flag). Source of truth stays the register file produced by impl(dns-registry): recurring DNS backup job, renewal/cost tracking, dashboard view of the domain register #902's backup job — the page renders it, never edits it. This issue owns the view; impl(dns-registry): recurring DNS backup job, renewal/cost tracking, dashboard view of the domain register #902 owns the data pipeline. Coordinate the format with impl(dns-registry): recurring DNS backup job, renewal/cost tracking, dashboard view of the domain register #902.
2. Comments on everything, with clear authorship
Comment threads attach to: needs-Drew items, needs-orchestrator items, roadmap/project items, GitHub-backed tasks, and dashboard objects generally. Requirements:
- Drew can comment on any of the above.
- Two comment kinds, visibly distinct: (a) message to Muse/orchestrator — triaged by the orchestrator on its next pass (may create work); (b) plain note — no trigger; read when the task/project is next picked up. Drew picks the kind when posting (default: note).
- GitHub-backed items (a single GitHub issue, or a dashboard item that compiles several issues) additionally offer post as GitHub comment, with the target issue explicit before posting. Posting uses the fleet's normal GitHub auth; the comment is attributed as the fleet account and notes it was written by Drew via the dashboard.
- Agents can comment too, and authorship is unambiguous: every comment carries an author identity —
drew,muse, or an agent identity from workstream 3 (display name + session link). No anonymous comments. - Storage: one comments store keyed by a stable object ref (the same RefKey scheme as the orchestration feed), so comments survive feed republishes. The orchestrator consumes kind-(a) comments as queue input.
3. Agent/session identity + lightweight session registry
Loose v1 — improve over time; do NOT block workstreams 1–2 on a perfect registry.
- Every agent/session gets a stable ID and a human display name at start: OpenCode sessions, Muse, Jules runs, fleet cron runs, subagents. Assignment points: the fleet init job and agent launch.
- Provide an OpenCode tool that auto-injects the caller's session ID (and parent session ID) so work products, comments, and dispatches can carry it without the agent remembering.
- A collector extracts session records — id, parent, source (OpenCode sandbox/laptop, Muse, Jules), start/last-seen, status, token usage where available — into a database the aggregator can query, enabling loose task ↔ session ↔ token linkage: given a task, which sessions worked it and roughly what they cost; given a session, what it was working on.
- Dashboard session views (from impl(aggregator): slice 2 — mobile, needs-Drew/needs-orchestrator tiers, time-granular roadmap, session clarity #898) consume this registry for their labels and attribution instead of scraping raw session lists.
Acceptance
- Dropdown on the home page lists pages from a manifest; DNS register page live and rendering impl(dns-registry): recurring DNS backup job, renewal/cost tracking, dashboard view of the domain register #902's register data.
- Drew can post both comment kinds on a needs-Drew item, a roadmap item, and a GitHub-backed item; a kind-(a) comment appears in the orchestrator's next run report as triaged input; a GitHub comment lands on the chosen issue.
- An agent-posted comment renders with its agent identity visibly distinct from Drew's and Muse's.
- Session registry holds records for at least OpenCode (both servers), Muse, and Jules sessions with parent links and token totals where the source reports them; a dashboard item shows its linked sessions.
Constraints: existing fleet rules — plan quotas only for any build sessions, measurement gate, no public route for the dashboard (tailnet + MagicDNS links only).
Activity
developing-today commentedon Oct 25, 2026
CODE-148
aggregator slice 3 (#906): pages, DNS + sessions views, comments UI +…
aggregator slice 3 (#906): OpenCode identity tool, tests, docs
aggregator slice 3 (#906): treefmt formatting (biome + prettier)
Merge pull request #920 from developing-today/dashboard-slice3
dezren39 commentedon Oct 25, 2026
Slice 3 (#906) is live: pluggable pages + DNS register, dashboard comments, and the session identity registry are deployed on the dashboard. Acceptance demo comment, posted from the dashboard comment flow.
dezren39 commentedon Oct 25, 2026
Slice 3 is complete and live. PR #920 merged (merge commit
12620917), deployed to the laptop aggregator, and verified end-to-end. Closing with the full results.§1 Pluggable pages — DNS register first
src/pages.ts(PAGES): the nav bar, the new Pages ▾ home-page dropdown, and/pagesall render from it. Adding a page = manifest entry + render function + route branch (+/api/*.jsontwin); the recipe is in the aggregator README. The slice-2 seam held — no restructuring./dns+/api/dns.json: the impl(dns-registry): recurring DNS backup job, renewal/cost tracking, dashboard view of the domain register #902 register is parsed collector-side (src/dns.ts, keyed on the register's table header) into adnsfleet-feed section — no new sync path. Verified live with the real register: 40 domains, next renewal 1110x.de 2027-02-09 ($4.07), portfolio shape 3 in use / 18 unused-but-earmarked / 19 completely unused — the status split is read from the register's own Plan cells and matches its accounting. The page states it renders the register, never edits it.§2 Comments on dashboard items
src/comments.ts, atomic writes), keyed by object ref so threads survive republishes:gh:<owner/repo#N>,orch:<tierItem.id>,session:<id>, board ids, roadmap subjects.drew/muse/ a registry agent identity; authorless posts are refused (400, tested + live).note(read on pickup, triggers nothing),message(message to Muse,triageStateuntil consumed),github(requires an explicitgithubReftarget at post time;githubStatepending → posted/failed, outcome + URL recorded). Threads + forms on item pages (merged across the item's subject and its linkedgh:refs),/discuss/<ref>for any object, 💬 badges on board/roadmap/session/tier cards.GET /api/comments.json?kind=message&state=newand?kind=github&state=new, triages into its normal flow (posts github-kind viaghand reports back throughPOST /api/comments/github-result), then marks consumed viaPOST /api/comments/triage { ids }. Notes are never polled — read on pickup via?object=<ref>.dc-mvoee41p-1rr63t), a drew message (dc-mvoee41v-23io1f— intentionally leftstate=newin the orchestrator's queue as its first real input), and a github-kind comment (dc-mvoee421-3m7poo) that was posted for real — impl(dashboard): slice 3 — pluggable pages (DNS register first), comments everywhere, agent/session identity registry #906 (comment) — and marked posted via the API. Pending counts verified: messages 1, github 0.§3 Agent/session identity registry
src/registry.tsnormalizes all sources into durable records (file store, max-token merge so cumulative totals never regress): OpenCode laptop (live) + sandbox (feed, per-session tokens read off the server at collection time), Jules (keeper state), Muse (launch records)./sessions+/api/registry.jsonverified live: 104 records · 4,238,270 tokens at check time, grouped by source, with agent identities (OpenCode · main (laptop)), parents, task refs.scripts/record-claude-launch.tsappends a JSONL record at spawn; the collector carries it. This build's own session is in the registry asclaude-2026-10-25-slice3-build(status completed, ref'd to this issue). Remaining gap, stated on the page + coverage note: a Muse session that never writes a launch record is invisible — the runtime exposes no session list to scrape.opencode-tools/session-identity.ts(shipped by install.sh): a session reports its own{ sessionId, parentId, agent, directory }. Installed to~/.config/opencode/tool/on both hosts; it becomes callable at each OpenCode server's next restart (not restarted as part of this deploy — restarts are a quiet-moment operation).Verification
tscclean, biome/prettier clean, PR checks green (treefmt, flake evaluation, CodeRabbit)./,/today,/attention,/roadmap,/quota,/dns,/sessions,/pages,/discuss/<ref>,/api/dns.json,/api/registry.json,/api/comments.json,/api/orchestration.json.agg-evidence/slice3-2026-10-25/{dns,sessions}-390.pngin the fleet goal workspace — both stack cleanly, tables scroll inside their wrappers.~/git/pm-feed(updated to the merge commit): feed now carriesdns 40 domains, registry 58 records. Note the collector timer is still inactive post-recycle — that's fix(pm-stack): fleet-feed-collector units do not survive a sandbox recycle #903's scope, not fixed here; the feed will need its ~5-min pushes restored there.