Skip to content

impl(dashboard): slice 3 — pluggable pages (DNS register first), comments everywhere, agent/session identity registry #906

Closed

Description

@dezren39

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

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

  1. developing-today commented on Oct 25, 2026

    @developing-today
    Contributor
  2. added 3 commits that reference this issue on Oct 25, 2026
  3. added a commit that references this issue on Oct 25, 2026
  4. dezren39 commented on Oct 25, 2026

    @dezren39
    MemberAuthor

    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.

  5. dezren39 commented on Oct 25, 2026

    @dezren39
    MemberAuthor

    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

    • Page manifest in src/pages.ts (PAGES): the nav bar, the new Pages ▾ home-page dropdown, and /pages all render from it. Adding a page = manifest entry + render function + route branch (+ /api/*.json twin); 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 a dns fleet-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.
    • One counting note (also left on impl(dns-registry): recurring DNS backup job, renewal/cost tracking, dashboard view of the domain register #902): the dashboard total is the sum over all 40 register rows, $606.70/yr — the register's own $595.62 headline covers the main Porkbun account's 39; drewrypope.com ($11.08, the second account) is the difference. Both numbers are right; they count different sets.

    §2 Comments on dashboard items

    • Store: aggregator-local JSON (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.
    • Unambiguous authorship: every comment carries drew / muse / a registry agent identity; authorless posts are refused (400, tested + live).
    • Kinds, visually distinct: note (read on pickup, triggers nothing), message (message to Muse, triageState until consumed), github (requires an explicit githubRef target at post time; githubState pending → posted/failed, outcome + URL recorded). Threads + forms on item pages (merged across the item's subject and its linked gh: refs), /discuss/<ref> for any object, 💬 badges on board/roadmap/session/tier cards.
    • Orchestrator consumption contract (also commented on impl(orchestrator): recurring orchestration job — queue triage, priority ladder, blocker awareness, goal measurement #899): each pass polls GET /api/comments.json?kind=message&state=new and ?kind=github&state=new, triages into its normal flow (posts github-kind via gh and reports back through POST /api/comments/github-result), then marks consumed via POST /api/comments/triage { ids }. Notes are never polled — read on pickup via ?object=<ref>.
    • Acceptance demo, live on this issue: a drew note (dc-mvoee41p-1rr63t), a drew message (dc-mvoee41v-23io1f — intentionally left state=new in 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.ts normalizes 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.json verified live: 104 records · 4,238,270 tokens at check time, grouped by source, with agent identities (OpenCode · main (laptop)), parents, task refs.
    • Muse v1 = launch records: scripts/record-claude-launch.ts appends a JSONL record at spawn; the collector carries it. This build's own session is in the registry as claude-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 tool 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

    • 82 tests (63 existing + 19 new: register parser/classification, registry normalization/merge, comment store lifecycle + validation, manifest, renders, the identity tool, full HTTP flows), tsc clean, biome/prettier clean, PR checks green (treefmt, flake evaluation, CodeRabbit).
    • Every new/changed route returns 200 on laptop loopback and the tailnet bind: /, /today, /attention, /roadmap, /quota, /dns, /sessions, /pages, /discuss/<ref>, /api/dns.json, /api/registry.json, /api/comments.json, /api/orchestration.json.
    • Phone-width (390px) renders captured: agg-evidence/slice3-2026-10-25/{dns,sessions}-390.png in the fleet goal workspace — both stack cleanly, tables scroll inside their wrappers.
    • Collector run live from ~/git/pm-feed (updated to the merge commit): feed now carries dns 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions