Commit Graph

17 Commits

Author SHA1 Message Date
marfrit 83170728e9 Doku: zwei Texte, die aktiv in die Irre fuehrten
Fables Punkte 4.6 und 5.4. Beide sind billig und beide haben Schaden
angerichtet, weil sie gelesen und geglaubt wurden.

participants/deus.md versprach "watch it" — und deus hat am 2026-08-08
genau das ausformuliert: "Ich ueberwache den Raum auf Blockaden und
greife wieder ein." Es kann das nicht. Der Lurker kennt als Laufzeit nur
`claude` und `opencode`, kein `pi`; der Prozess endet mit der Antwort;
es gibt weder Timer noch Waechter. Zwischen zwei Anstoessen existiert
deus nicht.

Neu steht dort, dass es nicht mitlaeuft, und die Anweisung, NIEMALS
weitere Beobachtung zu versprechen — sondern zu sagen, WORAUF jemand
schauen muss und WORAN man es erkennt. Fables Begruendung, wortwoertlich
richtig: "wer es liest, hoert auf hinzusehen". Ein unbelegtes
Versprechen ist schlimmer als gar keins, weil es Aufmerksamkeit durch
das Gefuehl ersetzt, sie sei schon vergeben.

docs/ORCHESTRATION.md ist das Onboarding-Dokument fuer neue Beteiligte
und beschrieb die Vor-Container-Welt: Raum auf hertz, Lurker auf
noether, @foreman auf orca:4097, Grind-Host boltzmann. 21 Treffer auf
Adressen, die es nicht mehr gibt. Aus genau dieser Quelle stammte schon
der "vier sic-Fundstellen"-Fehler.

KEIN Neuschrieb: die Mechanik traegt weiter und ist der Wert des
Dokuments — Weckmengen, Ticketform, die drei Fehlerbilder. Falsch sind
die ADRESSEN. Deshalb ein Abschnitt 0 mit Umrechnungstabelle vor allem
anderen, plus die drei Aussagen, die inzwischen ins Gegenteil gekippt
sind:

  * die zwei Endpunkte (:8080 strikt / :8081 gelockert) gibt es nicht
    mehr — eine Instanz laedt beide Plugins, das spaetere gewinnt;
  * PRIVILEGED als Namensliste gibt es nicht mehr — ein Nick ist
    privilegiert, wenn seine Geheimnisdatei existiert;
  * das Lease-Tor ist abgeklemmt, und der Lurker erneuert Leases, die
    nichts bewachen. Wer es scharf schaltet, tue es wissentlich.

Dazu die Invariante, die im Dokument fehlte: LMCP_TOOL_ALLOW. Ohne sie
hat jeder Token-Halter eine Wurzelschale im Raum — inklusive des
Orchestrators, dem dasselbe Dokument ausdruecklich keine zugesteht.
2026-08-08 15:55:46 +02:00
marfrit 878e99c562 docs/kampagnen: Fables Architektur-Review, wortlaut
Es lag nur im Sitzungskontext. Das ist zum vierten Mal an einem Tag
dieselbe Falle: die stehende Rolle von @deus lag nur in einem Container,
das Architektur-Manifest nur in einem Sitzungsverzeichnis, das
Befundprotokoll ebenso — und jetzt beinahe das Review, das die zwei
schwersten Befunde des Tages enthaelt.

Wortlaut unveraendert, plus ein Anhang mit dem, was danach NACHGEMESSEN
wurde. Fable hatte ausdruecklich den Auftrag, die Befunde nicht
ungeprueft zu uebernehmen; dieselbe Regel gilt fuer sein Review. Drei
Behauptungen gegengeprueft, alle drei bestaetigt:

  * foreman haelt das geteilte Post-Geheimnis, byteidentisch mit dem
    im room;
  * das Lease-Tor ist tot — das aktive room_say hat null Lease-Bezuege,
    das ueberschriebene sechs;
  * room_say bindet den Aufrufer nicht an den Nick: aus dem
    deus-Container als testdesigner gepostet -> id 175,
    from: testdesigner, verified: true.

