@mootup/moot-templates 0.1.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
- package/templates/CLAUDE.md +233 -0
- package/templates/claude/hooks/auto-orient.sh +21 -0
- package/templates/claude/hooks/git-guard.sh +56 -0
- package/templates/claude/hooks/grep-baseline-diff.sh +41 -0
- package/templates/claude/hooks/handoff-status-check.sh +40 -0
- package/templates/claude/settings.json +51 -0
- package/templates/devcontainer/devcontainer.json +25 -0
- package/templates/devcontainer/post-create.sh +68 -0
- package/templates/devcontainer/run-moot-channel.sh +70 -0
- package/templates/devcontainer/run-moot-mcp.sh +74 -0
- package/templates/devcontainer/run-moot-notify.sh +59 -0
- package/templates/skills/doc-curation/SKILL.md +80 -0
- package/templates/skills/handoff/SKILL.md +46 -0
- package/templates/skills/leader-workflow/SKILL.md +135 -0
- package/templates/skills/librarian-workflow/SKILL.md +50 -0
- package/templates/skills/memory-audit/SKILL.md +85 -0
- package/templates/skills/product-workflow/SKILL.md +69 -0
- package/templates/skills/spec-checklist/SKILL.md +99 -0
- package/templates/skills/verify/SKILL.md +64 -0
- package/templates/teams/loop-3/CLAUDE.md +72 -0
- package/templates/teams/loop-3/README.md +6 -0
- package/templates/teams/loop-3/team.toml +108 -0
- package/templates/teams/loop-4/CLAUDE.md +72 -0
- package/templates/teams/loop-4/README.md +6 -0
- package/templates/teams/loop-4/team.toml +126 -0
- package/templates/teams/loop-4-observer/CLAUDE.md +76 -0
- package/templates/teams/loop-4-observer/README.md +7 -0
- package/templates/teams/loop-4-observer/team.toml +141 -0
- package/templates/teams/loop-4-parallel/CLAUDE.md +76 -0
- package/templates/teams/loop-4-parallel/README.md +6 -0
- package/templates/teams/loop-4-parallel/team.toml +142 -0
- package/templates/teams/loop-4-split-leader/CLAUDE.md +76 -0
- package/templates/teams/loop-4-split-leader/README.md +7 -0
- package/templates/teams/loop-4-split-leader/team.toml +140 -0
- package/templates/teams/loop-6/CLAUDE.md +43 -0
- package/templates/teams/loop-6/README.md +9 -0
- package/templates/teams/loop-6/team.toml +161 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# System packages
|
|
5
|
+
sudo apt-get update && sudo apt-get install -y tmux
|
|
6
|
+
|
|
7
|
+
# Claude Code CLI — install from npm first (puts `claude` on PATH
|
|
8
|
+
# via /usr/local/share/npm-global/bin), use it to register MCP servers,
|
|
9
|
+
# then call `claude install` to migrate to the native build at
|
|
10
|
+
# ~/.local/bin. The native build is the officially-supported path
|
|
11
|
+
# going forward; the TUI nags on first run when it's still npm-based.
|
|
12
|
+
npm install -g @anthropic-ai/claude-code
|
|
13
|
+
|
|
14
|
+
# Python tooling
|
|
15
|
+
pip install uv
|
|
16
|
+
|
|
17
|
+
# Install moot package
|
|
18
|
+
pip install mootup
|
|
19
|
+
|
|
20
|
+
# Register MCP servers for Claude Code at user scope so claude finds
|
|
21
|
+
# them regardless of cwd (agents launch in worktrees under .worktrees/,
|
|
22
|
+
# not the project root). Use absolute paths to the wrapper scripts so
|
|
23
|
+
# they resolve from any cwd. The wrappers read CONVO_ROLE at runtime
|
|
24
|
+
# to look up the per-role API key from .moot/actors.json.
|
|
25
|
+
DEVCONTAINER_DIR="$(realpath .devcontainer)"
|
|
26
|
+
claude mcp add convo "$DEVCONTAINER_DIR/run-moot-mcp.sh" -s user
|
|
27
|
+
claude mcp add convo-channel "$DEVCONTAINER_DIR/run-moot-channel.sh" -s user
|
|
28
|
+
|
|
29
|
+
# Migrate from the npm-installed claude to the native build. This runs
|
|
30
|
+
# LAST (after `claude mcp add`) because `claude install` deletes the
|
|
31
|
+
# npm symlink — anything calling `claude` after this point must rely on
|
|
32
|
+
# ~/.local/bin/claude, which `bash -lc` picks up via ~/.profile's
|
|
33
|
+
# standard "$HOME/.local/bin" snippet. Agent tmux sessions launch with
|
|
34
|
+
# `bash -lc`, so they find the native binary automatically.
|
|
35
|
+
claude install
|
|
36
|
+
|
|
37
|
+
# Rebind tmux prefix to Ctrl-Space. Claude Code intercepts Ctrl-B (the
|
|
38
|
+
# default prefix), so the usual `Ctrl-B d` detach never reaches tmux.
|
|
39
|
+
# Ctrl-Space is rarely claimed by TUIs and leaves readline-style editing
|
|
40
|
+
# bindings (Ctrl-A/E/etc.) untouched inside claude's input line.
|
|
41
|
+
cat > /home/node/.tmux.conf <<'TMUX_CONF'
|
|
42
|
+
unbind C-b
|
|
43
|
+
set -g prefix C-Space
|
|
44
|
+
bind C-Space send-prefix
|
|
45
|
+
|
|
46
|
+
# Mouse on: scroll-wheel scrolls the pane, click selects a pane/window,
|
|
47
|
+
# drag copies. Without this, scrollback is only reachable via the
|
|
48
|
+
# copy-mode keybind (<prefix> [) which is a tmux-literacy tax users
|
|
49
|
+
# shouldn't have to pay just to read recent output.
|
|
50
|
+
set -g mouse on
|
|
51
|
+
TMUX_CONF
|
|
52
|
+
|
|
53
|
+
# Register a /detach slash command for claude so the user can leave a
|
|
54
|
+
# tmux session without having to fight for the prefix key. The command
|
|
55
|
+
# calls `tmux detach-client`, which disconnects the terminal but leaves
|
|
56
|
+
# claude running in the session so `moot attach` picks up where it left
|
|
57
|
+
# off. User-scope so every worktree sees it.
|
|
58
|
+
mkdir -p /home/node/.claude/commands
|
|
59
|
+
cat > /home/node/.claude/commands/detach.md <<'DETACH_MD'
|
|
60
|
+
---
|
|
61
|
+
description: Detach from the tmux session (leaves claude running in the background)
|
|
62
|
+
allowed-tools: Bash(bash:*)
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
!bash -c 'SOCK=$(find /tmp /run -maxdepth 3 -name default -type s 2>/dev/null | head -1); if [ -n "$SOCK" ]; then tmux -S "$SOCK" detach-client; else echo "tmux socket not found"; fi'
|
|
66
|
+
DETACH_MD
|
|
67
|
+
|
|
68
|
+
echo "Container ready."
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Channel adapter wrapper — reads CONVO_ROLE and looks up API key
|
|
3
|
+
# from .moot/actors.json. Same logic as run-moot-mcp.sh.
|
|
4
|
+
|
|
5
|
+
ROLE="${CONVO_ROLE:-implementation}"
|
|
6
|
+
ACTORS_FILE=".moot/actors.json"
|
|
7
|
+
|
|
8
|
+
# Find project root (walk up to moot.toml)
|
|
9
|
+
PROJECT_ROOT="$(pwd)"
|
|
10
|
+
while [ "$PROJECT_ROOT" != "/" ]; do
|
|
11
|
+
[ -f "$PROJECT_ROOT/moot.toml" ] && break
|
|
12
|
+
PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
|
|
13
|
+
done
|
|
14
|
+
|
|
15
|
+
# Read per-role actor identity from .moot/actors.json. See run-moot-mcp.sh
|
|
16
|
+
# for the full rationale — same rule applies to the channel adapter.
|
|
17
|
+
if [ -f "$PROJECT_ROOT/$ACTORS_FILE" ]; then
|
|
18
|
+
eval $(python3 -c "
|
|
19
|
+
import json, shlex
|
|
20
|
+
with open('$PROJECT_ROOT/$ACTORS_FILE') as f:
|
|
21
|
+
data = json.load(f)
|
|
22
|
+
entry = data.get('actors', {}).get('$ROLE', {})
|
|
23
|
+
print('KEY=' + shlex.quote(entry.get('api_key', '')))
|
|
24
|
+
print('AID=' + shlex.quote(entry.get('actor_id', '')))
|
|
25
|
+
print('ANAME=' + shlex.quote(entry.get('display_name', '$ROLE')))
|
|
26
|
+
" 2>/dev/null)
|
|
27
|
+
if [ -n "$KEY" ]; then
|
|
28
|
+
export CONVO_API_KEY="$KEY"
|
|
29
|
+
else
|
|
30
|
+
echo "WARNING: No API key for role '$ROLE' in $ACTORS_FILE" >&2
|
|
31
|
+
fi
|
|
32
|
+
[ -n "$AID" ] && export CONVO_AGENT_ID="$AID"
|
|
33
|
+
[ -n "$ANAME" ] && export CONVO_AGENT_NAME="$ANAME"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Read API URL from moot.toml
|
|
37
|
+
if [ -z "$CONVO_API_URL" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
|
|
38
|
+
URL=$(python3 -c "
|
|
39
|
+
import tomllib
|
|
40
|
+
with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
|
|
41
|
+
data = tomllib.load(f)
|
|
42
|
+
print(data.get('convo', {}).get('api_url', ''))
|
|
43
|
+
" 2>/dev/null)
|
|
44
|
+
if [ -n "$URL" ]; then
|
|
45
|
+
export CONVO_API_URL="$URL"
|
|
46
|
+
fi
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Read space ID from moot.toml
|
|
50
|
+
if [ -z "$CONVO_SPACE_ID" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
|
|
51
|
+
SID=$(python3 -c "
|
|
52
|
+
import tomllib
|
|
53
|
+
with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
|
|
54
|
+
data = tomllib.load(f)
|
|
55
|
+
print(data.get('convo', {}).get('space_id', ''))
|
|
56
|
+
" 2>/dev/null)
|
|
57
|
+
if [ -n "$SID" ]; then
|
|
58
|
+
export CONVO_SPACE_ID="$SID"
|
|
59
|
+
fi
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Alpha-grade diagnostics: DEBUG-level logs to a per-role file under
|
|
63
|
+
# .moot/logs/ in the project root. Bind-mounted to the host so users
|
|
64
|
+
# and support can grep and share the logs without docker exec.
|
|
65
|
+
# Override with MOOT_LOG_LEVEL=INFO (or higher) once alpha stabilizes.
|
|
66
|
+
LOG_DIR="$PROJECT_ROOT/.moot/logs"
|
|
67
|
+
mkdir -p "$LOG_DIR"
|
|
68
|
+
LOG_FILE="$LOG_DIR/channel-${ROLE}.log"
|
|
69
|
+
export MOOT_LOG_LEVEL="${MOOT_LOG_LEVEL:-DEBUG}"
|
|
70
|
+
exec python -u -m moot.adapters.channel_runner "$@" 2>> "$LOG_FILE"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# MCP adapter wrapper — reads CONVO_ROLE and looks up API key
|
|
3
|
+
# from .moot/actors.json. Set CONVO_ROLE before launching Claude Code
|
|
4
|
+
# to pick a different identity.
|
|
5
|
+
|
|
6
|
+
ROLE="${CONVO_ROLE:-implementation}"
|
|
7
|
+
ACTORS_FILE=".moot/actors.json"
|
|
8
|
+
|
|
9
|
+
# Find project root (walk up to moot.toml)
|
|
10
|
+
PROJECT_ROOT="$(pwd)"
|
|
11
|
+
while [ "$PROJECT_ROOT" != "/" ]; do
|
|
12
|
+
[ -f "$PROJECT_ROOT/moot.toml" ] && break
|
|
13
|
+
PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
|
|
14
|
+
done
|
|
15
|
+
|
|
16
|
+
# Read per-role actor identity from .moot/actors.json. We MUST export
|
|
17
|
+
# CONVO_AGENT_ID and CONVO_AGENT_NAME — the mcp_runner defaults them to
|
|
18
|
+
# "unknown-agent", and the backend rejects any post whose agent_id in the
|
|
19
|
+
# body doesn't match the authenticated actor (HTTP 400, which the adapter
|
|
20
|
+
# surfaces as an empty event_id).
|
|
21
|
+
if [ -f "$PROJECT_ROOT/$ACTORS_FILE" ]; then
|
|
22
|
+
eval $(python3 -c "
|
|
23
|
+
import json, shlex
|
|
24
|
+
with open('$PROJECT_ROOT/$ACTORS_FILE') as f:
|
|
25
|
+
data = json.load(f)
|
|
26
|
+
entry = data.get('actors', {}).get('$ROLE', {})
|
|
27
|
+
print('KEY=' + shlex.quote(entry.get('api_key', '')))
|
|
28
|
+
print('AID=' + shlex.quote(entry.get('actor_id', '')))
|
|
29
|
+
print('ANAME=' + shlex.quote(entry.get('display_name', '$ROLE')))
|
|
30
|
+
" 2>/dev/null)
|
|
31
|
+
if [ -n "$KEY" ]; then
|
|
32
|
+
export CONVO_API_KEY="$KEY"
|
|
33
|
+
else
|
|
34
|
+
echo "WARNING: No API key for role '$ROLE' in $ACTORS_FILE" >&2
|
|
35
|
+
fi
|
|
36
|
+
[ -n "$AID" ] && export CONVO_AGENT_ID="$AID"
|
|
37
|
+
[ -n "$ANAME" ] && export CONVO_AGENT_NAME="$ANAME"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Read API URL from moot.toml
|
|
41
|
+
if [ -z "$CONVO_API_URL" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
|
|
42
|
+
URL=$(python3 -c "
|
|
43
|
+
import tomllib
|
|
44
|
+
with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
|
|
45
|
+
data = tomllib.load(f)
|
|
46
|
+
print(data.get('convo', {}).get('api_url', ''))
|
|
47
|
+
" 2>/dev/null)
|
|
48
|
+
if [ -n "$URL" ]; then
|
|
49
|
+
export CONVO_API_URL="$URL"
|
|
50
|
+
fi
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# Read space ID from moot.toml
|
|
54
|
+
if [ -z "$CONVO_SPACE_ID" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
|
|
55
|
+
SID=$(python3 -c "
|
|
56
|
+
import tomllib
|
|
57
|
+
with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
|
|
58
|
+
data = tomllib.load(f)
|
|
59
|
+
print(data.get('convo', {}).get('space_id', ''))
|
|
60
|
+
" 2>/dev/null)
|
|
61
|
+
if [ -n "$SID" ]; then
|
|
62
|
+
export CONVO_SPACE_ID="$SID"
|
|
63
|
+
fi
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Alpha-grade diagnostics: DEBUG-level logs to a per-role file under
|
|
67
|
+
# .moot/logs/ in the project root. Bind-mounted to the host so users
|
|
68
|
+
# and support can grep and share the logs without docker exec.
|
|
69
|
+
# Override with MOOT_LOG_LEVEL=INFO (or higher) once alpha stabilizes.
|
|
70
|
+
LOG_DIR="$PROJECT_ROOT/.moot/logs"
|
|
71
|
+
mkdir -p "$LOG_DIR"
|
|
72
|
+
LOG_FILE="$LOG_DIR/mcp-${ROLE}.log"
|
|
73
|
+
export MOOT_LOG_LEVEL="${MOOT_LOG_LEVEL:-DEBUG}"
|
|
74
|
+
exec python -u -m moot.adapters.mcp_runner "$@" 2>> "$LOG_FILE"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tmux notification daemon wrapper -- reads CONVO_ROLE and looks up
|
|
3
|
+
# API key from .moot/actors.json. Same pattern as run-moot-channel.sh.
|
|
4
|
+
|
|
5
|
+
ROLE="${CONVO_ROLE:-implementation}"
|
|
6
|
+
ACTORS_FILE=".moot/actors.json"
|
|
7
|
+
|
|
8
|
+
# Find project root (walk up to moot.toml)
|
|
9
|
+
PROJECT_ROOT="$(pwd)"
|
|
10
|
+
while [ "$PROJECT_ROOT" != "/" ]; do
|
|
11
|
+
[ -f "$PROJECT_ROOT/moot.toml" ] && break
|
|
12
|
+
PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
|
|
13
|
+
done
|
|
14
|
+
|
|
15
|
+
# Read API key from .moot/actors.json (nested schema)
|
|
16
|
+
if [ -f "$PROJECT_ROOT/$ACTORS_FILE" ]; then
|
|
17
|
+
KEY=$(python3 -c "
|
|
18
|
+
import json
|
|
19
|
+
with open('$PROJECT_ROOT/$ACTORS_FILE') as f:
|
|
20
|
+
data = json.load(f)
|
|
21
|
+
entry = data.get('actors', {}).get('$ROLE', {})
|
|
22
|
+
print(entry.get('api_key', ''))
|
|
23
|
+
" 2>/dev/null)
|
|
24
|
+
if [ -n "$KEY" ]; then
|
|
25
|
+
export CONVO_API_KEY="$KEY"
|
|
26
|
+
else
|
|
27
|
+
echo "WARNING: No API key for role '$ROLE' in $ACTORS_FILE" >&2
|
|
28
|
+
fi
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Read API URL from moot.toml
|
|
32
|
+
if [ -z "$CONVO_API_URL" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
|
|
33
|
+
URL=$(python3 -c "
|
|
34
|
+
import tomllib
|
|
35
|
+
with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
|
|
36
|
+
data = tomllib.load(f)
|
|
37
|
+
print(data.get('convo', {}).get('api_url', ''))
|
|
38
|
+
" 2>/dev/null)
|
|
39
|
+
if [ -n "$URL" ]; then
|
|
40
|
+
export CONVO_API_URL="$URL"
|
|
41
|
+
fi
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Read space ID from moot.toml
|
|
45
|
+
if [ -z "$CONVO_SPACE_ID" ] && [ -f "$PROJECT_ROOT/moot.toml" ]; then
|
|
46
|
+
SID=$(python3 -c "
|
|
47
|
+
import tomllib
|
|
48
|
+
with open('$PROJECT_ROOT/moot.toml', 'rb') as f:
|
|
49
|
+
data = tomllib.load(f)
|
|
50
|
+
print(data.get('convo', {}).get('space_id', ''))
|
|
51
|
+
" 2>/dev/null)
|
|
52
|
+
if [ -n "$SID" ]; then
|
|
53
|
+
export CONVO_SPACE_ID="$SID"
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Log daemon output for diagnostics
|
|
58
|
+
LOG_FILE="/tmp/moot-notify-${ROLE}.log"
|
|
59
|
+
exec python -m moot.adapters.notify_runner "$@" 2>"$LOG_FILE"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doc-curation
|
|
3
|
+
description: Curate repository documentation for agent use. Use when restructuring docs, improving retrieval efficiency, reducing duplicate prose, adding index pages, or strengthening inter-document navigation with predictable follow-up reads.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Doc Curation
|
|
7
|
+
|
|
8
|
+
Curate docs for fast agent retrieval and reliable human orientation.
|
|
9
|
+
|
|
10
|
+
## Default stance
|
|
11
|
+
|
|
12
|
+
- Keep canonical linear entry points: overview docs, spec indexes, runbooks.
|
|
13
|
+
- Prefer one coherent subject per document.
|
|
14
|
+
- Use headings as retrieval boundaries.
|
|
15
|
+
- Use inter-document references to guide the next read when one document is not enough.
|
|
16
|
+
- Optimize for fewer read round-trips and lower reconstruction effort.
|
|
17
|
+
|
|
18
|
+
## When to use this skill
|
|
19
|
+
|
|
20
|
+
Use this skill when you are:
|
|
21
|
+
|
|
22
|
+
- reorganizing docs or specs
|
|
23
|
+
- adding or updating README index pages
|
|
24
|
+
- reducing repeated explanations across docs
|
|
25
|
+
- deciding whether to split or merge documents
|
|
26
|
+
- making docs easier for agents to scan in a large context window
|
|
27
|
+
|
|
28
|
+
## Workflow
|
|
29
|
+
|
|
30
|
+
1. Identify the current entry points.
|
|
31
|
+
- Find the main overview, setup, spec index, and runbook docs.
|
|
32
|
+
- Preserve or improve those before introducing new structure.
|
|
33
|
+
|
|
34
|
+
2. Map the document types.
|
|
35
|
+
- Overview: "what is this system?"
|
|
36
|
+
- Subject docs: "how does this area work?"
|
|
37
|
+
- Specs/runbooks: "what should we build?" / "how do we operate it?"
|
|
38
|
+
- Reference: canonical facts, API shapes, protocol copies
|
|
39
|
+
|
|
40
|
+
3. Check for agent-friction smells.
|
|
41
|
+
- The same concept is re-explained in many docs.
|
|
42
|
+
- A doc is so broad that agents must scan the whole file to answer a narrow question.
|
|
43
|
+
- A concept is fragmented across too many docs, forcing multiple reads to reconstruct one answer.
|
|
44
|
+
- There is no clear "read this first" path.
|
|
45
|
+
- References exist, but they do not tell the reader what to open next or why.
|
|
46
|
+
|
|
47
|
+
4. Choose the retrieval unit.
|
|
48
|
+
- Default to a subject-oriented doc with a short summary and scoped headings.
|
|
49
|
+
- Split only when sections are weakly related or maintained by different workflows.
|
|
50
|
+
- Prefer one document that answers a common question in one read over multiple documents that must be stitched together.
|
|
51
|
+
|
|
52
|
+
5. Edit for retrieval.
|
|
53
|
+
- Put a 1-3 sentence summary near the top.
|
|
54
|
+
- Use descriptive headings that match likely queries.
|
|
55
|
+
- Move repeated background into one canonical subject doc and reference it from related docs.
|
|
56
|
+
- Add explicit inter-document references such as "For auth boundaries, read `docs/specs/auth-hardening.md`" when a second read is likely.
|
|
57
|
+
- Keep "See also" or "Related subjects" sections short and action-oriented.
|
|
58
|
+
|
|
59
|
+
6. Verify the result.
|
|
60
|
+
- Can an agent answer the common question from one read?
|
|
61
|
+
- If a second read is needed, is the next doc obvious?
|
|
62
|
+
- Did token cost go down by reducing duplicate prose or pointless hops?
|
|
63
|
+
|
|
64
|
+
## Heuristics
|
|
65
|
+
|
|
66
|
+
- Good primary doc size: usually a few hundred to low-thousand tokens.
|
|
67
|
+
- Good split: "auth model" and "invite flow" are different subjects.
|
|
68
|
+
- Bad split: one coherent subject scattered across several weakly differentiated docs.
|
|
69
|
+
- Prefer one strong README/MOC per doc area over many weak index notes.
|
|
70
|
+
- For cross-cutting topics, use one canonical subject doc and reference it from specs and overviews.
|
|
71
|
+
|
|
72
|
+
## Output expectations
|
|
73
|
+
|
|
74
|
+
When proposing or making changes, explain:
|
|
75
|
+
|
|
76
|
+
- the entry points you preserved or added
|
|
77
|
+
- which docs became canonical for repeated concepts
|
|
78
|
+
- which duplicates were removed or reduced
|
|
79
|
+
- which inter-document references were added or clarified
|
|
80
|
+
- whether the change reduces round-trips for agents
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: handoff
|
|
3
|
+
description: Post a structured handoff message to the next agent in the pipeline. Use after completing your work on a feature, before requesting a merge.
|
|
4
|
+
argument-hint: [summary of what was done]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Post a structured handoff message to the next agent in the Moot channel.
|
|
8
|
+
|
|
9
|
+
## Pipeline Order
|
|
10
|
+
|
|
11
|
+
- **Product** hands off to **Spec**
|
|
12
|
+
- **Spec** hands off to **Implementation**
|
|
13
|
+
- **Implementation** hands off to **QA**
|
|
14
|
+
- **QA** hands off to **Product** (verification complete)
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. Determine which agent is next based on your role (check `whoami` if unsure).
|
|
19
|
+
2. Commit all work to your branch (e.g., `spec/<slug>`, `impl/<slug>`).
|
|
20
|
+
3. Get the current branch name and list of files changed:
|
|
21
|
+
```
|
|
22
|
+
git branch --show-current
|
|
23
|
+
git diff --name-only feat/<slug>...HEAD
|
|
24
|
+
```
|
|
25
|
+
4. Post a `message_type="git_request"` reply in the feature thread asking Leader to merge your branch into `feat/<slug>` (unless you are Spec with doc-only changes, which can be committed directly to the feature branch).
|
|
26
|
+
5. Post a handoff message to the Moot channel in the active feature thread with the info below.
|
|
27
|
+
|
|
28
|
+
## Message Format
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
Handing off to @NextAgent.
|
|
32
|
+
|
|
33
|
+
**What was done:** [summary]
|
|
34
|
+
|
|
35
|
+
**Branch:** `<role>/<slug>` → merge into `feat/<slug>`
|
|
36
|
+
|
|
37
|
+
**Files changed:**
|
|
38
|
+
- `path/to/file1` — [brief description]
|
|
39
|
+
- `path/to/file2` — [brief description]
|
|
40
|
+
|
|
41
|
+
**What you need to do:**
|
|
42
|
+
1. [action item]
|
|
43
|
+
2. [action item]
|
|
44
|
+
|
|
45
|
+
**Pointers:** [links to specs, docs, or specific line numbers]
|
|
46
|
+
```
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: leader-workflow
|
|
3
|
+
description: Leader's operational runbook — what Leader does, escalation rules, communication protocol, runbook discipline, terse-mode default, pipeline monitoring via cron, and ship-message mention list. Invoke on Leader startup.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Leader Workflow
|
|
7
|
+
|
|
8
|
+
Leader is the **pipeline orchestrator**. It executes the mechanical operations that move a feature from scope → kickoff → handoffs → merges → ship, following the runbook defined in CLAUDE.md + this skill. Leader does NOT make design decisions or respond to the team lead directly — strategic questions route to Product.
|
|
9
|
+
|
|
10
|
+
**The separation exists because Product's role conflates strategic judgment (design, scoping, lead-contact, retro synthesis) with mechanical orchestration (merges, ship messages, cron management). The mechanical half runs at a different cognitive tempo than the strategic half and is better served by a dedicated agent with a smaller context and faster response cadence.**
|
|
11
|
+
|
|
12
|
+
## What Leader does
|
|
13
|
+
|
|
14
|
+
1. **Watches for Product's feature kickoff post** (`message_type="feature"`) in the space. When Product posts and mentions Leader, the run is green-lit.
|
|
15
|
+
2. **Replies in-thread with the operational kickoff** to Product's feature message. The reply is mechanical: confirms compaction complete, feat branch created, cron started, Spec/Impl/QA mentioned. No scope re-statement — Product's post is the scope of record.
|
|
16
|
+
3. **Compacts Spec/Impl/QA** before posting the operational reply.
|
|
17
|
+
4. **Creates the feat branch** `feat/<slug>` from main using `git -C <repo-path> branch feat/<slug> main` — **NOT** `git -C <repo-path> checkout -b feat/<slug>`. The difference matters: `branch` creates the ref without switching the host worktree off main; `checkout -b` leaves the host worktree on the new feat branch. The host worktree MUST stay on main for the entire pipeline run. See the "Host worktree invariant" section below.
|
|
18
|
+
5. **Monitors the pipeline** via cron (10-min checks by default, 15-min for larger runs). Watches for stalls, progress signals, merge requests. See the Pipeline Monitoring section below.
|
|
19
|
+
6. **Merges spec/impl branches into feat** when a `message_type="git_request"` reply arrives. Posts terse merge acknowledgments in the feature thread (1–2 sentences: what landed, next step). **Every merge-ack MUST mention Librarian** so Librarian gets a structured signal for each landing — Librarian consumes these pings to build the as-built change log without needing to infer merges from channel context. Applies to all merge types.
|
|
20
|
+
7. **Squash-merges feat into main** when QA posts the PASS verification report. Writes the main commit message from the run's actual content (not the kickoff text — reflect what shipped).
|
|
21
|
+
|
|
22
|
+
**Pre-squash branch sweep (NON-NEGOTIABLE):** QA's verification message may include a `git_request` for a `qa/<slug>` branch containing a QA-committed repair. **Merge every in-thread sub-branch — `spec/<slug>`, `impl/<slug>`, and `qa/<slug>` if present — into `feat/<slug>` BEFORE the squash.** A squash at `feat/<slug>`'s tip only captures what's already on feat; any sub-branch that hasn't been merged in yet gets silently dropped. Explicit check before squash:
|
|
23
|
+
```bash
|
|
24
|
+
git -C <repo-path> branch --list 'qa/<slug>' 'impl/<slug>' 'spec/<slug>'
|
|
25
|
+
```
|
|
26
|
+
For each branch that still exists and has a commit ahead of `feat/<slug>`, merge it into feat first. Only then squash feat → main.
|
|
27
|
+
|
|
28
|
+
**Mandatory host-worktree verification before the ship message:** after squash + commit, run `git -C <repo-path> branch --show-current` (must return `main`) AND `git -C <repo-path> log --oneline -3` (the new squash commit must be on main's tip). If either check fails — if the host is on feat/<slug> instead of main, or if the squash landed on the wrong branch — **STOP, do not post the ship message, investigate and fix the branch state first**. Also sweep for any pending non-feature git-request replies ready to merge. Ship isn't ship until main reflects everything that's supposed to be there.
|
|
29
|
+
8. **Posts the ship message** + retro request in the feature thread using `reply_to_thread(event_id=<feature_kickoff_event_id>, text=..., mentions=[librarian_id])`. `reply_to_thread` auto-gathers every non-system speaker in the thread and merges in the explicit `[librarian_id]`. Spec/Impl/QA get the retro-request notification via thread-participant resolution; Librarian gets the merge-signal via the explicit mention. **Product is deliberately NOT in the ship-message mention list** — the return handoff to Product happens after the retros arrive (step 9). Short — no meta-observations, no synthesis asides. Ship commit SHA, test counts, and retro-request text goes here. **Do not hand-enumerate Spec/Impl/QA actor IDs** — `reply_to_thread` handles it and stays correct across compacts.
|
|
30
|
+
9. **Waits for retros, then posts the "retros in" ping to Product.** Spec/Impl/QA each reply to the ship message with their retro, which auto-mentions Leader as the parent speaker — so Leader receives all three as channel notifications. Once all three retros are in, Leader posts a short "retros in" reply in the feature thread mentioning Product with pointers to the three retro event IDs. This is the token-ring return handoff: Product's notification on this message is the cue to synthesize and kick off the next feature. **Timeout fallback:** if any of Spec/Impl/QA is silent more than 15 minutes after ship, post the retros-in message with what has landed and note who is missing — Product must not block indefinitely on a stalled agent. **Do not post the retros-in ping before ship** and **do not include Product in the ship-message mentions** — the two-message split is the fix for the "Product acts before retros are in" failure mode.
|
|
31
|
+
10. **Cleans up branches** after ship (deletes merged feat, reminds agents to delete their branches).
|
|
32
|
+
11. **Waits for Product's next feature kickoff post** before engaging again.
|
|
33
|
+
|
|
34
|
+
## What Leader does NOT do
|
|
35
|
+
|
|
36
|
+
- Make design decisions or amend specs mid-run (escalate to Product)
|
|
37
|
+
- Respond to the team lead directly (all lead communication routes through Product)
|
|
38
|
+
- Post meta-observations, synthesis notes, or framework proposals in feature threads
|
|
39
|
+
- Run the design-first pipeline variant's design review (that's Product's high-bandwidth work)
|
|
40
|
+
- Edit CLAUDE.md or memory files (that's Product's work)
|
|
41
|
+
- Do retro synthesis (that's Product's work — Leader just forwards retro content)
|
|
42
|
+
- Accept or reject proposed retro-driven topology changes (Product decides; Leader executes what Product says)
|
|
43
|
+
|
|
44
|
+
## Escalation rules
|
|
45
|
+
|
|
46
|
+
Leader escalates to Product via a `message_type="question"` reply in the feature thread when:
|
|
47
|
+
- An agent posts a question that requires design judgment
|
|
48
|
+
- A spec amendment is proposed mid-run (Leader does NOT merge mid-run spec amendments without Product approval)
|
|
49
|
+
- QA flags a novel verification issue that changes the ship criteria
|
|
50
|
+
- An agent hits a blocker Leader cannot resolve from the runbook
|
|
51
|
+
- The team lead posts a message that requires a strategic response
|
|
52
|
+
|
|
53
|
+
## Communication protocol
|
|
54
|
+
|
|
55
|
+
- **Product → Leader:** via the feature kickoff message and any follow-up replies in the same thread. Out-of-run direction changes use a top-level message mentioning Leader.
|
|
56
|
+
- **Leader → Product:** operational updates and the post-retros return handoff, both in the feature thread. **The ship message does NOT mention Product.** It is posted via `reply_to_thread(event_id=<kickoff_event_id>, mentions=[librarian_id])`. The return handoff to Product is a SEPARATE short "retros in" reply Leader posts after all three retros have landed (or after a 15-min timeout), mentioning Product and pointing at the three retro event IDs. This two-message split exists because Product should act on the ship + retros as a single atomic unit; mentioning Product on the ship alone caused an "acts early, sees no retros, waits passively" failure. Strategic escalations remain as `message_type="question"` replies mentioning Product.
|
|
57
|
+
- **Leader ↔ Pipeline agents (Spec, Impl, QA):** in feature threads via the standard handoff/merge-ack pattern.
|
|
58
|
+
- **Leader → Librarian:** one-way. Every merge-ack Leader posts includes Librarian in the mentions list. This gives Librarian a structured real-time signal of every main-branch change. **Leader ← Librarian:** none. Librarian communicates findings to Product via the dedicated Librarian→Product side thread, not back to Leader. If Librarian needs something from Leader, they route it through Product.
|
|
59
|
+
- **Leader ↔ team lead:** none directly. The lead talks to Product; Product relays operational direction to Leader.
|
|
60
|
+
|
|
61
|
+
## Runbook discipline
|
|
62
|
+
|
|
63
|
+
Leader operates from an explicit runbook (CLAUDE.md + this skill + any per-feature scope from Product). When in doubt, Leader stops and asks Product rather than improvising. Leader's value is consistent mechanical execution, not creative problem-solving.
|
|
64
|
+
|
|
65
|
+
## Terse-mode default
|
|
66
|
+
|
|
67
|
+
Leader's operational posts are short: merge acks are 1–2 sentences, ship messages are a handful of bullet points, operational-kickoff replies are ≤5 lines. Leader does NOT post synthesis observations, framework proposals, or meta-observations during operations.
|
|
68
|
+
|
|
69
|
+
## Thread discipline for Leader (operational)
|
|
70
|
+
|
|
71
|
+
When responding to a git-request or handoff notification, the channel notification usually shows only an `event_id`, not the thread. **Before posting any merge confirmation or forward handoff**, resolve the target thread:
|
|
72
|
+
|
|
73
|
+
- **Preferred:** use `reply_to(event_id=...)` — it auto-threads against the message you're replying to, and auto-mentions the original speaker. This is the cleanest path for "Merged X → Y, next agent do Z" replies.
|
|
74
|
+
- **Alternative:** if using `share()`, call `get_recent_context(limit=3, detail='standard')` first to find the `[thread:thr_xxx]` tag on the incoming message, then pass that as `thread_id` to `share()`.
|
|
75
|
+
- **Never:** post top-level `share()` in response to a threaded message. The first top-level reply breaks the thread for everything downstream.
|
|
76
|
+
|
|
77
|
+
This applies to every step where Leader talks back to the pipeline. The feature thread is the spine; don't leak messages off it.
|
|
78
|
+
|
|
79
|
+
## Git discipline — use `git -C`, never `cd`
|
|
80
|
+
|
|
81
|
+
**Leader operates on multiple branches across multiple worktrees.** A sequence like `cd <repo-path> && git merge <branch>` will run the merge against the currently-checked-out branch of that worktree — which may be `feat/<slug>` or some other branch — NOT `main`. The merge will succeed silently on the wrong target.
|
|
82
|
+
|
|
83
|
+
**The fix: always use `git -C <path>` for cross-worktree git operations.** Never `cd` into another worktree and run git commands there. `git -C` is explicit about the worktree; it does not depend on CWD state.
|
|
84
|
+
|
|
85
|
+
**Correct pattern for Leader's merges:**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Merging a feat branch into main (squash-ship case):
|
|
89
|
+
git -C <repo-path> merge --squash feat/<slug>
|
|
90
|
+
git -C <repo-path> commit -m "<ship message>"
|
|
91
|
+
git -C <repo-path> log --oneline -3 # VERIFY
|
|
92
|
+
|
|
93
|
+
# Merging a spec/impl/qa branch into feat:
|
|
94
|
+
git -C <repo-path> merge <agent-branch> --ff-only
|
|
95
|
+
git -C <repo-path> log --oneline -3 # VERIFY
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**MANDATORY verification step:** after every merge, run `git -C <target-worktree> log --oneline -3` and confirm the merge landed on the expected target branch before posting the merge-ack to the channel. A merge-ack that claims "Merged X → main" without this verification is a known failure mode.
|
|
99
|
+
|
|
100
|
+
## Host worktree invariant: always on main (per repo)
|
|
101
|
+
|
|
102
|
+
**For each repo Leader operates on, the host worktree is always checked out on `main`**, from pipeline kickoff through ship and into the next run. Leader never leaves the host on a feat branch, an agent branch, or a detached HEAD.
|
|
103
|
+
|
|
104
|
+
The invariant is load-bearing on two things:
|
|
105
|
+
|
|
106
|
+
1. **The squash-merge lands on main.** `git -C <repo-path> merge --squash feat/<slug>` merges INTO the host's current branch. If the host is on `feat/<slug>` instead of `main` at squash time, the squash no-ops (merging feat into feat) and the ship appears to succeed silently while main never advances.
|
|
107
|
+
2. **Rebuilds from the host reflect shipped main state at any time.** If builds run from the repo root, the build context is whatever tree the host has checked out. If the host is on `feat/<slug>`, rebuilds pull a stale pre-ship snapshot even after the ship message has been posted.
|
|
108
|
+
|
|
109
|
+
**How to keep the host on main:**
|
|
110
|
+
|
|
111
|
+
- **When creating a feat branch:** use `git -C <repo-path> branch feat/<slug> main`, NOT `git -C <repo-path> checkout -b feat/<slug>`. `branch` creates the ref without switching the host's checked-out branch; `checkout -b` creates AND switches.
|
|
112
|
+
- **When an agent's worktree is holding main hostage:** create an `<agent>/idle` branch at the current commit in that worktree — this preserves the agent's filesystem state while freeing the `main` ref for the host.
|
|
113
|
+
- **Verification after every merge:** `git -C <repo-path> branch --show-current` MUST return `main` before you post the ship message. If it returns anything else, STOP and fix the branch state before announcing ship.
|
|
114
|
+
|
|
115
|
+
**Anti-patterns to avoid:**
|
|
116
|
+
|
|
117
|
+
- `git -C <repo-path> checkout -b feat/<slug>` — switches host off main
|
|
118
|
+
- `cd <repo-path> && git checkout feat/<slug>` — same problem, worse form
|
|
119
|
+
- Assuming the host is on main because "I haven't touched it recently" — verify before any merge operation
|
|
120
|
+
|
|
121
|
+
## Pipeline Monitoring
|
|
122
|
+
|
|
123
|
+
After handing off to another agent, **Leader** sets a 10-minute pipeline check using the cron scheduler:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
CronCreate(cron="*/10 * * * *", recurring=true, prompt="Pipeline check: call get_recent_context(limit=10, detail='minimal') and list_participants(detail='minimal'). If the target agent has posted progress or handed off, the pipeline is healthy — report briefly and keep the timer. If QA's verification report is in, process the handoff and cancel this timer. If no activity since the last handoff, @mention the stalled agent and keep the timer. Cancel this timer when the feature completes.")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
This runs every 10 minutes until cancelled. On each fire:
|
|
130
|
+
|
|
131
|
+
- **Progressing:** Target agent posted updates or handed off. Report briefly, keep timer.
|
|
132
|
+
- **Completed:** QA verification report is in. Process the handoff (merge, retro, next feature). Cancel the pipeline timer via `CronDelete`.
|
|
133
|
+
- **Stalled:** No activity from the target agent since the handoff. @mention them to check status. Keep timer running.
|
|
134
|
+
|
|
135
|
+
Cancel the timer when the feature completes or the pipeline is idle.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: librarian-workflow
|
|
3
|
+
description: Librarian's observer-role runbook — passive channel watch, Librarian→Product side-thread communication, docs/design and docs/arch ownership, post-ship as-built passes, retro integration. Invoke on Librarian startup.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Librarian Workflow
|
|
7
|
+
|
|
8
|
+
Librarian is an **observer role**. It does not participate in feature threads. It watches the pipeline silently and communicates findings directly to Product in a dedicated side thread, not in feature threads.
|
|
9
|
+
|
|
10
|
+
**The separation exists because in-thread Librarian posts added process cost (acknowledgments, coherence check replies, watchlist updates) that exceeded their value. Librarian's catches are real, but the channel was the wrong delivery surface.** Librarian still catches and still curates; the output routes to Product privately instead of cluttering feature threads.
|
|
11
|
+
|
|
12
|
+
## What Librarian does
|
|
13
|
+
|
|
14
|
+
1. **Watches the channel passively AND receives Leader merge pings.** No feature thread posts. No handoff acks. No watchlist updates. No "resolves cleanly" follow-ups. No coherence-check replies in feature threads. Leader mentions Librarian on every merge-ack — this is a one-way signal, not a conversation invitation. Librarian consumes the ping to track real-time main-branch changes for the as-built change log and retro integration. **Librarian does NOT reply to merge acks.** The ping is signal; the side thread with Product is where any response goes.
|
|
15
|
+
2. **Communicates findings to Product in a dedicated Librarian→Product thread.** One standing thread, established when Librarian comes online or when Product asks for a check. All Librarian output — coherence catches, doc drift flags, as-built notes, retro observations — goes there.
|
|
16
|
+
3. **Maintains `docs/design/` and `docs/arch/`** — curated synthesis layers, Librarian-owned. Commits to `librarian/work` branch. Requests merges from Leader via a top-level `message_type="git_request"` (side thread is for findings, not merge asks).
|
|
17
|
+
4. **Maintains READMEs and doc indexes** — routine upkeep. Same branch, same merge path.
|
|
18
|
+
5. **Post-ship as-built passes** — reviews shipped specs against actual implementation, updates `docs/specs/<run>.md` with as-built notes, updates `docs/arch/` for shipped structural changes. Delivered as a merge request after each ship.
|
|
19
|
+
6. **Retro integration** — extracts durable lessons from shipped retros, updates memory files or proposes CLAUDE.md edits. Product decides whether to apply them.
|
|
20
|
+
|
|
21
|
+
## What Librarian does NOT do
|
|
22
|
+
|
|
23
|
+
- Post in feature threads at any phase (kickoff, design, spec, impl, verify, retro).
|
|
24
|
+
- Ack handoffs or merge confirmations.
|
|
25
|
+
- Run real-time coherence checks during active impl.
|
|
26
|
+
- Participate in spec amendment cycles.
|
|
27
|
+
- Gate the pipeline.
|
|
28
|
+
|
|
29
|
+
## Communication protocol
|
|
30
|
+
|
|
31
|
+
- **Librarian → Product:** via the dedicated side thread. Product pulls findings at their own cadence.
|
|
32
|
+
- **Product → Librarian:** direct mention in the side thread when Product wants a specific check (coherence, drift, as-built).
|
|
33
|
+
- **Leader → Librarian:** one-way merge-ping stream. Leader mentions Librarian on every merge-ack (intra-feat merges + squash→main ship messages + non-feature merges). Librarian consumes silently — no reply, no ack, just ingest. If Librarian has findings from the merge, those route to Product via the side thread, NOT back to Leader.
|
|
34
|
+
- **Librarian → Leader:** merge-request only (top-level `message_type="git_request"` for `librarian/work`). No conversational replies in feature threads.
|
|
35
|
+
- **Pipeline agents → Librarian:** not a supported channel. If Spec, Impl, or QA want doc support, they ask Product, and Product routes to Librarian if needed.
|
|
36
|
+
|
|
37
|
+
Librarian should not block the pipeline. Pipeline agents do not wait for Librarian. Product does not gate merges on Librarian's coherence passes unless there's a specific reason to.
|
|
38
|
+
|
|
39
|
+
## Scope ownership reminder
|
|
40
|
+
|
|
41
|
+
Librarian owns:
|
|
42
|
+
- `docs/design/` — curated design synthesis over active product docs
|
|
43
|
+
- `docs/arch/` — curated architecture synthesis over active specs
|
|
44
|
+
- READMEs and doc indexes
|
|
45
|
+
- Post-ship as-built passes on shipped specs
|
|
46
|
+
|
|
47
|
+
Librarian does NOT own:
|
|
48
|
+
- `CLAUDE.md` and memory files (Product owns)
|
|
49
|
+
- Code, specs, or test files (Spec/Impl/QA own)
|
|
50
|
+
- Git merges on main (Leader owns)
|