MapLibre Native maintainer dashboard for reviewing pull requests
  • TypeScript 66.2%
  • JavaScript 22.3%
  • CSS 11.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Bart Louwers 00c636e39e Track the PR head in Open in Agent worktrees so gh pr commands find the PR
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 09:56:01 +02:00
.agents/skills scaffold Vike app with Bati 2026-10-05 13:48:32 +02:00
.claude scaffold Vike app with Bati 2026-10-05 13:48:32 +02:00
assets scaffold Vike app with Bati 2026-10-05 13:48:32 +02:00
components Hide line numbers in the prompt editor 2026-10-06 14:27:10 +02:00
pages Keep report table columns readable instead of breaking every letter 2026-10-06 14:49:40 +02:00
server Track the PR head in Open in Agent worktrees so gh pr commands find the PR 2026-10-07 09:56:01 +02:00
shared Add a Prompts page for editing the report prompts 2026-10-06 14:21:52 +02:00
tests Add a Prompts page for editing the report prompts 2026-10-06 14:21:52 +02:00
+server.ts scaffold Vike app with Bati 2026-10-05 13:48:32 +02:00
.env.example Replace report generation with a copyable prompt; add Open in Agent 2026-10-06 14:10:36 +02:00
.gitignore Add persistent PR report state and background Codex worker 2026-10-05 14:57:10 +02:00
AGENTS.md Set up Octokit pull request dashboard and project instructions 2026-10-05 14:05:59 +02:00
package.json Add a Prompts page for editing the report prompts 2026-10-06 14:21:52 +02:00
pnpm-lock.yaml Add a Prompts page for editing the report prompts 2026-10-06 14:21:52 +02:00
pnpm-workspace.yaml scaffold Vike app with Bati 2026-10-05 13:48:32 +02:00
README.md Autosave prompt edits instead of a Save button 2026-10-06 14:26:29 +02:00
tsconfig.json Add persistent PR report state and background Codex worker 2026-10-05 14:57:10 +02:00
vite.config.ts Add persistent PR report state and background Codex worker 2026-10-05 14:57:10 +02:00

MapLibre Native Maintainer Dashboard

Setup

  1. Use Node.js 22.18 or newer and run pnpm install.
  2. Copy .env.example to .env and set GITHUB_TOKEN to a GitHub token with read access to pull requests for maplibre/maplibre-native. The token stays on the server; .env is ignored by Git.
  3. Run pnpm dev and open the URL printed by Vike.

Restart the server after changing .env. Production also loads .env from the working directory; an existing environment variable takes precedence.

Review workflow

  • Open / for Next task: the oldest open, non-draft PR targeting main. Workflow failures, pending runs, and approval requirements do not exclude PRs. The task shows workflow and report status, with a link into the dashboard review page. Once the PR is merged or closed, the next oldest becomes the task after the cached list refreshes.
  • Click the page title to return to Next task. The top menu's Pull Requests link opens /pull-requests, showing all open PRs in one compact table. Drafts are hidden by default; use Draft pull requests to show them in grey. The eye icon indicates visibility, and the heading count reflects the visible PRs.
  • The table's default order is newest first. Click Opened, +, or − to sort by date opened, added lines, or deleted lines. Click again to reverse the order. Sorting uses the loaded data without a network request.
  • Click an author to show only their PRs. Click Author: name × beside the heading to clear that filter. It works together with the draft filter and sorting.
  • Author, draft visibility, and sorting are stored in URL query parameters. Back and Forward restore previous views; copying or reloading the URL preserves the selected view.
  • Click a row to open /pull-requests/<number> inside the dashboard, with the description, reports, and annotated changes. Review the PR and decide whether to merge, request changes, or close it on GitHub.
  • Click Open in Agent on the Next task card, in a table row, or in a PR's header to work on the PR in your agent workspace (see below).
  • Use the browser's Back button or Pull Requests in the menu to return to the list.

GitHub cache

Octokit fetches all pages of open PRs through GitHub's GraphQL API, including line counts. A complete snapshot is stored with node:sqlite in .cache/github.sqlite, which is ignored by Git. Set GITHUB_CACHE_PATH to use another location. Keep that file on persistent storage when deploying.

The first visit waits for GitHub to populate the cache. Later visits read SQLite immediately. Data older than one minute triggers a background refresh. The landing page and table check for updates every ten seconds, or every two seconds while a refresh is running or reports are awaited. Concurrent requests share a refresh, and failures retain the last complete snapshot with a one-minute retry delay. Closed and merged PRs disappear after the next successful refresh.

Details use the cached list when possible; direct links to PRs outside that list use a separately cached Octokit request. Credentials and raw API errors are never included in the cached data or browser responses.

Checks

  • pnpm test — cache, GitHub integration, and sorting tests, using mocked GitHub responses.
  • pnpm exec tsc --noEmit — TypeScript checks.
  • pnpm build — production build.
  • pnpm prod — build and start the production server.

PR reports

The dot after each PR number summarizes GitHub Actions workflows on the latest commit: green means passed, solid grey means awaiting approval, and red means failed. Hover for a text label. A hollow grey dot means pending/incomplete or no workflows reported. Failures take precedence when workflows have mixed results. Workflow status shares the SQLite PR cache and refreshes in the background; only the latest run of each workflow/event in MapLibre Native is considered.

