#!/usr/bin/env bash
# bullpen-selfimprove — weekly SELF-IMPROVEMENT run of the bullpen room.
#
# Pokes @foreman (the room-resident orchestrator, a claude -p on the coordinator host) with a research
# campaign: survey the SOTA on multi-agent teamups / personas / single rich-agent skill-teams /
# scientific prompt engineering (incl. Chinese/Asian labs), find GAPS in bullpen's OWN design,
# and land ranked findings in the idea keeper (mneme /ideas + the DokuWiki ideas mirror).
#
# The room does the thinking; this driver only schedules + hands off (release-principle: the
# rich-agent/orchestration layer lives outside the chat). Scheduled by bullpen-selfimprove.timer.
#
#   bullpen-selfimprove              # post the poke for real
#   DRY_RUN=1 bullpen-selfimprove    # compose + print the brief, post NOTHING
set -u

# Rollen-Hosts/Pfade aus der Config (env > /etc/bullpen/bullpen.conf > Default = Ursprungsfleet).
_bp_lib="$(cd "$(dirname "$(readlink -f "$0")")/../lib" 2>/dev/null && pwd)"
for _c in "$_bp_lib/bullpen_config.sh" /usr/local/lib/bullpen/bullpen_config.sh; do
  [ -r "$_c" ] && . "$_c" && break
done

LOG="${SELFIMPROVE_LOG:-$HOME/bullpen-selfimprove.log}"
exec >>"$LOG" 2>&1
echo "==== $(date -Is) selfimprove run start (DRY_RUN=${DRY_RUN:-0}) ===="

WEEK=$(date +%V)
FOCI=(
  "multi-agent orchestration & communication topologies — teamups, routing/dispatch, shared-memory/blackboard, handoff & verification protocols, role societies"
  "agent personas & role-conditioning — persona prompts, role specialization, critic/skeptic/debate roles, when a persona measurably helps"
  "single rich-agent SKILL-TEAMS — one strong agent with skills/subagents/tool-use/plan-then-execute as an ALTERNATIVE to a multi-agent room; when does one beat the other"
  "scientific/empirical prompt engineering — measured techniques with ablations & benchmarks, not folklore"
)
FOCUS="${FOCI[$((10#$WEEK % 4))]}"

read -r -d '' BRIEF <<BRIEF
Weekly bullpen SELF-IMPROVEMENT run (W${WEEK}). GOAL: survey the state of the art, then find GAPS
in bullpen's OWN design and propose ranked, cheap-first improvements. Drive the room; keep it visible.

THIS WEEK GO DEEP ON: ${FOCUS}
(cover the other three lightly so /ideas accumulates full coverage over the month.)

RESEARCH SCOPE — delegate to @researcher, CITED, several sources each:
 1. Multi-agent teamups: orchestration patterns, communication topologies, shared memory/blackboard,
    routing, handoff & verification, role societies.
 2. Agent personas: role-conditioning, specialization, critic/skeptic/debate roles.
 3. Single rich-agent skill-teams: skills/subagents/tool-use/plan-execute in ONE agent vs a room.
 4. Scientific prompt engineering: empirical, ablated, benchmarked techniques.
 * EXPLICITLY include Chinese/Asian-lab papers & sources — Qwen/Alibaba, DeepSeek, Moonshot/Kimi,
   Zhipu/GLM, Baidu, Tencent, Tsinghua/PKU — not only US/English work; note where they diverge.

GROUND THE GAPS IN BULLPEN'S ACTUAL DESIGN (read it, don't guess):
   sic $BULLPEN_GRIND_HOST cat '~/src/bullpen/README.md'   and   sic $BULLPEN_ROOM_HOST bullpen-dispatcher --roster
 bullpen today: append-only JSONL room; thin reactive workers (callboy/librarian/dispatcher);
 conversant personas (architect/skeptic); lurker-agents (foreman/reviewer/testdesigner); grinder (@py);
 pipeline testdesigner->py->reviewer; "packaging/rollout is a rich-agent layer OUT of the chat".

METHOD: plan -> @researcher per subtopic (--timeout 340, poll if 'no reply within') -> synthesize a
GAP LIST (each gap tied to a concrete bullpen piece + a cited source) -> @reviewer critiques the gaps &
proposals (ranked) -> a ranked PROPOSED-IMPROVEMENTS list (cheapest experiment first).

PERSIST (idea keeper — do BOTH):
 A. mneme /ideas (canonical namespace). Write one line per distinct gap/proposal, tagged selfimprove-W${WEEK}
    (mneme writes are instant queue-appends, no lmcp-cap workaround needed):
    sic $BULLPEN_GRIND_HOST lmcp-tool mneme "command=remember '<line>' -n /ideas"
 B. DokuWiki 'ideas' page (human mirror). Append a dated "===== Self-improvement W${WEEK} =====" section
    (gap list + ranked proposals, DokuWiki syntax) via the nc-tools MCP write path (nc is HTTP-MCP-only):
    read the page, append, write back, clear its cache. If you cannot complete the push, post the exact
    section text in the room and say 'dokuwiki mirror pending' — do NOT drop the findings.

FINISH: post a tight final room summary — top 3 gaps + the single highest-value cheap experiment.
Budget ~30 min; if it runs out, persist what you have and state what's left for next week.
BRIEF

echo "focus: $FOCUS"
if [ "${DRY_RUN:-0}" = "1" ]; then
  echo "--- DRY_RUN: brief that WOULD be posted to @foreman ---"
  printf '%s\n' "$BRIEF"
  echo "--- (nothing posted) ---"
  exit 0
fi

# R4: the coordinator nick is PRIVILEGED — room_say silently rejects a privileged post with no
# secret ({"ok":false,"error":"unauthorized"}), and a bare shell truthiness check on `sic`
# can't see that: the SSH+HTTP round-trip itself succeeds even when the room refuses the
# post. Read the secret fresh each run (no caching — a rotated secret shouldn't break
# silently) and inspect the response body, not just the exit code.
SECRET="$(sic "$BULLPEN_ROOM_HOST" sudo cat "$BULLPEN_SECRET_FILE" 2>/dev/null)"
if [ -z "$SECRET" ]; then
  echo "$(date -Is) ERROR: could not read post-secret from $BULLPEN_ROOM_HOST — cannot post as a privileged nick" >&2
  exit 1
fi

# post the campaign to @foreman; the foreman lurker (coordinator host) picks up messages to @foreman and runs it
RESP="$(sic "$BULLPEN_ROOM_HOST" lmcp-tool room_say from="$BULLPEN_POST_NICK" to=@foreman type=ask body="$BRIEF" "secret=$SECRET")"
echo "$RESP"
if printf '%s' "$RESP" | grep -q '"ok":true'; then
  echo "$(date -Is) posted self-improvement campaign to @foreman (W${WEEK})"
else
  echo "$(date -Is) ERROR: room_say to @foreman failed or was rejected: $RESP" >&2
  exit 1
fi
echo "==== $(date -Is) selfimprove run end ===="
