Compare commits
6
Commits
56cd00dac2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b25c63416 | ||
|
|
d9640f085b | ||
|
|
2ff2e43a31 | ||
|
|
0d647d0155 | ||
|
|
af868ca982 | ||
|
|
16a1959074 |
No files matched your search
+165
@@ -0,0 +1,165 @@
|
||||
# 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.2 — the terminal prompt
|
||||
|
||||
**Operator commands ask you instead of refusing you.** Run `standup update`,
|
||||
`uninstall`, `service stop` or any other operator-only command in your own
|
||||
terminal without `--code`, and it now says what it is about to do and asks
|
||||
you to confirm you are the operator. Type `y` to go ahead; anything else
|
||||
stops it, and nothing is done. `--code` and `STANDUP_OPERATOR_CODE` work as
|
||||
before, with no prompt.
|
||||
|
||||
It is a guard against accidents, not a lock: your code is in
|
||||
`~/.standup/config.toml`, which anything running as you can read. Agents run
|
||||
without a terminal, so they never see the prompt; they are refused as
|
||||
before, and told to ask you.
|
||||
|
||||
**Agents can add to the knowledge base.** `standup kb add` no longer needs
|
||||
the code, so an agent can save a note without asking you. Deleting one is
|
||||
still yours: `standup kb rm` is operator-only, and like the other operator
|
||||
commands it now asks you at a terminal.
|
||||
|
||||
# 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; `operator` 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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# agent-standups — installer
|
||||
# agent-standups — installer (current version: 0.1.2)
|
||||
|
||||
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,6 +7,16 @@ 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 changed in each release is in [CHANGELOG.md](CHANGELOG.md).
|
||||
|
||||
## Meet the dashboard
|
||||
|
||||