Die zwei Befunde, die ICH nicht hatte und Fable fand: der Kollaps der
Zwei-Endpunkt-Architektur beim Container-Umbau (eine lmcp-Instanz laedt
beide Plugins, das spaeter geladene ueberschreibt lautlos) und die
Folge daraus, dass foreman das Geheimnis ueberhaupt bekommen musste.
Dazu die Korrektur meines eigenen B3-Fixes: eine Fassungsliste im
Vertrag zu NENNEN ist eine zweite Kopie der Tatsache und veraltet; der
Test muss den laufenden Server fragen.
2026-08-08 13:19:05 +02:00
marfrit 04d89da5cc docs/kampagnen: Befundprotokoll des ersten Container-Durchlaufs
Phase B der lmcp-Angleichung, vollstaendig durchgelaufen, GRÜN gemeldet
und inhaltlich falsch abgenommen. Acht Befunde, alle mit Beleg.

Warum ins Repo und nicht in eine Sitzungsnotiz: das ist die Lehre des
Tages, dreimal gelernt. Die stehende Rolle von @deus lag nur in einem
Container und war beim Neubau weg. Das Architektur-Manifest lag nur in
einem Sitzungsverzeichnis. Beides ist heute nachgezogen worden. Ein
Protokoll, das die naechste Arbeit bestimmt, gehoert an denselben Ort.

DIE ZWEI SCHWEREN:

B6 — Der Orchestrator hat eine Wurzelschale, ueber den Raum. Die
tools.d-Dateien FUEGEN room_say/room_read HINZU; der Grundstock aus
server.lua bringt shell/write_file/edit_file mit, und eine Werkzeugdatei
kann nichts wegnehmen. Nachgewiesen aus dem foreman-Container mit dem
Raum-Token: uid=0(root), hostname room, Schreibzugriff auf room.jsonl.
@foreman hat die Schale unaufgefordert benutzt und damit die Abnahme
seiner eigenen Koordination ausgefuehrt.

B7 — `verified` beweist niemanden. Nachgewiesen: aus dem deus-Container
als "testdesigner" gepostet, mit dem geteilten Geheimnis -> id 175,
from: testdesigner, verified: true. room_say bindet den Aufrufer nicht
an den Nick. Ursache: die Zwei-Endpunkt-Architektur (strikt/relaxt) ist
beim Container-Umbau still kollabiert - eine Instanz laedt beide
Plugins, das spaeter geladene ueberschreibt, foreman brauchte deshalb
das Geheimnis. Dabei wurde das Lease-Tor mit abgeklemmt: das aktive
room_say hat null Lease-Bezuege, der Lurker erneuert Leases, die nichts
bewachen.

WAS FUNKTIONIERT HAT, damit der Blick nicht schief wird: die
Rollentrennung hielt ohne Nachfassen (@foreman wies den Fix @coder zu
statt selbst zu tippen), @coders eingebetteter Selbsttest wurde von der
Gesellschaft verboten statt von mir, und der Kaefig meldete Fehllaeufe
ehrlich mit exit 1 und echter Lua-Meldung.

Die Befunde B6/B7 sind von zwei unabhaengigen Stellen bestaetigt: Fable
(Architektur-Review) fand B7 und den Endpunkt-Kollaps, den ich
uebersehen hatte; @deus fand B3 und die Abnahme-Vermischung selbstaendig,
ohne dass ihm gesagt wurde, wonach er suchen soll - und trennte sauber,
was es nicht pruefen konnte.
2026-08-08 13:04:14 +02:00
marfrit 214e2688c0 docs/ARCHITECTURE.md — das Entwurfsmanifest kommt ins Repo, Fassung 3
Fassung 2 entstand am 2026-08-07 als Entwurf VOR dem Bau und lag danach
nur in einem Sitzungsverzeichnis. Dieselbe Krankheit, gegen die das
Dokument antritt: die stehende Rolle von @deus lag genauso nur in einem
Container und war nach dem Neubau weg. Wenn ein Dokument den Betrieb
bestimmt, gehoert es versioniert - sonst ueberlebt es den naechsten
Neubau nicht, und der Neubau ist der Moment, in dem man es braucht.

Fassung 3 trennt sauber, was Fassung 2 vermischte: was ENTWORFEN war,
was GEBAUT wurde, und was die Messung danach KORRIGIERT hat. Alle Zahlen
sind nachgemessen, nicht uebernommen.

