Summary
platform-integrations/claude/plugins/evolve-lite/skills/learn/scripts/on_stop.py:23 hardcodes .evolve/trajectories/claude-transcript_<session-id>.jsonl as the path it tells
the learn skill to read. The sibling hook save-trajectory/scripts/on_stop.py writes the transcript to $EVOLVE_DIR/trajectories/ (or
$CLAUDE_PROJECT_ROOT/.evolve/trajectories/) using a proper resolution order. When either env var is set to a non-default location, the two paths disagree and the learn skill
can't find the saved transcript — it exits without extracting guidelines or influence records.
Repro
- Set
EVOLVE_DIR=/tmp/my-evolve (or CLAUDE_PROJECT_ROOT=<some-dir>).
- Run any Claude Code session to completion so the Stop hook fires.
save-trajectory writes to /tmp/my-evolve/trajectories/claude-transcript_<id>.jsonl.
learn/on_stop.py tells the model the path is .evolve/trajectories/claude-transcript_<id>.jsonl.
- The learn skill reads a non-existent path and silently produces no guidelines.
Root cause
learn/scripts/on_stop.py:23 builds the path as a literal string instead of using the same resolution logic as save-trajectory/scripts/on_stop.py:41-52
(get_trajectories_dir()).
Suggested fix
Either:
- Extract
get_trajectories_dir() into a shared helper under the plugin's lib/ and import it from both hooks, or
- Duplicate the resolution logic inside
learn/on_stop.py (EVOLVE_DIR → CLAUDE_PROJECT_ROOT/.evolve → .evolve) and emit the resolved absolute path in the reason field.
Test plan
Context
Flagged by Codex review on PR #245.
Summary
platform-integrations/claude/plugins/evolve-lite/skills/learn/scripts/on_stop.py:23hardcodes.evolve/trajectories/claude-transcript_<session-id>.jsonlas the path it tellsthe learn skill to read. The sibling hook
save-trajectory/scripts/on_stop.pywrites the transcript to$EVOLVE_DIR/trajectories/(or$CLAUDE_PROJECT_ROOT/.evolve/trajectories/) using a proper resolution order. When either env var is set to a non-default location, the two paths disagree and the learn skillcan't find the saved transcript — it exits without extracting guidelines or influence records.
Repro
EVOLVE_DIR=/tmp/my-evolve(orCLAUDE_PROJECT_ROOT=<some-dir>).save-trajectorywrites to/tmp/my-evolve/trajectories/claude-transcript_<id>.jsonl.learn/on_stop.pytells the model the path is.evolve/trajectories/claude-transcript_<id>.jsonl.Root cause
learn/scripts/on_stop.py:23builds the path as a literal string instead of using the same resolution logic assave-trajectory/scripts/on_stop.py:41-52(
get_trajectories_dir()).Suggested fix
Either:
get_trajectories_dir()into a shared helper under the plugin'slib/and import it from both hooks, orlearn/on_stop.py(EVOLVE_DIR→CLAUDE_PROJECT_ROOT/.evolve→.evolve) and emit the resolved absolute path in thereasonfield.Test plan
EVOLVE_DIRset,on_stop.pyemits a reason whose path equals$EVOLVE_DIR/trajectories/claude-transcript_<id>.jsonl.CLAUDE_PROJECT_ROOTset, path resolves under that root..evolve/trajectories/....Context
Flagged by Codex review on PR #245.