|
||||
|
||||
Every project that needs agent-collaboration, one dashboard.
|
||||
|
||||
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
|
||||
|
||||
**Linux / macOS / WSL**
|
||||
@@ -31,23 +41,28 @@ already set up prints status and changes nothing.
|
||||
| --- | --- |
|
||||
| `--skill-only` | skill and hooks only; no daemon, no service |
|
||||
| `--no-node` | never provision Node; falls back to skill-only if yours is too old |
|
||||
| `--no-codex` | don't mention Codex, even if it's installed |
|
||||
| `--no-codex` | don't wire Codex, even if it's installed |
|
||||
| `--registry <url>` | install from somewhere other than the default registry |
|
||||
| `--yes` | don't prompt |
|
||||
|
||||
Node 20 is the floor for single mode. The daemon needs 22.13 or newer, because
|
||||
it uses `node:sqlite` without a flag.
|
||||
|
||||
Claude Code gets wired up machine-wide here. **Codex is per-project** — one of
|
||||
the things it writes is a block in the project's own `AGENTS.md` — so the
|
||||
installer can't do it for you. If `codex` is on your PATH, the installer says
|
||||
so and prints the command; run it inside each project you want Codex in:
|
||||
Claude Code gets wired up for you. **Codex too**, if `codex` is on your PATH —
|
||||
the skill and hooks go in machine-wide, and `--no-codex` skips it.
|
||||
|
||||
Two things Codex needs that the installer can't do for you:
|
||||
|
||||
```sh
|
||||
# 1. in Codex, approve the hooks it just installed
|
||||
/hooks
|
||||
|
||||
# 2. in each project you want Codex in, for the room rules
|
||||
standup install --runtime codex
|
||||
```
|
||||
|
||||
`--no-codex` tells the installer not to mention it.
|
||||
The second one is per-project because it writes a block into that project's
|
||||
own `AGENTS.md`.
|
||||
|
||||
Windows uses the same flags with PowerShell spelling: `-SkillOnly`, `-NoNode`,
|
||||
`-NoCodex`, `-Registry <url>`, `-Yes`.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 114 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 187 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 188 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 221 KiB |
+14
-7
@@ -1,6 +1,6 @@
|
||||
# agent-standups installer for Windows.
|
||||
#
|
||||
# irm https://git.rethinkstudios.io/rethink-software/agent-standups/raw/tag/v0.1.0/install.ps1 | iex
|
||||
# irm https://git.rethinkstudios.io/rethink-software/agent-standups/raw/tag/v0.1.2/install.ps1 | iex
|
||||
#
|
||||
# Flags (when invoked as a file): -SkillOnly -NoNode -NoCodex -Registry <url> -Yes
|
||||
# Through `irm | iex` the defaults apply; download it to pass flags.
|
||||
@@ -243,6 +243,15 @@ if (-not $serviceOnly) {
|
||||
& standup install --runtime claude
|
||||
if ($LASTEXITCODE -ne 0) { Warn 'runtime install reported a problem; see doctor below' }
|
||||
|
||||
# Codex where its binary exists. Machine-wide: the skill and the hooks. The
|
||||
# AGENTS.md step needs a project and is skipped here -- named in the closing
|
||||
# lines instead. Not run at all without codex, so no marked blocks are left
|
||||
# for a tool that is not installed; -NoCodex opts out where it is.
|
||||
if (-not $NoCodex -and $codexBin) {
|
||||
& standup install --runtime codex
|
||||
if ($LASTEXITCODE -ne 0) { Warn 'codex runtime install reported a problem; see doctor below' }
|
||||
}
|
||||
|
||||
if ($probe -and -not $probe.HasExited) { Stop-Process -Id $probe.Id -Force -ErrorAction SilentlyContinue }
|
||||
Remove-Item -Recurse -Force $probeDir -ErrorAction SilentlyContinue
|
||||
}
|
||||
@@ -300,13 +309,11 @@ Write-Host ''
|
||||
& standup code
|
||||
Write-Host ''
|
||||
Write-Host 'Next: cd <your project>; standup create'
|
||||
# Codex's runtime is per-project -- one of its three targets is the project's
|
||||
# own AGENTS.md -- so the installer cannot wire it from here: there is no
|
||||
# project yet, and the runtime step's throwaway is deleted. Name the command
|
||||
# instead, only where codex exists and the user has not opted out.
|
||||
if (-not $NoCodex -and $codexBin) {
|
||||
Write-Host ''
|
||||
Write-Host 'Codex is installed here. In each project you want it in:'
|
||||
Write-Host ' standup install --runtime codex # hooks, skill, a block in AGENTS.md'
|
||||
Write-Host 'Codex: the skill and hooks are wired machine-wide. Codex must TRUST them:'
|
||||
Write-Host ' run /hooks inside Codex and approve.'
|
||||
Write-Host 'Per project, for the room rules in AGENTS.md:'
|
||||
Write-Host ' standup install --runtime codex'
|
||||
}
|
||||
}
|
||||
+17
-9
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# agent-standups installer: detect, provision Node, install, start.
|
||||
#
|
||||
# curl -fsSL https://git.rethinkstudios.io/rethink-software/agent-standups/raw/tag/v0.1.0/install.sh | sh
|
||||
# curl -fsSL https://git.rethinkstudios.io/rethink-software/agent-standups/raw/tag/v0.1.2/install.sh | sh
|
||||
#
|
||||
# Flags: --skill-only --no-node --registry <url> --yes
|
||||
#
|
||||
@@ -83,7 +83,7 @@ if [ "$OS" = linux ] && grep -qi microsoft /proc/version 2>/dev/null; then IS_WS
|
||||
[ "$OS" = unknown ] && die "unsupported OS: $UNAME"
|
||||
if [ "$OS" = windows ]; then
|
||||
die "run the PowerShell installer on Windows:
|
||||
irm https://git.rethinkstudios.io/rethink-software/agent-standups/raw/tag/v0.1.0/install.ps1 | iex"
|
||||
irm https://git.rethinkstudios.io/rethink-software/agent-standups/raw/tag/v0.1.2/install.ps1 | iex"
|
||||
fi
|
||||
say " os : $OS$([ "$IS_WSL" = 1 ] && echo ' (WSL2)')"
|
||||
|
||||
@@ -426,6 +426,13 @@ if [ "$SERVICE_ONLY" = 0 ]; then
|
||||
done
|
||||
fi
|
||||
standup install --runtime claude || warn "runtime install reported a problem; see doctor below"
|
||||
# Codex where its binary exists. Machine-wide: the skill and the hooks. The
|
||||
# AGENTS.md step needs a project and is skipped here -- named in the closing
|
||||
# lines instead. Not run at all without codex, so no marked blocks are left
|
||||
# for a tool that is not installed; --no-codex opts out where it is.
|
||||
if [ "$NO_CODEX" = 0 ] && [ -n "$CODEX_BIN" ]; then
|
||||
standup install --runtime codex || warn "codex runtime install reported a problem; see doctor below"
|
||||
fi
|
||||
[ -n "$PROBE_PID" ] && { kill "$PROBE_PID" 2>/dev/null || true; wait "$PROBE_PID" 2>/dev/null || true; PROBE_PID=""; }
|
||||
rm -rf "$PROBE_DIR"; PROBE_DIR=""
|
||||
fi
|
||||
@@ -471,9 +478,12 @@ if [ -n "$DAEMON_NODE" ]; then
|
||||
service_as_operator start >/dev/null 2>&1 \
|
||||
|| warn "service installed but did not start; see 'standup service status'"
|
||||
elif printf '%s' "$SVC_OUT" | grep -qi 'connect to bus'; then
|
||||
# By hand on the unit's home, `standup daemon` is operator-only once a
|
||||
# code exists (P8-06), so the hint carries the flag (R213 C1).
|
||||
warn "no systemd --user bus here, so the unit was written but not enabled.
|
||||
If this is WSL2: add [boot] systemd=true to /etc/wsl.conf, then 'wsl --shutdown'.
|
||||
Until then run 'standup daemon' yourself; single mode needs nothing."
|
||||
Until then run 'standup daemon --code <operator code>' yourself ('standup code'
|
||||
prints it); single mode needs nothing."
|
||||
else
|
||||
warn "service install failed; single mode still works. See 'standup service status'."
|
||||
fi
|
||||
@@ -494,12 +504,10 @@ say ""
|
||||
standup code 2>/dev/null || say " (run 'standup code' for the operator code)"
|
||||
say ""
|
||||
say "Next: cd <your project> && standup create"
|
||||
# Codex's runtime is per-project -- one of its three targets is the project's
|
||||
# own AGENTS.md -- so the installer cannot wire it from here: there is no
|
||||
# project yet, and step 7's throwaway is deleted. Name the command instead,
|
||||
# only where codex exists and the user has not opted out.
|
||||
if [ "$NO_CODEX" = 0 ] && [ -n "$CODEX_BIN" ]; then
|
||||
say ""
|
||||
say "Codex is installed here. In each project you want it in:"
|
||||
say " standup install --runtime codex # hooks, skill, a block in AGENTS.md"
|
||||
say "Codex: the skill and hooks are wired machine-wide. Codex must TRUST them:"
|
||||
say " run /hooks inside Codex and approve."
|
||||
say "Per project, for the room rules in AGENTS.md:"
|
||||
say " standup install --runtime codex"
|
||||
fi
|
||||
@@ -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"
|
||||
Reference in new issue
Block a user