An Urban app that turns a stream of merged pull requests into polished, human-approved GitHub Releases — with an AI agent doing the drafting and a person staying in the loop for the final say.
Cutting a release note by hand is tedious and easy to get wrong: you scrape the merged PRs since the last tag, guess at categories, write a summary, and hope you didn't miss a breaking change. The Concierge automates the toil and keeps the judgment where it belongs — with a human reviewer.
The whole thing is a BPMN process (visible and editable in the Nano modeller):
collect merged PRs ──▶ draft notes (agent) ──▶ await approval ──┬─(approve)─▶ publish release
▲ │
└──────────────────── revise (agent) ◀──────(request changes)
- Collect — gather PRs merged since the last release tag for a target repo.
- Draft — an agent service task categorizes changes (Features / Fixes / Breaking / Chore) and writes a summary + highlights.
- Await approval — the draft parks in the Urban page for a human to approve or send back with change requests (a message catch event).
- Revise loop — on "request changes", the agent re-drafts with the feedback; back to await approval.
- Publish — on approval, create the GitHub Release with the finalized notes.
Early scaffold. The build-out is tracked by the planning epic and its sub-issues in this repo. This app is also a live test of the Nano delegation -> PR-convergence -> merge loop.
npm install # installs deps and wires git hooks (via the `prepare` script)
npm run gen # derive typed artifacts from nano.app.json (never committed)
npm run lint # biome check (lint + format) over main.ts/app/workers/pages/actions/tests
npm run typecheck # tsc --noEmit -p tsconfig.check.json
npm run test # node --test (--experimental-strip-types) over tests/unit/*.test.ts
npm run check # urban manifest + model validation
npm start # run against a Nano engine (CAMUNDA_REST_ADDRESS, default http://localhost:8080/v2)Every change goes through the same five gates, aggregated by a single command:
npm run verify # gen && lint && typecheck && test && check- gen —
urban genregenerates the typed SDK undernano-generated/fromnano.app.json. It is derived, never committed (see.gitignore); run it first. - lint —
biome check(config inbiome.json, the c8ctlrecommended+ strict ruleset), scoped tomain.ts,app/,workers/,pages/,actions/,tests/and excluding generated dirs (nano-generated/,templates/). Usenpm run lint:fixto auto-apply safe fixes and formatting. - typecheck —
tsc --noEmit -p tsconfig.check.json. - test — the Node built-in runner (
node --experimental-strip-types --test). - check —
urban checkvalidates the manifest and models.
The app targets Node only (minimum >=22.13, the first release to expose
node:sqlite unflagged). CI runs the full Node pipeline on every PR
(.github/workflows/ci.yml) across the minimum and latest Node versions, so all
sub-issue PRs are gated by these same conventions.
npm install runs a prepare script that points core.hooksPath at .githooks/:
- pre-commit —
lint/format staged*.ts(via Biome), thentypecheckthe whole project (tsc -p tsconfig.check.jsonis project-wide, not staged-scoped). - pre-push — the full
verifyaggregate.
Hooks degrade gracefully (skip, non-fatal) when tooling isn't installed yet.
Tests live under tests/ and run on the Node built-in test runner:
tests/unit/*.test.ts— fast unit tests (npm run test).tests/integration/*.test.ts— integration tests (npm run test:integration).
Write tests with node:test + node:assert/strict (keep imports to node:
builtins and the app's own modules). Feature
sub-issues (#2–#5) add their own tests here — drop a *.test.ts file directly
into tests/unit/ and npm run test (and CI, which runs that script) picks it
up automatically. The globs are non-recursive and per-directory: files under
tests/integration/ run via npm run test:integration (not part of CI by
default), and nested subdirectories aren't matched. See
tests/unit/scaffold.test.ts for the shape.
This repo is built in waves. Sub-issue #7 (this scaffold) is the only task
that scaffolds the app or configures tooling — it must merge before any feature
work starts. Every later sub-issue (#2–#5) builds on the merged skeleton and
MUST NOT re-scaffold or change the lint/test/CI configuration; it only adds its
own code under the existing layout and its own tests under tests/, gated by the
conventions established here.
- Commits are DCO signed-off (
git commit -s). - Dev workflow and CI gates: gen → lint → typecheck → test → check — all enforced on every PR.