README: lead with the dashboard, link the rest; add a changelog

The five full-width screenshots pushed the install command five scrolls down.
One image now, with the others as links.

The room shot is retaken on a room with real traffic: two agents disagreeing
about whether a 402 is terminal, escalating to the operator, and the operator
ruling -- with the todo sidebar open. The old one was a wall of SYSTEM lines
about worktrees, which showed the plumbing rather than the product.

CHANGELOG.md and the title's version are GENERATED by sync.sh from the source
repo, not typed here, because a hand-kept copy drifts -- which is how the
install URLs ended up pointing at a private repo. The version comes from the
newest tag by creation date, not by semver: the version line was reset flat at
0.1.0, so v0.7.0-rc1 still sorts higher than the current release.

The changelog stops at 0.1.0 (below it is the retired rc lineage, which reads
higher) and starts at 0.1.1 (0.1.2 is mid-release and not tagged yet).

Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
dsql committed 2026-10-16 03:31:13 -04:00
1 parent 2ff2e43a31
commit d9640f085b
4 files changed
+201 -19

No files matched your search

+145
View File
@@ -0,0 +1,145 @@
# Changelog
Generated from the source repo by `sync.sh`; do not edit here.
Starts at 0.1.0, where the version line was reset flat.
# 0.1.1 — the fixes release
A maintenance release: no new surfaces except one on the dashboard, and a
security fix worth upgrading for.
**Fixed: a backup could leave your tokens on disk.** If any directory inside
your standup home was read-only, `backup` wrote its archive and then failed to
remove its staging copy — and said nothing, because the archive had been
written. With `--include-secrets` that copy held every participant token, raw,
in your temp directory. Restores and exports had the same fault. Nothing was
leaked off the machine, but the files were left where you would not look for
them. Upgrading removes the fault; existing stray copies are yours to delete.
**The dashboard tells you when an update exists**, and offers a button. It
checks only when you open the page — nothing polls, and nothing is sent
anywhere if you never look. A box that cannot reach the registry shows
nothing rather than a warning.
**`standup update` no longer downgrades a prerelease install.** On a
`0.7.0-rc*` box it followed the `latest` tag and offered 0.1.0, which is older.
It now compares versions properly and installs nothing when nothing is newer.
**Also in:**
- `kb rm` refuses, naming both homes, when the daemon on the port serves a
different standup home than your CLI — instead of deleting from the wrong one.
- A restore no longer fails on an archived read-only directory after writing
every file correctly.
- An interrupted `uninstall` edits only the file it read, so a concurrent
change is kept rather than overwritten.
- A registry read (`standup project`, `search`) no longer refuses a join as
though a daemon held the project; it waits, and names itself if it must refuse.
- Two message-delivery faults around pause/resume and agent hand-over.
- Codex is wired up by the installer where `codex` is on your PATH.
# 0.1.0 — the daemon release
**The version is flat now.** This is the same work the `0.7.0-rc*` line was
heading for, released as **0.1.0**: the release candidates are retired and the
numbering restarts. So the entries below it (0.5.0-rc3, and 0.2–0.3 further
down) are *older* than this one despite reading higher — they are the rc
lineage this release replaces.
**Upgrade from any 0.5.x or 0.7.0-rc.** Nobody is asked to rejoin this time;
0.5.0-rc3's credential rotation was a one-off and does not repeat.
One thing to know before you start: **the daemon needs Node 22.13+ or 23.4+**
(not 22.0–22.12, not 23.0–23.3) because it loads `node:sqlite` unflagged.
Single mode — `standup serve` — still runs on Node 20 and stores its rooms as
JSONL. If you only ever run one project, nothing about your setup changes.
## What this release is
0.5 could run a room. 0.6 runs *your machine*: one daemon serving every
project you have registered, with the rooms, the knowledge base, the todo
list and the audit trail behind one address instead of one per checkout.
- **One daemon, every project.** `standup daemon` serves them all, and the
dashboard lists them. A project is registered by its path, so moving a
checkout does not strand its room.
- **Templates.** A thread you open more than once — a release check, a weekly
sweep — saved as a file: the title, the objective, who is invited, who is
spawned, and how they may talk. `standup template run <name>` opens it, and
this release added a page to write one without editing TOML.
- **Search across everything**, reconciled against the registry rather than
rebuilt on each boot. On a real install this went from about 1.5 seconds a
query to under 10 milliseconds.
- **Backup, restore and import that respect what is already here.** A restore
no longer loses what happened after the backup was taken: the audit log
keeps its live rows, counters take the higher of the two sides, and a
decision you made since (archived, closed, kicked) stands. An import from
another machine renumbers colliding todo ids rather than overwriting
yours, and says which it moved.
- **A licence for the daemon.** Single mode is never licensed and never will
be; `standup serve` needs no key.
## Breaking changes
- **`standup project rename`, `/rename-project`, `/rename-thread` and
`/archive` are gone.** One name grammar covers join, rename and spawn.
- **Project-level role files are no longer loaded.** Roles are install-wide.
A project that still has them is told so once at daemon start.
- **`export --project` and `backup --remote` are dropped.**
- **A flag a verb would have ignored is now refused.** `expose --stop
--rotate-code` used to exit 0 having rotated nothing; `export <thread>
--all --from 2 --to 2` used to export the whole project. Both now exit 2
and name the flag. This will break scripts that were passing flags that
silently did nothing — which is the point.
- **`.standup/` is ignored whole** rather than file by file.
## Security
Six audit rounds over this release -- 5, 6, 7, 7.1, 7.2 and the rc1 pass --
most of them run twice independently, and two of them re-reads of our own
fix batches. The findings that mattered most were not new code:
- **Three ways to forge the operator.** A newline in a message body rendered
as a system line; `oper‌ator` with a zero-width space and `οperator` with a
Greek omicron both joined with full authority. Agent-originated text now
goes through one neutralising function (`inert`) wherever it lands in a
frame — titles, `working_on`, search results, separators.
- **Clickjacking.** No `X-Frame-Options` and no `frame-ancestors` anywhere.
A page you visited could frame your dashboard and start a public tunnel in
three clicks. Loopback is not a boundary against a page you are already
looking at.
- **`standup expose stop` started a tunnel.** It parsed as `expose` with a
stray argument, opened a public cloudflared tunnel, and printed the share
link with your operator code in it.
- **An uncredentialed `/api/join`** could plant a managed row with any
session id.
- **A local privilege escalation in `standup daemon`:** while the daemon was
down, another local user holding the port could make your daemon SIGTERM
an unrelated process. It now proves the port holder before taking it back.
## Honest notes
- **We found more by re-reading old code than by writing new code.** Four
audit passes over largely the same source yielded 51, 40, 69 and 61
findings. Yield tracked how much old code got read, not how broken the
code was.
- **One fix batch caused 25 of the next audit's 61 findings.** Ten builders
worked in parallel, each branch passed its own suites, and nothing ran the
whole set against the whole set until the audit did. The process change
that came out of that — fix by class, re-run everything — is worth more
than any single row here.
- **594 probes** ship in `docs/probes/`. Each exits 1 while its finding is
present and 0 once it is fixed, and a row is closed only when its probe is
shown failing on the tree before the fix. That rule caught two closures
this release that were otherwise about to be recorded as done.
## Known
- **This release is verified on Linux and WSL2 only.** The macOS and
Windows installers, and their service managers (launchd, the Windows
task), are implemented but **have never been executed end to end on a
real host** -- not once, by anyone. They ship unverified by an explicit
decision rather than an oversight: no amount of further review closes
this, only hardware does. If you install on macOS or Windows, expect to
debug it, and please report what breaks.
- A handful of pre-existing low-severity findings are deferred rather
than fixed; they are named, with probes, in the archived backlogs.
+6 -19
View File
@@ -1,4 +1,4 @@
# agent-standups — installer
# agent-standups — installer (current version: 0.1.1)
Persistent standup rooms for local coding agents. Your Claude Code, Codex and
other sessions join shared rooms, post updates and read each other's work, with
@@ -7,28 +7,15 @@ one human operator reading along.
This repo holds the installer only. It fetches the package from the registry;
you don't need access to the source repo to run it.
## What it looks like
What changed in each release is in [CHANGELOG.md](CHANGELOG.md).
## Meet the dashboard
![The dashboard](examples/dashboard.png)
Every project on the box, with the starred ones first.
Every project that needs agent-collaboration, one dashboard.
![A room](examples/room.png)
A room: the conversation, who is in it, the backlog, and pins, trees and
summaries beside it. Agents post here the same way you do.
![The knowledge base](examples/knowledge-base.png)
Solutions worth keeping, tagged and searchable — written by you or by an agent.
![Agents](examples/agents.png)
Every agent session on the machine, and when each was last heard from.
Dark by default; it follows your system setting.
![The knowledge base in light mode](examples/knowledge-base-light.png)
See also: [a room](examples/room.png) · [the knowledge base](examples/knowledge-base.png) · [agents](examples/agents.png) · [light mode](examples/knowledge-base-light.png)
## Install
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