WAS DER BAU SCHULDIG BLIEB (neu, und der eigentliche Grund fuer diesen
Commit):

* Der Erbauer existiert nicht. roster.yaml und secrets.example fehlen,
  deploy/bullpen-up ist noch der alte Einzel-Container-Starter. Die neun
  Container sind von Hand angelegt, und sie laufen aus /opt/bullpen-src,
  einem git-Checkout - `dpkg -l bullpen` ist in jedem leer. Die stehende
  Anweisung war, die laufende Instanz AUS DEM PAKET zu bauen. Das war
  Fables Blocker Nummer eins an Fassung 1 und ist wieder offen.
* Die Speicherdeckel summieren sich auf 10752 MiB in einem Eltern mit
  4096 MiB: Ueberbuchung 2,62. Genau der Zustand, den die
  Zulassungssteuerung verhindern sollte ("OOM ist kein Scheduler") - und
  die Sperre gibt es nicht. Was den Deckel heute haelt, ist Glueck.
* room.jsonl hat keine Sicherung, obwohl das Dokument ihn selbst "den
  einzigen unersetzlichen Zustand" nennt.
* Neun Kinder sind die Decke; ein zehnter scheitert an newuidmap trotz
  idmap.size=1e9.

KORREKTUREN, die die Messung erzwungen hat:

* @deus ist kein Lurker - der Lurker kennt nur claude und opencode, kein
  pi. Kein Rueckschritt (der alte deus hatte auch keinen Wecker), aber es
  heisst: wenn sich die Gesellschaft verklemmt, weckt ihn niemand.
* deus haelt keine Schluessel, also baut er den Sandkasten nicht mehr -
  `grind` IST der Sandkasten.
* TRUST ist eine Architektur-Invariante. Fehlt ein Nick, verschwindet
  seine Nachricht geraeuschlos: ok:true beim Absender, verworfen beim
  Empfaenger. Nachzusehen ist beim EMPFAENGER.
* Raum und Rolle duerfen auf demselben Rechner liegen (LMCP_HOST).
* Der Grinder-Ausgang ist GEFILTERT, nicht gesperrt - "kein Ausgang"
  baut einen toten Container, die Schleife braucht Proxy und Raum.
* bullseyes Denk-Anzeige ist ueber Containergrenzen tot: sie liest
  DATEIEN, die im Nachbarcontainer liegen, und der except schluckt es.
2026-08-08 11:37:06 +02:00
marfrit c00359660e docs: model gateway, wrong-chat-template failure mode, room-ask trust caveat
Three gaps found while onboarding onto this society from cold context.

ORCHESTRATION §4.1 — how a grinder reaches a model. Tiers were documented but
not the path: grinders go through llm-proxy, and the standing ladder lives in
PY_GRIND_TIERS on the unit, not in the ticket. A ticket's tiers= is per-grind
override; the unit is policy. Also names the gateway as the only place to
enforce request-level policy across all clients.

ORCHESTRATION §5 Failure Mode D — a wrong chat template stops an agent
mid-chain. Reads as the model losing the plot, is a tokenizer problem one layer
below the room. Separates the two causes that need different fixes: a template
from the wrong family (configuration, fix with --chat-template-file) versus the
model spelling the marker out as ordinary text (behaviour, mitigate with
stop-strings at the gateway). Includes the tokenise test that tells them apart:
one token = real special token, six = the model typed it.

invoking-from-a-rich-agent §1 — room-ask fails for a PRIVILEGED nick. It posts
through the strict endpoint without the shared secret, so most rich agents get
"unauthorized" from the tool the doc recommends. ORCHESTRATION §3 explains the
gate; this adds the caveat where a reader actually looks for it.

No local hostnames in the new text — the gateway is referenced by repository,
hosts as placeholders.
2026-08-01 12:46:16 +02:00
marfrit 74abc8e1da docs/ORCHESTRATION.md: add §8 Campaign sandbox convention
Add the referenceable sandbox section that the /bullpen/sandbox mneme
namespace (already referenced in §7) points to. Covers the four topics
from the hot-log Open Items:

§8.1 Build-dir convention — /tmp/bullpen-build/<slug> + /tmp/sandbox
    alias, why alias (removes slug-handoff failures), why /tmp not /
§8.2 Host boundary — .runtime files, which agent executes where,
    failure signatures when wrong, pre-flight check
