Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3f87d60
feat(app): render terminals via WebGL, attached only to the active pa…
fujibee Jul 20, 2026
94704fd
feat(app): drag files onto a pane to insert their path (#481)
fujibee Jul 23, 2026
4672e15
fix: close #87-class SQLi/path-hazard gaps in rename/leave/reset/rena…
fujibee Jul 24, 2026
f01ce75
fix: shell-quote delivery hook command paths (F14) (#487)
fujibee Jul 24, 2026
f32cafd
fix(install): bound the self-clean race in the watcher re-invocation …
Masashi-Ono0611 Jul 26, 2026
96fa5e5
fix(codex): avoid two-line grep -c count breaking record-session inte…
lmncaj Jul 26, 2026
9c1b8af
fix(codex): make record-session project arg optional, reject poison r…
masa6161 Jul 26, 2026
e743a81
ci: stop the required checks from failing on unrelated changes (#492)
fujibee Jul 26, 2026
a7b012f
fix(spawn): add -g to macOS Terminal/iTerm launch so it doesn't steal…
Masashi-Ono0611 Jul 26, 2026
ed7f160
fix(watch): fail loudly on shifted args instead of running with zero …
Masashi-Ono0611 Jul 26, 2026
03df7da
fix(liveness): treat kill -0 EPERM as alive under the command sandbox…
TakahiroHaruyama Jul 26, 2026
10f96d1
fix(storage): memoize the sqlite3 -escape probe instead of re-running…
fujibee Jul 26, 2026
8c22364
fix(watch): mark read_at on live delivery so a later inbox.sh does no…
Masashi-Ono0611 Jul 27, 2026
a93abfb
fix(codex-bridge): make the turn watchdog an idle timeout, not a fixe…
Masashi-Ono0611 Jul 27, 2026
b41d2a4
feat(spawn): support spawning into herdr panes (#495)
fujibee Jul 27, 2026
5392b84
feat(codex): offer monitor as the default delivery mode, drop the bet…
fujibee Jul 27, 2026
92b16f6
fix(codex): stop the bridge launcher duplicating children and burning…
fujibee Jul 27, 2026
cdb562e
docs(readme): state how to pronounce agmsg (#498)
fujibee Jul 27, 2026
7ac4d6e
release: 1.1.11 (#499)
fujibee Jul 27, 2026
29df066
test: close inherited bats fd 3 in all backgrounded process launches …
fujibee Jul 27, 2026
90bbe8f
ci: run the bats suite in parallel shards (#501)
fujibee Jul 27, 2026
e9a5fc2
test: wait for conditions instead of fixed sleeps in the watcher suit…
fujibee Jul 27, 2026
c1415e9
fix(liveness): a process you cannot signal is not a process that is g…
fujibee Jul 28, 2026
9941ebb
fix(delivery): validate project_path in set instead of mkdir-ing what…
Masashi-Ono0611 Jul 29, 2026
68744d4
fix(codex): compare status metadata project as canonical normalized p…
chemica-tan Jul 29, 2026
053c358
fix(codex): parse the app-server port through ANSI color sequences (#…
chemica-tan Jul 29, 2026
62450b3
test(watch): wait for the watcher instead of sleeping a guess at it (…
fujibee Jul 29, 2026
40610c7
fix(codex): bound watch-once by its lifetime, not by its polling (#55…
fujibee Jul 30, 2026
9a8202e
docs(skill): document the permission allowlist agmsg needs on Claude …
fujibee Jul 30, 2026
7c6220e
docs(codex): document safe Git Bash quoting from PowerShell
otsune Jul 19, 2026
b7f5f19
fix(spawn): keep opencode worker resident via TUI --prompt instead of…
tsukimiya Jul 9, 2026
2a755ca
docs(opencode): mark spawn as supported via --prompt
tsukimiya Jul 29, 2026
3670661
fix(opencode): add cmd_prefix=$ so spawned actas uses $agmsg, not /agmsg
tsukimiya Jul 29, 2026
25fed87
feat(opencode): monitor delivery via opencode-sentinel plugin
tsukimiya Jul 9, 2026
3151f37
docs(opencode): document monitor mode via opencode-sentinel plugin
tsukimiya Jul 29, 2026
70bac28
fix(opencode): harden monitor rule + docs per Copilot review
tsukimiya Jul 29, 2026
a32136d
docs(opencode): describe the monitor fallback as instructed, not enfo…
fujibee Jul 30, 2026
8101d6d
fix(opencode): quote the project path into the generated monitor comm…
fujibee Jul 31, 2026
39197bb
docs(site): add agmsg-bubblelog and agmsg-tui to the showcase and REA…
fujibee Jul 31, 2026
6248bb0
release: 1.1.12 (#576)
fujibee Jul 31, 2026
3aa02f3
Merge upstream v1.1.12
orangewk Aug 1, 2026
a3feae5
fix: preserve MSYS app-server pid checks on Windows
orangewk Aug 1, 2026
8bdd1de
fix: distinguish MSYS and native pid checks
orangewk Aug 1, 2026
2af9539
test: make Codex launcher checks portable on Windows
orangewk Aug 1, 2026
b2566cb
fix: route MSYS liveness through shared helper
orangewk Aug 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "agmsg",
"description": "Cross-agent messaging via SQLite. Send messages between CLI AI agents. No daemon, no network.",
"version": "1.1.10",
"version": "1.1.12",
"author": {
"name": "fujibee"
},
Expand Down
110 changes: 110 additions & 0 deletions .github/scripts/shard-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env bash
#
# Deterministically partition the bats suite into shards, and print the test
# files belonging to one of them (one path per line).
#
# .github/scripts/shard-tests.sh <index> <total> [tests-dir]
#
# The partition is computed from the tree itself, not from a list someone has
# to remember to update. That is the point: with a hand-maintained matrix, a
# newly added test file lands in no shard at all and simply never runs — a
# green CI that silently stopped testing something. Here every `*.bats` file in
# the directory is assigned to exactly one shard, so the union of all shards is
# always the whole suite (asserted by tests/test_ci_sharding.bats).
#
# Balancing is by @test count, greedy longest-processing-time first, rather
# than by file count: the suite's files differ by more than an order of
# magnitude in size, so splitting on names alone would leave one shard doing
# most of the work and cap the speedup at whatever that shard costs.
#
# Test count is a proxy for runtime, and a loose one — measured on macOS, the
# whole suite is 860s and the count-balanced quarters (197/196/197/197 tests)
# come out at 125s/298s/366s/71s. Per-test cost varies from ~0.0s to ~8s
# depending on how much a file forks or waits. So the real speedup here is
# 860s -> 366s (~2.4x), not 4x.
#
# It is still the right weight to ship first. The alternative, a checked-in
# table of measured per-file seconds, buys ~150s more but goes stale silently:
# it would be wrong the moment the fixed `sleep`s in the suite are replaced by
# condition polling, which is the very next CI change queued. Weights are worth
# revisiting once runtimes stop moving. Note the floor either way is the
# slowest single file (test_spawn.bats, 199s) — no split beats that, so the
# ceiling on this approach is ~4.5x, not 4x-and-then-some.
#
# Whatever the weights, the property that matters is coverage, not balance: the
# worst case of a bad weight is an unevenly filled shard, never a missing file.

set -euo pipefail

usage() {
echo "usage: ${0##*/} <shard-index> <shard-total> [tests-dir]" >&2
echo " shard-index is 1-based and must be <= shard-total" >&2
exit 2
}

[ "$#" -ge 2 ] || usage
index="$1"
total="$2"
dir="${3:-tests}"

case "$index" in ''|*[!0-9]*) usage ;; esac
case "$total" in ''|*[!0-9]*) usage ;; esac
[ "$total" -ge 1 ] || usage
[ "$index" -ge 1 ] || usage
[ "$index" -le "$total" ] || usage
[ -d "$dir" ] || { echo "${0##*/}: no such directory: $dir" >&2; exit 1; }

# LC_ALL=C keeps the enumeration order identical across the GNU and BSD
# userlands the suite already runs on, so a given tree always produces the same
# partition regardless of which runner computes it.
files="$(find "$dir" -maxdepth 1 -name '*.bats' | LC_ALL=C sort)"
[ -n "$files" ] || { echo "${0##*/}: no .bats files under $dir" >&2; exit 1; }

# Weight each file by its number of test cases. `grep -c` exits 1 on no match
# after printing 0, which set -e would otherwise treat as fatal.
weighted=""
while IFS= read -r f; do
[ -n "$f" ] || continue
n="$(grep -c '^[[:space:]]*@test' "$f" || true)"
[ -n "$n" ] || n=0
weighted="${weighted}${n} ${f}
"
done <<EOF
$files
EOF

# Heaviest first; ties broken by path so the order is total, not incidental.
sorted="$(printf '%s' "$weighted" | LC_ALL=C sort -t' ' -k1,1nr -k2,2)"

# Greedy LPT: hand each file to the currently lightest shard.
i=0
while [ "$i" -lt "$total" ]; do
load[i]=0
i=$((i + 1))
done

while IFS=' ' read -r n f; do
[ -n "$f" ] || continue
best=0
best_load=${load[0]}
j=1
while [ "$j" -lt "$total" ]; do
if [ "${load[j]}" -lt "$best_load" ]; then
best=$j
best_load=${load[j]}
fi
j=$((j + 1))
done
load[best]=$((best_load + n))
# An `if`, not `[ ... ] && printf`: a false test as the loop's last command
# becomes the script's exit status, so the caller would see failure or
# success depending on nothing but whether the final file happened to land
# in the requested shard.
if [ "$best" -eq "$((index - 1))" ]; then
printf '%s\n' "$f"
fi
done <<EOF
$sorted
EOF

exit 0
Loading
Loading