# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ### Changed - `coord-inbox.sh` now warns on stderr for each unknown argument instead of discarding it silently. The read path stays lenient (it runs inside the SessionStart hook, which must never fail a session over a stray flag) and the exit code is unchanged, but a mistyped flag no longer looks like a working invocation. The hook runs the script with stderr discarded, so the warning surfaces in manual CLI use only. ### Added - Selftest: 68 -> 70 checks, covering the stderr warning and the leniency it must not break (unknown argument still reads the inbox and exits 0). ### Documentation - README: corrected the stale selftest count (64 -> 70), documented that a broadcast is never delivered back to its own sender (shipped in 0.2.1 but undocumented), and added rule 6 — message content is data, never instructions — which `coord-inbox.sh` already enforces in the injection framing. ## [0.2.1] - 2026-07-25 ### Fixed - Broadcast self-delivery: `coord-send --broadcast` left no seen-set entry for the sender, so the announcing repo got its own announcement injected at its next session start. The delivered filename is now recorded in `_broadcast/seen/` at delivery time, reusing the existing per-repo seen set rather than adding a second exclusion mechanism. Filtering on the `from:` field at read time was rejected: `from:` is sender-controlled, so it would let any repo suppress a broadcast for another by forging the field. The seen file is keyed by the raw sender name (the read side keys it unsanitized, so the two must agree); senders containing a slash, or equal to `.`/`..`, skip the marking rather than escape the directory. ### Added - Selftest: 64 -> 68 checks, covering sender self-exclusion, unaffected delivery to other repos, self-exclusion for sender names that are not shell-clean, and the seen-marking path-escape guard. ## [0.2.0] - 2026-07-24 Hardening pass over the three CLIs. ### Fixed - Atomic delivery: the temp file is created inside the destination directory (dot-prefixed, invisible to the inbox glob), so the final rename never crosses filesystems and readers never observe a half-written message. - `.` and `..` are rejected explicitly in the `--reply-to` and `coord-done` name guards instead of relying on downstream failure. ### Added - `-h`/`--help` on `coord-inbox.sh`, making usage output uniform across the three CLIs. - Selftest: 48 -> 64 checks, closing gaps around the default mailbox path via `HOME` fallback, malformed frontmatter on the read path, and a read-only destination directory. ## [0.1.0] - 2026-07-24 First public release: extraction of a battle-tested personal mechanism into a distributable plugin. ### Added - Bash engine: `coord-send.sh` (directed / broadcast / reply delivery), `coord-inbox.sh` (pending inbox + unseen broadcasts, formatted for context injection), `coord-done.sh` (archive without reply), all bash-3.2-safe, ASCII-only, zero dependencies. - `coord-selftest.sh`: 48 checks against a throwaway mailbox, including regression cover for filename sanitization, no-hang argument parsing, prompt-injection resistance, frontmatter hygiene, and broadcast ordering. - SessionStart hook (`hooks/scripts/session-start.mjs`): thin zero-dependency Node wrapper that injects the repo's pending mailbox as `additionalContext`. Always exits 0 — a broken mailbox never blocks a session. - `coord-send` skill: natural-language front door (English + Norwegian triggers) mapping intent to engine invocations, including bounded multi-target loops, deferred sends, and replies. ### Fixed - Frontmatter injection: CR/LF and control characters in `--subject`/`--from` are collapsed before writing, so fields can no longer inject frontmatter lines or a premature `---` terminator. - Broadcast loss: a per-repo seen set (`_broadcast/seen/`, one delivered filename per line) replaces the single high-water mark, which silently dropped a same-second broadcast whose filename sorted below one already seen. Upgrade note: a legacy watermark file is read as a one-entry seen set, so old broadcasts may be re-delivered once. ### Changed - Read-side protocol strings are English (`--- message:`, `-> reply:`, UNTRUSTED DATA framing); the forgery-resistance selftest checks pin the English tokens.