#!/bin/zsh -l # capture-note.sh — matrix-bridge capture wrapper. # # Invoked over SSH by the bot: capture-note.sh # Appends ONE line to the cross-project inbox (standards/INBOX.md) in the exact format the # /capture skill uses, commits it, and best-effort pushes — so /triage (run later inside the # target repo) drains it like any other captured item. # # Deterministic on purpose: no LLM, no token, nothing leaves the Mac except the git push to # Gitea. The "smarts" (priority, repo-routing, phrasing) stay at /triage, where the human is — # routing message text through a frontier model would break the sovereignty boundary (D13/D8). # Type comes from an optional leading keyword the user types ("bug: ...", "feature: ..."); # anything without one defaults to a raw [idea]. Priority is always P2; /triage sets the real one. # # Why a login shell (-l): git config / PATH live in ~/.zprofile, which a non-login SSH shell # skips — the same seam as launch-claude.sh / ask-claude.sh. set -e setopt extended_glob # for whitespace-run trimming below standards="$HOME/Projects/standards" inbox="$standards/INBOX.md" project="$1" shift || true note="$*" if [[ -z "$project" || -z "$note" ]]; then print -u2 "usage: capture-note.sh " exit 2 fi if [[ ! -f "$inbox" ]]; then print -u2 "capture-note: inbox not found: $inbox" exit 1 fi # Optional leading type keyword ("bug: ...", "feature: ...", etc.) → that type; default idea. # Only fires when the text before the first colon is exactly one known keyword, so a note that # merely contains a colon ("ratio is 3:1") is left untouched. Types: standards/guides/capture.md. type="idea" if [[ "$note" == *:* ]]; then cand="${(L)note%%:*}" # lowercase the text before the first colon cand="${cand##[[:space:]]#}" # trim surrounding whitespace cand="${cand%%[[:space:]]#}" case "$cand" in bug|feature|idea|chore|skill|agent|project) type="$cand" note="${note#*:}" # drop "keyword:" note="${note##[[:space:]]#}" # trim leading whitespace ;; esac fi line="- [ ] ($project) [$type][P2] $note — via matrix, $(date +%F)" print -r -- "$line" >> "$inbox" git -C "$standards" add INBOX.md git -C "$standards" commit -q -m "Capture: ${note[1,60]} (via matrix)" -- INBOX.md # Push is best-effort — a captured line committed locally is not lost if Gitea is unreachable. git -C "$standards" push -q 2>/dev/null || print -u2 "capture-note: push skipped/failed (committed locally)" # Echo the exact line so the bot can post it back into the thread as confirmation. print -r -- "$line"