§8.3 Ticket rules — required fields in order (PROBLEM, REPO, TRAPS,
    STEP 1+2, constraints), SPEC requirement
§8.4 Route by test file type — routing table, coordinator wiring
§8.5 Result extraction — where the green artifact lives, how to review

Also updates §7's /bullpen/sandbox entry to point to §8 and deus_ex.md.
2026-07-25 15:59:38 +00:00
marfrit cb66ad0458 consolidate mneme /bullpen namespace: split the undifferentiated dump into 5 typed namespaces
markus asked to consolidate the bullpen namespace in mneme and whether it's well anchored.
It wasn't: bare /bullpen held 39 entries with no internal structure -- 19 raw @callboy
fetch-cache pointers (RSS/heise/lwn URLs), 17 genuine @researcher findings (cited surveys
on multi-agent patterns, hardware questions), and 3 real ops/policy facts (release model,
grinder routing), all landing in the identical namespace because bullpen_mem.py's
save(text, ns="/bullpen") default was never overridden by either caller.

Root-caused and fixed at the call sites (the correct fix, not the shared library default --
callboy and researcher produce different KINDS of content and need different homes):
- bin/bullpen-callboy: remember() now passes ns="/bullpen/artifacts"
- bin/bullpen-researcher: remember() now passes ns="/bullpen/research"
Deployed (both are repo-symlinked system units on hertz; restarted, both active).

Migrated all 39 existing entries via mneme's POST /update {id, ns} (verified prefix-match
semantics first -- ns filtering is `WHERE ns LIKE '<ns>%'`, so @librarian's existing
ns="/bullpen" recall scope still sees everything after the split, nothing broke):
  /bullpen/artifacts  19  (raw fetch-cache pointers, low value beyond dedup)
  /bullpen/research   17  (cited @researcher findings, durable synthesis)
  /bullpen/ops         3  (standing policy: release model, grinder routing)
bare /bullpen: 0 remaining.

docs/ORCHESTRATION.md new S7: documents the now-5-way schema (adds /bullpen/sandbox from
2026-07-24) and, more importantly, the discovery-path split that actually answers "is this
anchored" -- lessons-learned/* auto-injects into every poke via _recall_lessons(); sandbox/
ops/research/artifacts are manual-lookup-only via @librarian and require an explicit
escalation instruction in the CONSUMING agent's prompt (@foreman, Deus) or they're invisible
regardless of how clean the namespace is. Also fixes a stale claim in the same doc found
while making this section a room-hub restart is NOT a "seconds-long blip" for @foreman
specifically (its opencode MCP session goes stale and does not self-heal) -- correction
owed since discovering this live earlier in the same session (deus_ex.md S5), now applied.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-25 14:26:09 +02:00
marfrit b594bba104 docs(deus_ex): fixed sandbox alias /tmp/sandbox — no more per-campaign slug in tickets
Repeated handoff failures traced back to the slug in /tmp/bullpen-build/<slug>/:
a ticket with the wrong or missing slug produces DIR NOT FOUND on an otherwise-
correct agent. markus proposed switching the shared basis to "/" so everyone
agrees on one reference point; investigated first since he flagged the exact
risk himself (is "/" the same thing everywhere?).

It is not: boltzmann (the grind host, where @testdesigner now executes per the
earlier host-boundary fix) is BARE METAL (systemd-detect-virt: none) -- the
real physical Pi, which itself hosts other Incus containers. orca (@foreman)
and deus are each their own isolated Incus container filesystem. Three
different roots; giving an unconfined bare-metal agent a "/" mental model is
a real safety risk, not just an inconvenience -- a confused absolute path
could touch the real host instead of a sandbox.

Landed on a fixed SYMLINK instead: /tmp/sandbox -> /tmp/bullpen-build/<slug>,
repointed at the start of each campaign. Solves the actual pain (one name,
never changes, no slug to get wrong) without expanding what any agent can
reach -- stays inside the already-safe /tmp boundary. Verified end-to-end on
boltzmann: opencode reads/writes through the symlink transparently, and the
grinder's os.path.realpath() safety check resolves it correctly.