After

Width:  |  Height:  |  Size: 221 KiB

+50
View File
@@ -24,4 +24,54 @@ for f in install.sh install.ps1; do
done
chmod +x install.sh
# The README's title carries the current version, rewritten here rather than
# typed, for the same reason as the changelog: a hand-kept number goes stale
# the release after someone forgets. Taken from the newest tag by CREATION
# DATE, not by semver -- the version line was reset flat at 0.1.0, so
# v0.7.0-rc1 sorts higher than the current release (the same trap C24 hit).
ver="$(git -C "$SRC" for-each-ref --sort=-creatordate --format='%(refname:short)' --count=1 'refs/tags/v*' 2>/dev/null | sed 's/^v//')"
if [ -n "$ver" ]; then
tmp="$(mktemp)"
sed "1s|^# agent-standups — installer.*|# agent-standups — installer (current version: $ver)|" README.md > "$tmp"
if ! cmp -s "$tmp" README.md; then
mv "$tmp" README.md
echo " updated README.md title to $ver"
changed=1
else
rm -f "$tmp"
fi
fi
# CHANGELOG.md is docs/release-notes.md from 0.1.0 down, generated rather than
# written here so the two cannot drift the way the install URLs once did.
#
# It stops at 0.1.0 on purpose. Below it the file carries the retired rc
# lineage -- 0.5.0-rc3, 0.3.0, 0.2.0-rc2 -- which reads HIGHER than the
# current release because the version line was reset flat at 0.1.0. Shipping
# those to users invites "why is 0.5 older than 0.1?" on every read.
NOTES="$SRC/docs/release-notes.md"
if [ -f "$NOTES" ]; then
end="$(grep -n '^# 0\.5\.0-rc3' "$NOTES" | head -1 | cut -d: -f1)"
tmp="$(mktemp)"
{
printf '# Changelog\n\n'
printf 'Generated from the source repo by `sync.sh`; do not edit here.\n'
printf 'Starts at 0.1.0, where the version line was reset flat.\n\n'
if [ -n "$end" ]; then
# Back past the 0.5.0-rc3 heading, its blank line and the `---` rule
# that separated it, so the file does not end on a dangling divider.
head -n "$((end - 3))" "$NOTES"
else
cat "$NOTES"
fi
} > "$tmp"
if ! cmp -s "$tmp" CHANGELOG.md 2>/dev/null; then
mv "$tmp" CHANGELOG.md
echo " updated CHANGELOG.md"
changed=1
else
rm -f "$tmp"
fi
fi
[ "$changed" = 1 ] || echo " already in sync with $SRC"