| name | reselect-figures |
| description | Use when the user wants to change which figures are embedded in xhs.md and wechat.md. Shows the user the figures with importance scores from analysis/06-figures.md, lets them multi-select per platform, re-runs both renderers with new selections. |
| disable-model-invocation | false |
| allowed-tools | Bash, Read, Write, Edit, Agent |
paperstudio: reselect-figures workflow
Hard rules (non-negotiable, enforced by tests)
These apply to every Agent dispatch in this skill. Stage-local exceptions must be stated inline with a one-line "why".
- Provenance — every output line 1:
<!-- generated: <ts> by <agent> (paperstudio v<ver>) -->
- Idempotence —
OUTPUT_PATH exists + no --force ⇒ skip; exists + --force ⇒ cp $f $f.bak.NN first, then dispatch.
- Log — after every dispatch (success or fail), call
log_dispatch <subagent> <output-path> <ok|failed>. Never on a skip.
- Paths — paper root is
${PAPERS_ROOT}, resolved once from ${CLAUDE_PAPERS_ROOT:-$HOME/claude-papers/papers}. Never hard-code ~/claude-papers/papers/ in writes.
- Failure — Agent failure: log
failed, do NOT delete partial output, do NOT auto-retry, surface the actionable rerun command, continue independent stages.
- Chat language — reply in the user's invocation language. Artifact language is governed by the prompt's
LANG= input.
Full text + rationale: see paperstudio/skills/_shared/dispatch-rules.md.
Invoke after /paperstudio:study has produced analysis/06-figures.md plus the notes set. Both notes/xhs.md and notes/wechat.md are re-rendered with the new figure selections; their prior versions are backed up.
Optional flags:
--reinterpret: re-run figure-interpreter first to refresh analysis/06-figures.md importance scores. Useful if the original interpretation was off.
--paper <slug>: target a specific paper folder.
Stage 1: Setup
1.1 Resolve target paper
Resolve target paper folder
Source the shared helper and resolve which paper folder this invocation targets:
source $CLAUDE_PLUGIN_ROOT/scripts/lib/resolve-paper.sh
resolve_paper "$@"
If resolve_paper returns non-zero, abort with the helper's stderr message. Verify required files:
$PAPER_DIR/analysis/06-figures.md
$PAPER_DIR/images/ directory (non-empty)
$PAPER_DIR/notes/source.md
$PAPER_DIR/notes/titles.md
$PAPER_DIR/notes/xhs.md
$PAPER_DIR/notes/wechat.md
Abort with helpful message if any are missing.
Set:
FIGURES_MD=$PAPER_DIR/analysis/06-figures.md
IMAGES_DIR=$PAPER_DIR/images
XHS_PATH=$PAPER_DIR/notes/xhs.md
WECHAT_PATH=$PAPER_DIR/notes/wechat.md
SOURCE_PATH=$PAPER_DIR/notes/source.md
TITLES_PATH=$PAPER_DIR/notes/titles.md
PLUGIN_ROOT=${CLAUDE_PLUGIN_ROOT}
Source the log-dispatch helper and extract plugin version:
source $CLAUDE_PLUGIN_ROOT/scripts/lib/log-dispatch.sh
PLUGIN_VERSION=$(grep -m1 '"version"' $CLAUDE_PLUGIN_ROOT/.claude-plugin/plugin.json | sed -E 's/.*"version"[^"]*"([^"]+)".*/\1/')
1.2 Optionally re-interpret figures
If --reinterpret is set:
First, back up the existing 06-figures.md:
NN=1
while [ -e "$FIGURES_MD.bak.$NN" ]; do
NN=$((NN + 1))
done
cp "$FIGURES_MD" "$FIGURES_MD.bak.$NN"
Then dispatch figure-interpreter:
Agent(
description: "figure-interpreter (refresh scores)",
subagent_type: "general-purpose",
prompt: <contents of $PLUGIN_ROOT/prompts/figure-interpreter.md> + concrete inputs:
PAPER_TEXT=$PAPER_DIR/paper.txt (or paper.pdf if .txt missing)
IMAGES_DIR=$IMAGES_DIR
OUTPUT_PATH=$FIGURES_MD
TEMPLATE_PATH=$PLUGIN_ROOT/templates/analysis/06-figures.md
PLUGIN_VERSION=$PLUGIN_VERSION
)
Wait for completion.
log_dispatch figure-interpreter analysis/06-figures.md ok
If --reinterpret is not set, skip this step.
Stage 2: Show figures to user
2.1 Parse 06-figures.md
Read $FIGURES_MD. Parse YAML frontmatter to extract the figures: list — for each figure, capture file, caption, importance, role.
If the YAML is the FAILED placeholder (<!-- FAILED: ... -->), abort: "analysis/06-figures.md is FAILED — re-run /paperstudio:rerun-stage analysis or /paperstudio:reselect-figures --reinterpret first."
2.2 Display the menu
Show the user (in their invocation language):
Figures available (from analysis/06-figures.md):
[1] page_1_img_1.png importance=0.95 role=architecture
Caption: "Overview of the model showing input → encoder → decoder."
[2] page_3_img_2.png importance=0.85 role=main-result
Caption: "BLEU on WMT'14: our method 28.4 vs prior 27.3."
[3] ...
Pick figures:
- For xhs (1 figure): type a number, e.g. "1"
- For wechat (2-3 figures): type comma-separated numbers, e.g. "1,2,4"
- Type 'cancel' to abort.
xhs choice:
Wait for user input. Validate:
- xhs: exactly 1 number, must be in range [1, len(figures)].
- Re-prompt on invalid.
Then prompt for wechat:
wechat choice (2-3 numbers, comma-separated):
Wait for user input. Validate:
- wechat: 2 or 3 numbers, all in range, no duplicates.
- Re-prompt on invalid.
Set:
XHS_FIGURES=[<images_dir>/<filename> for the chosen xhs figure] (1 path)
WECHAT_FIGURES=[<images_dir>/<filename> for each chosen wechat figure] (2-3 paths)
If user types 'cancel' at either prompt, exit gracefully without modifying anything.
Stage 3: Backup + dispatch renderers
3.1 Back up both renderings
for path in "$XHS_PATH" "$WECHAT_PATH"; do
NN=1
while [ -e "$path.bak.$NN" ]; do
NN=$((NN + 1))
done
cp "$path" "$path.bak.$NN"
done
3.2 Dispatch xhs-renderer + wechat-renderer in parallel
Issue both Agent calls in one message:
Agent( // xhs
description: "xhs-renderer with new figure selection",
subagent_type: "general-purpose",
prompt: <contents of $PLUGIN_ROOT/prompts/xhs-renderer.md> + concrete inputs:
SOURCE_PATH=$SOURCE_PATH
TITLES_PATH=$TITLES_PATH
OUTPUT_PATH=$XHS_PATH
TEMPLATE_PATH=$PLUGIN_ROOT/templates/notes/xhs.md
SELECTED_FIGURES=<XHS_FIGURES>
PLUGIN_VERSION=$PLUGIN_VERSION
)
Agent( // wechat
description: "wechat-renderer with new figure selection",
subagent_type: "general-purpose",
prompt: <contents of $PLUGIN_ROOT/prompts/wechat-renderer.md> + concrete inputs:
SOURCE_PATH=$SOURCE_PATH
TITLES_PATH=$TITLES_PATH
OUTPUT_PATH=$WECHAT_PATH
TEMPLATE_PATH=$PLUGIN_ROOT/templates/notes/wechat.md
SELECTED_FIGURES=<WECHAT_FIGURES>
PLUGIN_VERSION=$PLUGIN_VERSION
)
(Note: EDIT_INSTRUCTION and EXISTING_PATH are intentionally omitted — this skill re-renders from scratch with new figures. The user's prior body edits will not be preserved. If the user wants to preserve body edits, they should use /paperstudio:refine-notes with a figure-swap instruction instead.)
After both complete:
log_dispatch xhs-renderer notes/xhs.md ok
log_dispatch wechat-renderer notes/wechat.md ok
If either failed: log with failed status.
3.3 Verify outputs
If either output is missing or empty, restore from backup:
for path in "$XHS_PATH" "$WECHAT_PATH"; do
if [ ! -s "$path" ]; then
bak=$(ls -t "$path".bak.* 2>/dev/null | head -1)
if [ -n "$bak" ]; then
cp "$bak" "$path"
echo "WARN: renderer produced empty output for $(basename "$path"); restored from $bak"
fi
fi
done
Stage 4: Final summary
✓ Reselected figures for both renderings.
xhs.md: <new figure list> (was: <prior figure list>)
wechat.md: <new figure list> (was: <prior figure list>)
Backups:
notes/xhs.md.bak.<NN>
notes/wechat.md.bak.<NN>
<if --reinterpret was set: analysis/06-figures.md.bak.<NN>>
Notes
- Body content is regenerated. Unlike
/paperstudio:refine-notes which surgically edits, /paperstudio:reselect-figures re-renders both files from source.md. Prior body edits (e.g., from earlier /paperstudio:refine-notes rounds) will be lost. To preserve body edits, use /paperstudio:refine-notes <platform> and ask the renderer to swap a figure as part of the instruction.
- --reinterpret only refreshes scores, doesn't change image files. The actual image files in
images/ are produced by claude-paper:study and are read-only here.
- Translation: chat-facing prose to user is in user's invocation language. Renderings stay Chinese.