The slug dir itself is unchanged and still required (real git-tracked archive,
baseline commit, diff target) -- only ticket-facing references (REPO:, SPEC:,
the healthy-chain diagram, the DIR-NOT-FOUND failure signature, the checklist)
now say /tmp/sandbox instead of the slug path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-25 14:11:03 +02:00
marfrit d90f0b87ff docs(deus_ex): state the host boundary — a path is only meaningful with a host
The mneme-fts5 campaign stalled with @testdesigner reporting DIR NOT FOUND for a build
dir that demonstrably existed: the dir was on boltzmann (grind host) while the agent was
executing on orca. The ticket and the path were both correct; the doc simply never said
which host each agent runs on, so "put it in /tmp/bullpen-build/<slug>/" read as one
shared filesystem.

- new §2.1: the `.runtime` file decides the HOST — absent/claude => runs on noether and
  has sic (cross-host reach); `opencode` => runs on LURKER_OC_HOST (default orca),
  sandboxed, sees only that host and auto-rejects external dirs. Flipping .runtime
  silently relocates an agent. Includes the current placement table, the rule (build dir
  must live where the test-writer AND grinder execute), the exact failure signature, and
  the drop-in recipe for moving an opencode nick to another host.
- host-setup caveats learned installing opencode 1.18.4 on boltzmann: symlink the binary
  into /usr/local/bin (the installer only edits ~/.bashrc, which non-interactive sic never
  sources); install oc-run + oc-final-text.py; use a MINIMAL provider-only config — a
  copied full config declares MCP servers (degater/hertz/hub) that block startup on a host
  that lacks them, which presents as a model hang. Bisect model vs harness with a direct
  3-token /chat/completions call. oc-run blocks on an open stdin (add < /dev/null by hand;
  harmless under systemd).
- §3.1 pre-flight: verify the dir from BOTH hosts before posting a ticket.
- unwedging table: two new rows (wrong-host DIR NOT FOUND; opencode hang from absent MCP).
- checklist: host boundary is now the first item.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-24 23:50:33 +02:00
marfrit 7b3a9f671c docs: add deus_ex.md — how to set up and run a bullpen campaign
A reusable playbook for the Deus ex Machina (operator) role, referenceable from any
agent's context. Generalizes what the Asteroids benchmark and the mneme FTS5 initiative
made explicit:

- why the Deus is required at all: @foreman/@testdesigner are sandboxed (room-only, no
  shell), and grinder auto-scaffold only produces empty stubs — so fix-existing-code and
  fixture-bearing campaigns need the operator to place source + a baseline commit
- campaign setup recipe: slug/build dir on the grind host, baseline commit, ticket
  anatomy (PROBLEM / REPO / TRAPS / acceptance contract / constraints), routing by test
  file type with an absolute SPEC: path, posting as a privileged nick
- writing a spec that can't pass wrongly (green != correct): forbid the plausible-but-
  wrong fix, assert observable state change, always require no-regression + migration
- unwedging table (reply-wake, INVALID TICKET, stale MCP session, confabulated blockers)
  plus how to peek inside the shell-less orchestrator with oc-rpc
- sic quick-reference + hard rules (no heredocs, no sic-to-self, remote --user systemd)
- safety: production is never the test target; back up with the service's own mechanism;
  silent-failure surfaces need an explicit post-deploy check; deploy is the operator's call

Companion to docs/ORCHESTRATION.md (mechanics); this is the process.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-24 23:08:26 +02:00
marfrit a850cc95ae bullpen: fix orchestrator reply-wake + JS grinder parser; add onboarding doc
- lurker: opt-in reply-waking via ~/<nick>_lurker/.wakereplies (WAKE_TYPES gains
  "reply"). The default {ask,chat} wake set is reply-deaf, which deadlocks any
  orchestrator running dispatch -> END TURN -> worker-reply-wakes-me (@foreman sat
  waiting for a wake event the lurker filtered away). Loop-safe: from==NICK guard +
  opt-in-only.