Click Pull requests above the table to restore the default view: newest PRs first, drafts hidden, and no author filter. The Reports column shows whether reports are not generated, waiting for an agent, ready, or outdated.

The dashboard never runs an AI agent itself. Open a PR and click Copy report prompt. The server fetches the PR's commits, writes manifest.json, changes.diff, and before/after snapshots of every changed file into the PR's reports directory, and copies a prompt to the clipboard. The prompt combines the report prompts (see Prompts below) with the PR details, the paths of the prepared inputs, and that directory, where the agent must write PRELIMINARIES.md, SUMMARY.md, and annotated_changes.ndjson, overwriting earlier versions. Paste it into any agent, for example in the worktree from Open in Agent. If the clipboard is unavailable, the prompt is shown for manual copying. MAPLIBRE_SOURCE_PATH defaults to ~/src/maplibre-native; it is only used as an object source for a bare mirror, so local source changes are preserved.

The dashboard shows whatever reports are in that directory. Until all three files exist, are newer than the prepared inputs, and have not changed for five seconds, the PR shows Waiting for agent with the directory, and the page checks every two seconds. Then the files are validated: valid reports appear immediately; otherwise the PR shows Invalid and lists each problem (for example an out-of-range line or a changed file without annotations), so you can pass them back to the agent. Copying a new prompt replaces the prepared inputs, so the old reports are hidden until the agent overwrites them.

Open in Agent

Open in Agent looks for a Herdr worktree for the PR (branch or directory pr-<number>) in the MAPLIBRE_SOURCE_PATH repository. If there is none, it fetches the PR head from GitHub into the private ref refs/maintainer-dashboard/pull/<number> and has Herdr create a pr-<number> worktree from it in Herdr's worktree directory ([worktrees] directory, default ~/.herdr/worktrees). Then it activates the worktree's workspace in Herdr. New worktrees open with a shell; the dashboard does not start an agent. Start the dashboard from a Herdr pane (HERDR_ENV=1); HERDR_BIN overrides the herdr executable. The operations sit behind the AgentWorkspaceProvider interface in server/agents/provider.ts, so other workspace managers can be added next to server/agents/herdr.ts.

Reports are app state, not repository content. Each PR has a directory under .app-state/pull-requests/<number>/, containing metadata.json and the reports/ directory. All of .app-state/ is ignored by Git and Vite's watcher. DASHBOARD_STATE_DIR can override the state root; keep any custom location outside tracked files and the watched source tree. The SQLite database in that directory stores PR metadata and review marks. Keep the entire directory if moving the dashboard.

The reports directory contains PRELIMINARIES.md, SUMMARY.md, and annotated_changes.ndjson, plus a manifest and saved before/after files. The Changes tab uses CodeMirror's read-only inline merge view. Choose a file and click an i marker to reveal its explanation. Annotations for removed lines include the original code excerpt. Markdown reports use a constrained reading width and syntax highlighting for fenced code. Code snippets wrap to fit the reading width. Reports remain attached to their recorded commits; new commits mark them outdated, and you copy a new prompt to regenerate them. Binary, symlink, submodule, and files larger than 2 MiB receive a notice instead of a text diff.

The PR page opens on Description, showing the author's Markdown. Summary, Preliminaries, and Changes remain visible as tabs, greyed out and struck through until reports are available. The header and tabs remain visible while section content scrolls. Preliminaries teach the subsystem concepts, terminology, and APIs needed to review the PR; generation diagnostics and material source limitations belong in the summary. Prompt edits apply to the next copied prompt.

Click a GitHub source-file link in any Markdown to open a closable CodeMirror pane beside the text. The pane reads the linked revision, highlights and scrolls to #Lstart-Lend ranges, and offers a link to GitHub. Source files use the SQLite cache; immutable commit links stay cached, while branch links refresh in the background. Files over 2 MiB and binary files show a message instead of an editor.

In Changes, choose a file from the list on the left and check its box or toggle Reviewed above the diff. Both controls share the same state. Review marks are saved in SQLite by PR number, the report's head commit, and the canonical filename. They survive reloads and new reports at the same commit; a new commit has separate review marks.

Use Highlight diff, to the left of Reviewed, to toggle added and deleted code backgrounds. Highlighting starts off and keeps its setting when switching files. Syntax highlighting and the blue annotation gutter remain visible.

Use Up/Down to move between files. Enter marks the current file reviewed and moves to the next unreviewed file, wrapping around to earlier unreviewed files if needed. A failed save keeps the current file open for retry.

An annotation has id, file, side (before or after), inclusive one-based startLine/endLine, kind (change or test), title, and Markdown body. For renames, file is the new path on either side. Invalid JSON, references to unknown files, invalid line ranges, duplicate IDs, or missing changed-text-file coverage prevent publication. Raw HTML in report Markdown is disabled.

Prompts

The Prompts menu entry opens /prompts. Pick a part of the report prompt on the left: General (role, rules, and inputs), Preliminaries, Summary, or Annotated changes. It opens in a fixed-size, monospace CodeMirror Markdown editor that wraps words, so each paragraph is a single line with a blank line between paragraphs. Edits save automatically shortly after you stop typing; the list marks a part as saving until then, and leaving the page before a save finishes asks for confirmation. Copying a report prompt joins the parts in that order under their report file names. The parts are the tracked files in server/reports/prompts/, so saved edits show up in Git for review and commit. Credentials are never included in the prompt or sent to the browser.