feat(skills): add paseo chat coordination
This commit is contained in:
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
name: paseo-chat
|
||||||
|
description: Use chat rooms through a chat helper. Use when the user says "chat room", "room", "coordinate through chat", "shared mailbox", or wants agents to communicate asynchronously.
|
||||||
|
user-invocable: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Paseo Chat Skill
|
||||||
|
|
||||||
|
This skill teaches how to use chat.
|
||||||
|
|
||||||
|
Use `skills/paseo-chat/bin/chat.sh`.
|
||||||
|
|
||||||
|
**User's arguments:** $ARGUMENTS
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Load the **Paseo skill** first if you need CLI guidance for launching or messaging agents.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
When using chat:
|
||||||
|
- create a room with `chat.sh room create` if you need a new room
|
||||||
|
- inspect available rooms with `chat.sh room list` and `chat.sh room show`
|
||||||
|
- post with `chat.sh post`
|
||||||
|
- read with `chat.sh read`
|
||||||
|
- keep reads bounded, usually `--limit 10` or `--limit 20`
|
||||||
|
- check chat often while working
|
||||||
|
|
||||||
|
Do not read or write the backing files directly. Use `chat.sh`.
|
||||||
|
|
||||||
|
Mentions and replies are active:
|
||||||
|
- if you post `@agent-id` in a message, chat will notify that agent immediately
|
||||||
|
- if you use `--reply-to`, chat will notify the author of the replied-to message immediately
|
||||||
|
- notifications are sent with `paseo send --no-wait`
|
||||||
|
|
||||||
|
## Command Surface
|
||||||
|
|
||||||
|
### Create a room
|
||||||
|
|
||||||
|
```bash
|
||||||
|
skills/paseo-chat/bin/chat.sh room create \
|
||||||
|
--room issue-456 \
|
||||||
|
--title "Issue 456 coordination" \
|
||||||
|
--purpose "Coordinate implementation and review"
|
||||||
|
```
|
||||||
|
|
||||||
|
### List rooms
|
||||||
|
|
||||||
|
```bash
|
||||||
|
skills/paseo-chat/bin/chat.sh room list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Show room details
|
||||||
|
|
||||||
|
```bash
|
||||||
|
skills/paseo-chat/bin/chat.sh room show --room issue-456
|
||||||
|
```
|
||||||
|
|
||||||
|
### Post a message
|
||||||
|
|
||||||
|
```bash
|
||||||
|
skills/paseo-chat/bin/chat.sh post \
|
||||||
|
--room issue-456 \
|
||||||
|
--body "I traced the failure to relay auth. Investigating config loading now."
|
||||||
|
```
|
||||||
|
|
||||||
|
Author defaults:
|
||||||
|
- `--agent-id` if provided
|
||||||
|
- otherwise `$PASEO_AGENT_ID`
|
||||||
|
- otherwise `manual`
|
||||||
|
|
||||||
|
Optional reply:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
skills/paseo-chat/bin/chat.sh post \
|
||||||
|
--room issue-456 \
|
||||||
|
--reply-to msg-001 \
|
||||||
|
--body "I can take that next."
|
||||||
|
```
|
||||||
|
|
||||||
|
Direct mention:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
skills/paseo-chat/bin/chat.sh post \
|
||||||
|
--room issue-456 \
|
||||||
|
--body "@agent-beta can you verify the relay path next?"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read recent messages
|
||||||
|
|
||||||
|
```bash
|
||||||
|
skills/paseo-chat/bin/chat.sh read --room issue-456 --limit 10
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filter reads
|
||||||
|
|
||||||
|
```bash
|
||||||
|
skills/paseo-chat/bin/chat.sh read --room issue-456 --agent-id 123abc
|
||||||
|
skills/paseo-chat/bin/chat.sh read --room issue-456 --since 2026-03-24T10:00:00Z
|
||||||
|
```
|
||||||
|
|
||||||
|
## Defaults
|
||||||
|
|
||||||
|
When creating a room:
|
||||||
|
- choose a short explicit room id
|
||||||
|
- prefer slugs like `issue-456`, `pr-143-review`, `feature/relay-cleanup`
|
||||||
|
- give the room a clear title and purpose
|
||||||
|
|
||||||
|
When using a room:
|
||||||
|
- read only a bounded window before acting
|
||||||
|
- post updates when they would help another agent or your future self
|
||||||
|
- use `--reply-to` when responding to a specific message
|
||||||
|
- use `@agent-id` when you want to get a specific agent's attention
|
||||||
|
- check chat frequently enough that shared coordination actually works
|
||||||
|
|
||||||
|
Typical things to post:
|
||||||
|
- status updates
|
||||||
|
- blockers
|
||||||
|
- handoffs
|
||||||
|
- review findings
|
||||||
|
- important context and memories another agent may need later
|
||||||
|
|
||||||
|
## Your Job
|
||||||
|
|
||||||
|
1. Understand whether you should use an existing room or create a new one
|
||||||
|
2. Choose a room id and title
|
||||||
|
3. Create the room with `chat.sh room create` if needed
|
||||||
|
4. Read the room with bounded history
|
||||||
|
5. Post clearly
|
||||||
|
6. Use `--reply-to` when replying to a specific message
|
||||||
|
7. Use `@agent-id` when you want to notify someone directly
|
||||||
Executable
+415
@@ -0,0 +1,415 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage:
|
||||||
|
chat.sh room create --room ROOM [--title TITLE] [--purpose PURPOSE]
|
||||||
|
chat.sh room list
|
||||||
|
chat.sh room show --room ROOM
|
||||||
|
chat.sh post --room ROOM (--body TEXT | --body-file PATH) [--agent-id ID] [--agent-name NAME] [--reply-to MESSAGE_ID]
|
||||||
|
chat.sh read --room ROOM [--limit N] [--since ISO_TIMESTAMP] [--agent-id ID]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--root PATH Override chat root (default: ~/.paseo/chat)
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
yaml_quote() {
|
||||||
|
local value="${1//\'/\'\'}"
|
||||||
|
printf "'%s'" "$value"
|
||||||
|
}
|
||||||
|
|
||||||
|
require_command() {
|
||||||
|
local name="$1"
|
||||||
|
command -v "$name" >/dev/null 2>&1 || {
|
||||||
|
echo "Error: required command not found: $name" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sanitize_room_path() {
|
||||||
|
local room="$1"
|
||||||
|
if [[ -z "$room" || "$room" == /* || "$room" == *".."* ]]; then
|
||||||
|
echo "Error: invalid room id: $room" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
load_body() {
|
||||||
|
local inline_value="$1"
|
||||||
|
local file_value="$2"
|
||||||
|
|
||||||
|
if [[ -n "$inline_value" && -n "$file_value" ]]; then
|
||||||
|
echo "Error: use either --body or --body-file, not both" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$file_value" ]]; then
|
||||||
|
[[ -f "$file_value" ]] || { echo "Error: --body-file not found: $file_value" >&2; exit 1; }
|
||||||
|
cat "$file_value"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$inline_value" ]]; then
|
||||||
|
printf '%s' "$inline_value"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Error: one of --body or --body-file is required" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
frontmatter_value() {
|
||||||
|
local key="$1"
|
||||||
|
local file="$2"
|
||||||
|
awk -F': ' -v search_key="$key" '
|
||||||
|
BEGIN { in_frontmatter = 0 }
|
||||||
|
/^---$/ {
|
||||||
|
if (in_frontmatter == 0) {
|
||||||
|
in_frontmatter = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
in_frontmatter == 1 && $1 == search_key {
|
||||||
|
value = substr($0, length(search_key) + 3)
|
||||||
|
gsub(/^'\''|'\''$/, "", value)
|
||||||
|
print value
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
' "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_message() {
|
||||||
|
local file="$1"
|
||||||
|
local created_at agent_id agent_name reply_to message_id
|
||||||
|
created_at="$(frontmatter_value "created_at" "$file")"
|
||||||
|
agent_id="$(frontmatter_value "agent_id" "$file")"
|
||||||
|
agent_name="$(frontmatter_value "agent_name" "$file")"
|
||||||
|
reply_to="$(frontmatter_value "reply_to" "$file")"
|
||||||
|
message_id="$(frontmatter_value "message_id" "$file")"
|
||||||
|
|
||||||
|
printf '### %s · %s' "$created_at" "$agent_id"
|
||||||
|
if [[ -n "$agent_name" ]]; then
|
||||||
|
printf ' (%s)' "$agent_name"
|
||||||
|
fi
|
||||||
|
printf '\n'
|
||||||
|
printf 'message_id: %s\n' "$message_id"
|
||||||
|
if [[ -n "$reply_to" ]]; then
|
||||||
|
printf 'reply_to: %s\n' "$reply_to"
|
||||||
|
fi
|
||||||
|
printf '\n'
|
||||||
|
|
||||||
|
awk '
|
||||||
|
BEGIN { delim_count = 0 }
|
||||||
|
/^---$/ {
|
||||||
|
delim_count += 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
delim_count >= 2 {
|
||||||
|
print
|
||||||
|
}
|
||||||
|
' "$file"
|
||||||
|
printf '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
require_room() {
|
||||||
|
local room="$1"
|
||||||
|
local room_dir="$rooms_root/$room"
|
||||||
|
[[ -d "$room_dir" ]] || { echo "Error: room not found: $room" >&2; exit 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
find_message_file_by_id() {
|
||||||
|
local room="$1"
|
||||||
|
local message_id="$2"
|
||||||
|
find "$rooms_root/$room/messages" -name '*.md' -type f -print0 |
|
||||||
|
while IFS= read -r -d '' file; do
|
||||||
|
if [[ "$(frontmatter_value "message_id" "$file")" == "$message_id" ]]; then
|
||||||
|
printf '%s\n' "$file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
extract_mentions() {
|
||||||
|
local body="$1"
|
||||||
|
printf '%s\n' "$body" | grep -oE '@[A-Za-z0-9._:-]+' | sed 's/^@//' | awk '!seen[$0]++'
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_agent() {
|
||||||
|
local target_agent_id="$1"
|
||||||
|
local room="$2"
|
||||||
|
local sender_agent_id="$3"
|
||||||
|
local sender_agent_name="$4"
|
||||||
|
local message_id="$5"
|
||||||
|
local reason="$6"
|
||||||
|
|
||||||
|
if [[ -z "$target_agent_id" || "$target_agent_id" == "manual" || "$target_agent_id" == "$sender_agent_id" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local sender_label="$sender_agent_id"
|
||||||
|
if [[ -n "$sender_agent_name" ]]; then
|
||||||
|
sender_label="$sender_agent_name ($sender_agent_id)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local notification="You have a new chat message.
|
||||||
|
|
||||||
|
Room: $room
|
||||||
|
From: $sender_label
|
||||||
|
Message ID: $message_id
|
||||||
|
Reason: $reason
|
||||||
|
|
||||||
|
To read it:
|
||||||
|
skills/paseo-chat/bin/chat.sh read --room $room --limit 10"
|
||||||
|
|
||||||
|
"$paseo_bin" send --no-wait "$target_agent_id" "$notification" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
require_command uuidgen
|
||||||
|
|
||||||
|
chat_root="${HOME}/.paseo/chat"
|
||||||
|
paseo_bin="${PASEO_CHAT_PASEO_BIN:-paseo}"
|
||||||
|
|
||||||
|
if [[ $# -lt 1 ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$1" == "--root" ]]; then
|
||||||
|
[[ $# -ge 3 ]] || usage
|
||||||
|
chat_root="$2"
|
||||||
|
shift 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
rooms_root="${chat_root}/rooms"
|
||||||
|
mkdir -p "$rooms_root"
|
||||||
|
|
||||||
|
command_name="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
case "$command_name" in
|
||||||
|
room)
|
||||||
|
[[ $# -ge 1 ]] || usage
|
||||||
|
room_subcommand="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
case "$room_subcommand" in
|
||||||
|
create)
|
||||||
|
room=""
|
||||||
|
title=""
|
||||||
|
purpose=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--room) room="$2"; shift 2 ;;
|
||||||
|
--title) title="$2"; shift 2 ;;
|
||||||
|
--purpose) purpose="$2"; shift 2 ;;
|
||||||
|
*) echo "Unknown option: $1" >&2; usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -n "$room" ]] || { echo "Error: --room is required" >&2; exit 1; }
|
||||||
|
sanitize_room_path "$room"
|
||||||
|
|
||||||
|
room_dir="$rooms_root/$room"
|
||||||
|
messages_dir="$room_dir/messages"
|
||||||
|
mkdir -p "$messages_dir"
|
||||||
|
|
||||||
|
if [[ -z "$title" ]]; then
|
||||||
|
title="$room"
|
||||||
|
fi
|
||||||
|
|
||||||
|
created_at="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
|
||||||
|
room_file="$room_dir/room.md"
|
||||||
|
if [[ ! -f "$room_file" ]]; then
|
||||||
|
printf '%s\n' \
|
||||||
|
"---" \
|
||||||
|
"room: $(yaml_quote "$room")" \
|
||||||
|
"title: $(yaml_quote "$title")" \
|
||||||
|
"purpose: $(yaml_quote "$purpose")" \
|
||||||
|
"created_at: $(yaml_quote "$created_at")" \
|
||||||
|
"---" \
|
||||||
|
"" \
|
||||||
|
"# $(printf '%s' "$title")" \
|
||||||
|
"" \
|
||||||
|
"$(printf '%s' "$purpose")" > "$room_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'created room %s\n' "$room"
|
||||||
|
;;
|
||||||
|
|
||||||
|
list)
|
||||||
|
while IFS= read -r room_file; do
|
||||||
|
room_id="${room_file#"$rooms_root"/}"
|
||||||
|
room_id="${room_id%/room.md}"
|
||||||
|
printf '%s\n' "$room_id"
|
||||||
|
done < <(find "$rooms_root" -name room.md -type f | sort)
|
||||||
|
;;
|
||||||
|
|
||||||
|
show)
|
||||||
|
room=""
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--room) room="$2"; shift 2 ;;
|
||||||
|
*) echo "Unknown option: $1" >&2; usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -n "$room" ]] || { echo "Error: --room is required" >&2; exit 1; }
|
||||||
|
sanitize_room_path "$room"
|
||||||
|
require_room "$room"
|
||||||
|
|
||||||
|
room_file="$rooms_root/$room/room.md"
|
||||||
|
title="$(frontmatter_value "title" "$room_file")"
|
||||||
|
purpose="$(frontmatter_value "purpose" "$room_file")"
|
||||||
|
created_at="$(frontmatter_value "created_at" "$room_file")"
|
||||||
|
message_count="$(find "$rooms_root/$room/messages" -name '*.md' -type f | wc -l | tr -d ' ')"
|
||||||
|
|
||||||
|
printf 'room: %s\n' "$room"
|
||||||
|
printf 'title: %s\n' "$title"
|
||||||
|
printf 'purpose: %s\n' "$purpose"
|
||||||
|
printf 'created_at: %s\n' "$created_at"
|
||||||
|
printf 'messages: %s\n' "$message_count"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
|
||||||
|
post)
|
||||||
|
room=""
|
||||||
|
body_input=""
|
||||||
|
body_file=""
|
||||||
|
agent_id="${PASEO_AGENT_ID:-manual}"
|
||||||
|
agent_name=""
|
||||||
|
reply_to=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--room) room="$2"; shift 2 ;;
|
||||||
|
--body) body_input="$2"; shift 2 ;;
|
||||||
|
--body-file) body_file="$2"; shift 2 ;;
|
||||||
|
--agent-id) agent_id="$2"; shift 2 ;;
|
||||||
|
--agent-name) agent_name="$2"; shift 2 ;;
|
||||||
|
--reply-to) reply_to="$2"; shift 2 ;;
|
||||||
|
*) echo "Unknown option: $1" >&2; usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -n "$room" ]] || { echo "Error: --room is required" >&2; exit 1; }
|
||||||
|
sanitize_room_path "$room"
|
||||||
|
require_room "$room"
|
||||||
|
body="$(load_body "$body_input" "$body_file")"
|
||||||
|
|
||||||
|
created_at="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
|
||||||
|
created_at_file="$(date -u +'%Y-%m-%dT%H-%M-%SZ')"
|
||||||
|
message_id="msg-$(uuidgen | tr '[:upper:]' '[:lower:]' | tr -d '-' | cut -c1-8)"
|
||||||
|
agent_slug="$(printf '%s' "$agent_id" | tr '/ :@' '_' | tr -cd '[:alnum:]_.-')"
|
||||||
|
[[ -n "$agent_slug" ]] || agent_slug="manual"
|
||||||
|
message_file="$rooms_root/$room/messages/${created_at_file}__${agent_slug}__${message_id}.md"
|
||||||
|
|
||||||
|
printf '%s\n' \
|
||||||
|
"---" \
|
||||||
|
"room: $(yaml_quote "$room")" \
|
||||||
|
"message_id: $(yaml_quote "$message_id")" \
|
||||||
|
"agent_id: $(yaml_quote "$agent_id")" \
|
||||||
|
"agent_name: $(yaml_quote "$agent_name")" \
|
||||||
|
"created_at: $(yaml_quote "$created_at")" \
|
||||||
|
"reply_to: $(yaml_quote "$reply_to")" \
|
||||||
|
"---" \
|
||||||
|
"" \
|
||||||
|
"$body" > "$message_file"
|
||||||
|
|
||||||
|
notified_agents=()
|
||||||
|
if [[ -n "$reply_to" ]]; then
|
||||||
|
reply_file="$(find_message_file_by_id "$room" "$reply_to" || true)"
|
||||||
|
if [[ -n "$reply_file" ]]; then
|
||||||
|
reply_target_agent_id="$(frontmatter_value "agent_id" "$reply_file")"
|
||||||
|
notify_agent "$reply_target_agent_id" "$room" "$agent_id" "$agent_name" "$message_id" "reply to $reply_to"
|
||||||
|
notified_agents+=("$reply_target_agent_id")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS= read -r mentioned_agent_id; do
|
||||||
|
[[ -n "$mentioned_agent_id" ]] || continue
|
||||||
|
already_notified=false
|
||||||
|
for existing_id in "${notified_agents[@]}"; do
|
||||||
|
if [[ "$existing_id" == "$mentioned_agent_id" ]]; then
|
||||||
|
already_notified=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ "$already_notified" == false ]]; then
|
||||||
|
notify_agent "$mentioned_agent_id" "$room" "$agent_id" "$agent_name" "$message_id" "direct mention"
|
||||||
|
notified_agents+=("$mentioned_agent_id")
|
||||||
|
fi
|
||||||
|
done < <(extract_mentions "$body")
|
||||||
|
|
||||||
|
printf '%s\n' "$message_id"
|
||||||
|
;;
|
||||||
|
|
||||||
|
read)
|
||||||
|
room=""
|
||||||
|
limit="20"
|
||||||
|
since=""
|
||||||
|
agent_id_filter=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--room) room="$2"; shift 2 ;;
|
||||||
|
--limit) limit="$2"; shift 2 ;;
|
||||||
|
--since) since="$2"; shift 2 ;;
|
||||||
|
--agent-id) agent_id_filter="$2"; shift 2 ;;
|
||||||
|
*) echo "Unknown option: $1" >&2; usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -n "$room" ]] || { echo "Error: --room is required" >&2; exit 1; }
|
||||||
|
sanitize_room_path "$room"
|
||||||
|
require_room "$room"
|
||||||
|
|
||||||
|
messages_dir="$rooms_root/$room/messages"
|
||||||
|
mapfile -t all_files < <(find "$messages_dir" -name '*.md' -type f | sort)
|
||||||
|
|
||||||
|
filtered_files=()
|
||||||
|
for file in "${all_files[@]}"; do
|
||||||
|
created_at="$(frontmatter_value "created_at" "$file")"
|
||||||
|
file_agent_id="$(frontmatter_value "agent_id" "$file")"
|
||||||
|
|
||||||
|
if [[ -n "$since" && "$created_at" < "$since" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ -n "$agent_id_filter" && "$file_agent_id" != "$agent_id_filter" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
filtered_files+=("$file")
|
||||||
|
done
|
||||||
|
|
||||||
|
start_index=0
|
||||||
|
if [[ "$limit" != "all" ]]; then
|
||||||
|
if ! [[ "$limit" =~ ^[0-9]+$ ]]; then
|
||||||
|
echo "Error: --limit must be a number or 'all'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "${#filtered_files[@]}" -gt "$limit" ]]; then
|
||||||
|
start_index=$((${#filtered_files[@]} - limit))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
for ((index = start_index; index < ${#filtered_files[@]}; index += 1)); do
|
||||||
|
print_message "${filtered_files[$index]}"
|
||||||
|
if [[ $index -lt $((${#filtered_files[@]} - 1)) ]]; then
|
||||||
|
printf -- '---\n\n'
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -43,6 +43,32 @@ Before any agent starts working, align with the user on logistics:
|
|||||||
|
|
||||||
These questions prevent wasted work. A perfectly implemented feature in the wrong branch or without a PR is still a failure.
|
These questions prevent wasted work. A perfectly implemented feature in the wrong branch or without a PR is still a failure.
|
||||||
|
|
||||||
|
## Chat Rooms
|
||||||
|
|
||||||
|
When agents need asynchronous coordination, shared status, or a lightweight handoff channel, use chat rooms.
|
||||||
|
|
||||||
|
If you decide chat would help:
|
||||||
|
- create a room for the task
|
||||||
|
- tell agents the exact room id
|
||||||
|
- tell agents to load the `paseo-chat` skill
|
||||||
|
- tell agents to use `skills/paseo-chat/bin/chat.sh` for reading and posting
|
||||||
|
- tell agents to post memories, useful context, findings, blockers, and handoffs there
|
||||||
|
- tell agents to check chat very often while they are working
|
||||||
|
|
||||||
|
Use chat when:
|
||||||
|
- multiple agents need to coordinate without constant orchestrator relays
|
||||||
|
- review findings should be visible to other agents
|
||||||
|
- a task benefits from a shared running log
|
||||||
|
|
||||||
|
When you launch planning, implementation, investigation, or review agents and chat is in play:
|
||||||
|
- require them to add their findings to the room
|
||||||
|
- require them to read recent chat before acting
|
||||||
|
- require them to post back when they discover something another agent may need
|
||||||
|
|
||||||
|
Chat is not just passive storage. Mentions and replies trigger direct notifications through chat, so agents can actively get each other's attention.
|
||||||
|
|
||||||
|
Do not assume chat is required for every orchestration. Use it when it adds coordination value.
|
||||||
|
|
||||||
## Agent Types
|
## Agent Types
|
||||||
|
|
||||||
Implementation and review are not the only agent roles. Use the right agent for the job:
|
Implementation and review are not the only agent roles. Use the right agent for the job:
|
||||||
@@ -55,6 +81,50 @@ Implementation and review are not the only agent roles. Use the right agent for
|
|||||||
|
|
||||||
Don't limit yourself to implement → review. Explore first if you need context. Get a second opinion if the design is tricky. The user is paying for thoroughness, not speed.
|
Don't limit yourself to implement → review. Explore first if you need context. Get a second opinion if the design is tricky. The user is paying for thoroughness, not speed.
|
||||||
|
|
||||||
|
## Naming Agents
|
||||||
|
|
||||||
|
Name sub-agents in kebab-case and include both role and scope.
|
||||||
|
|
||||||
|
Use this format:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<role>-<scope>[-<slice>]
|
||||||
|
```
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
- `plan-issue-456`
|
||||||
|
- `impl-issue-456`
|
||||||
|
- `review-issue-456`
|
||||||
|
- `test-issue-456`
|
||||||
|
- `qa-issue-456`
|
||||||
|
- `refactor-relay-auth`
|
||||||
|
- `investigate-ci-flake`
|
||||||
|
- `explore-agent-chat`
|
||||||
|
- `verify-pr-143`
|
||||||
|
- `impl-issue-456-api`
|
||||||
|
|
||||||
|
Approved role prefixes:
|
||||||
|
- `plan`
|
||||||
|
- `impl`
|
||||||
|
- `review`
|
||||||
|
- `test`
|
||||||
|
- `qa`
|
||||||
|
- `verify`
|
||||||
|
- `investigate`
|
||||||
|
- `explore`
|
||||||
|
- `refactor`
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
- always use kebab-case
|
||||||
|
- no spaces
|
||||||
|
- no emoji
|
||||||
|
- no brackets
|
||||||
|
- no vague names
|
||||||
|
- always include the task scope
|
||||||
|
- add a final slice only when needed to disambiguate
|
||||||
|
|
||||||
|
Good names make chat, mentions, logs, and agent lists much easier to use.
|
||||||
|
|
||||||
## How to Write Agent Prompts
|
## How to Write Agent Prompts
|
||||||
|
|
||||||
This is the most important skill. A good prompt produces good work. A bad prompt produces wasted time.
|
This is the most important skill. A good prompt produces good work. A bad prompt produces wasted time.
|
||||||
@@ -125,6 +195,13 @@ Agents start with **zero knowledge** of your conversation. Everything they need
|
|||||||
- What decisions were made
|
- What decisions were made
|
||||||
- What was already tried
|
- What was already tried
|
||||||
|
|
||||||
|
If agents should coordinate through chat, include:
|
||||||
|
- the room id
|
||||||
|
- the instruction to load `paseo-chat`
|
||||||
|
- what they should post there
|
||||||
|
- that they should check it very often
|
||||||
|
- that they should use `@agent-id` and replies when they want to notify someone directly
|
||||||
|
|
||||||
## Always Review
|
## Always Review
|
||||||
|
|
||||||
After every implementation agent finishes, spin up a **review agent** to independently verify the work.
|
After every implementation agent finishes, spin up a **review agent** to independently verify the work.
|
||||||
|
|||||||
Reference in New Issue
Block a user