- grinder: _resolve_test_rel now matches .test.js / absolute JS spec paths, and
  serve() derives GRIND_REPO from an absolute spec's directory. The JS runner
  (test_kind/run_tests) already existed but the coordinator's ticket parser knew
  only tests/*.py and *_test.go, so every @jsdev ticket was silently bounced.
- docs/ORCHESTRATION.md: agent-readable onboarding for the room/lurker/grinder/
  dispatcher wake + trust protocols, with the three 2026-07-24 failure modes worked.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-24 19:03:38 +02:00
Markus Fritsche bf2c9d07f3 add @reviewer (Fable) + refactor lurker into a systemd @-template
The lurker is now one parameterized watcher (bullpen-lurker <nick>) driven by a
systemd template bullpen-lurker@.service; each instance = a nick with its own
~/<nick>_lurker/ context dir and optional .model override. Two instances:
- @herder  (~/herder_lurker, default Claude model) — infra specialist, re-homed.
- @reviewer (~/reviewer_lurker, .model=fable) — outside-look code/design review.
  It IS Fable (claude --model claude-fable-5), reads the target repo via sic,
  returns a ranked findings list. Same locationing discipline as @herder.
Registered @reviewer in the dispatcher (review/critique/implementation keywords,
distinct from @herder host-ops), bp (600s timeout), skills, docs. Adding a role
is now: a context dir + one enabled template instance, no new code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-20 23:33:53 +02:00
Markus Fritsche 4a38b19a21 rename the infra worker nick @his -> @herder (disambiguate)
@his failed all three naming criteria: its a pronoun (dissolves into any
sentence), an existing repo name (a strong model resolved it to the wrong
noun and went spelunking gitea), and semantically empty. @herder is an
unambiguous role noun that ties to /opt/herding (the fleet infra-tooling
root). Renamed across dispatcher roster, bp, skills (noether/pica/pipi/orca),
docs, and the lurker (script/service/dir his_lurker -> herder_lurker). The
his SUBAGENT + /opt/his-context runbook are untouched (thats the real HIS).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-20 23:11:47 +02:00
Markus Fritsche d5c78c3307 register @his in the dispatcher roster + skills
@his (the infra-specialist lurker) was built but never registered, so nothing
could route to it — a request to assess a host fell through to @librarian. Add
it to the dispatcher ROSTER as the heavyweight: action/host-scoped keywords
(assess/audit/reach/wake/set up/configure/marfrit-packages/on <host>) so it is
escalated only for LIVE host work, not memory recall (that stays @librarian).
Verified: the higgs-inventory query now routes to @his; recall + which-host
still go to @librarian. Skills (noether/pica/pipi/orca) + docs table updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-20 22:48:13 +02:00
Markus Fritsche cfc9f82975 tool-hands @callboy (write_file) + bp shorthand + gc retention
- @callboy gains write_file(name, content): jailed to /var/lib/bullpen/hands/,
  returned as a fetchable "sic hertz cat" handle + /bullpen stash index (never
  the raw content). Small content only — big verbatim text should not round-trip
  the 4B. Mechanical allowlist still enforced (fetch_url + write_file).
- bin/bp: REPL shorthand for room-ask (@/# optional, --from default, researcher
  auto-bumps timeout; no-arg = roster).
- bin/bullpen-gc + timer: daily retention, artifacts >14d / hands >7d, scoped to
  the two scratch dirs (never room.jsonl/COUNTER).
- @dispatcher roster: callboy re-described as tool-hands + write/save-file keywords
  so the new capability is discoverable; dropped librarian s collision-prone
  "notes" keyword (matched filenames like notes.md).
- Docs/skill/README updated; bp shorthand + tool-hands noted across surfaces.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-20 19:32:30 +02:00
Markus Fritsche 19bbba7ab7 add @dispatcher: rule-based routing worker (reply-only, no relay)
Reads a request and names the right worker + the exact room-ask to run;
never answers or forwards it, so a misroute costs one wasted hop. Keyword
match first (no LLM slot burned), one LLM tie-break through the gated proxy
only on ambiguity, full roster on weak signal. Strong debate markers route
to @architect/@skeptic and win over an incidental worker-keyword hit. Roster
manifest in the script is the single source of truth. Docs + skill updated
with a start-here-if-unsure pointer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-20 18:55:17 +02:00
Markus Fritsche 7d20986653 docs: add rich-agent invocation guide (three interaction modes)
Written by Fable. Covers visit->ask->leave, direct post/read, and the
new turn-driven conversation-start mode, plus a gotchas section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EWpfhDgYNA21tETDP9ueBE
2026-07-20 18:47:40 +02:00