Skill Tracer
Skills › Compound Engineering › ce-compound › session-history.md

session-history.md

72 lines · skills/ce-compound/references/session-history.md at 3449230

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Session history (Phase 1 step 4)
2

Session history (Phase 1 step 4)

Raw lines 1 to 2
3## Session context
4
5Resolve two values at runtime with the shell tool before Phase 1 session-history filtering. Run each as its own command and read its exit status. A non-zero exit is a normal state here, not an error to route around:
6
7- **Git branch**: run `git rev-parse --abbrev-ref HEAD`. Use the branch name to filter session history in Phase 1. If it returns `HEAD` (detached) or exits non-zero (not a git repo), skip branch filtering.
8- **Repo root**: run `git rev-parse --show-toplevel`. Use it as the session-history repo filter in Phase 1. If it exits non-zero (not a git repo), fall back to the working directory.
9
10#### 4. **Session History** (internal flow after dispatching the Related Docs Finder; automatic in Full mode, including non-interactive)
11 - This is a two-stage probe: the cheap discovery+metadata pass below always executes, and the expensive extraction+synthesis executes only when the probe clears the relevance bar (see **Escalation check** below).
12 - Run session discovery, branch/keyword filtering, scan-window selection, deep-dive selection, and per-session extraction directly inside this skill using `scripts/session-history/`.
13 - Read the skill-local synthesis prompt at `references/agents/session-historian.md`, then dispatch a generic subagent using that prompt content. Do not dispatch a standalone agent by type/name.
15 **Keep the session-history payload tight.** A long, keyword-rich payload invites the flow to widen its search. Use this shape:
17 - **Session context** (only if the values resolved cleanly above; otherwise omit): repo name, current git branch.
18 - **Time window**: explicit `7 days` unless the documented problem clearly spans a longer arc.
19 - **Problem topic**: one sentence naming the concrete issue — error message, module name, what broke and how it was fixed. Not a paragraph; not a bullet list of related topics.
20 - **Filter rule (one line)**: "Only surface findings directly relevant to this specific problem. Ignore unrelated work from the same sessions or branches."
21 - **Output schema**:
23 ```
24 Structure your response with these sections (omit any with no findings):
25 - What was tried before
26 - What didn't work
27 - Key decisions
28 - Related context
29 ```
31 Do not append additional context blocks, exclusion lists, or topic-keyword bullets. Verbose payloads let the session-history flow keep widening the search, which rapidly compounds wall time. If keyword search is needed, the internal flow decides that from the topic.
32 - Returns a structured digest, or `no relevant prior sessions`. Either is a valid final Phase 1 input, and the documentation gets written without session context when it is the latter.
34 **Script resolution.** Set `SKILL_DIR` to the absolute path of the directory containing the SKILL.md you just read, and run the bundled scripts from `"$SKILL_DIR/scripts/session-history/"`. Set `SKILL_DIR` inline in each bash block below (shell state does not persist between commands). If the bundled scripts are genuinely not present on disk under `"$SKILL_DIR/scripts/session-history/"`, skip session history visibly with: "Session history bundled scripts were not found in this skill's directory; skipping the session-history probe for this run." Continue Phase 2 without session context.
36 **Discovery pipeline.** Infer the scan window from the problem topic, starting with 7 days. Run discovery and metadata extraction:
38 ```bash
39 SKILL_DIR="<absolute path of the directory containing the SKILL.md you just read>";
40 if [ -f "$SKILL_DIR/scripts/session-history/discover-sessions.sh" ] && [ -f "$SKILL_DIR/scripts/session-history/extract-metadata.py" ]; then
41 PY="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"; [ -n "$PY" ] || { echo "no working Python 3 interpreter on PATH" >&2; exit 1; };
42 REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd); REPO_NAME=$(basename "$REPO_ROOT"); SCAN_DAYS="7"; bash "$SKILL_DIR/scripts/session-history/discover-sessions.sh" "$REPO_NAME" "$SCAN_DAYS" --cwd "$REPO_ROOT" | tr '\n' '\0' | xargs -0 "$PY" "$SKILL_DIR/scripts/session-history/extract-metadata.py" --cwd-filter "$REPO_ROOT";
43 else echo "Session history bundled scripts were not found in this skill's directory; skipping the session-history probe for this run."; fi
44 ```
46 The command prints JSONL. `xargs` may split a long file list across several runs of the script; each run prints one object per kept session, then its own `_meta` line. Parse the output one line at a time, because the stream as a whole is not one JSON document. A pass's `files_processed` total is the sum across its `_meta` lines; a `--keyword` re-run is a new pass, not more files. Optional fields are omitted, not set to null, so a missing key is not an error. Rank recency by `last_ts`, falling back to `ts`. If you process the output with code, look at a few lines first and use the keys you see.
48 Claude sessions live under `~/.claude/projects/` unless `CLAUDE_CONFIG_DIR` is set, in which case they live under that directory's `projects/`. Codex sessions live under `~/.codex/sessions/` unless `CODEX_HOME` is set, in which case they live under that directory's `sessions/`; `~/.agents/sessions/` is also scanned. Pi sessions are included when present under `~/.pi/agent/sessions/` (`PI_CODING_AGENT_DIR` / `PI_CODING_AGENT_SESSION_DIR` override), and oh-my-pi (`omp`) sessions under `~/.omp/agent/sessions/` (named profiles: `~/.omp/profiles/<name>/agent/sessions/`; XDG: `$XDG_DATA_HOME/omp/sessions` and `$XDG_DATA_HOME/omp/profiles/<name>/sessions`; `PI_CONFIG_DIR` / `PI_CODING_AGENT_DIR` / `PI_CODING_AGENT_SESSION_DIR` override). Claude, Codex, Pi, and oh-my-pi (`omp`) sessions carry a recorded `cwd` (Claude also has git branch; Pi/omp do not). `--cwd-filter` keeps a session when that cwd is the repo root, an ancestor of it, or a path inside it (path-component boundaries: `my-repo` vs `my-repo-old` do not match). Claude, Codex, Pi, and omp sessions with no recorded cwd are dropped. Cursor has no cwd and stays. Do not drop a Claude session because its project folder name lacks the repo basename. That is how Claude stores parent-started sessions. If the first pass's `files_processed` total is `0`, return `no relevant prior sessions`. If the first pass finds no relevant branch matches, or if processing Codex, Pi, or oh-my-pi (`omp`) sessions, derive 2-4 keywords from the topic and re-run metadata extraction with `--keyword K1,K2,...`. Keep at most 5 sessions across Claude Code, Codex, Cursor, Pi, and oh-my-pi (`omp`), ranked by branch match, keyword match count, file size over 30KB, and recency. Exclude the current session.
50 **Escalation check.** The discovery+metadata pass above is the cheap probe and always runs in Full mode. Escalate to the extraction and synthesis stages below **only** when at least one retained candidate clears the relevance bar: a current-branch match, or ≥2 topic-keyword matches. If no candidate clears the bar (including a `files_processed` total of `0`), stop here, record `no relevant prior sessions` as the session-history input, and skip extraction and synthesis. This check is what keeps the always-on probe cheap. The expensive synthesis runs only when a prior session is genuinely relevant.
52 **Extraction pipeline.** Create `SCRATCH=$(mktemp -d "${TMPDIR:-/tmp}/ce-compound-sessions-XXXXXX")`. For each selected session, write extracted content to scratch files:
54 ```bash
55 SKILL_DIR="<absolute path of the directory containing the SKILL.md you just read>";
56 if [ -f "$SKILL_DIR/scripts/session-history/extract-skeleton.py" ]; then
57 PY="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"; [ -n "$PY" ] || { echo "no working Python 3 interpreter on PATH" >&2; exit 1; };
58 "$PY" "$SKILL_DIR/scripts/session-history/extract-skeleton.py" --output "$SCRATCH/<session-id>.skeleton.txt" < <session-file>;
59 else echo "Session history bundled scripts were not found in this skill's directory; skipping the session-history probe for this run."; fi
60 ```
62 Use `extract-errors.py` selectively when dead ends or recurring errors are likely useful. Pass only the scratch file paths and metadata to the synthesis subagent.
64 **Synthesis dispatch.** Build a generic subagent prompt containing:
65 - the full content of `references/agents/session-historian.md`
66 - `problem_topic`
67 - `scratch_dir`
68 - a `sessions` array with extracted file paths and metadata
69 - the output schema above
70 - the filter rule above
72 The subagent reads only the scratch paths, **writes its prose findings to `{run_dir}/session-history.md`, and returns only that artifact path once the write is confirmed** (the same #956 reliability reason applies, because session-history findings are long-form prose prone to summary-collapse). If `{run_id}` did not resolve or the artifact write failed, it returns the prose inline instead (per the inline-fallback rule above). If synthesis fails, note the failure and continue without session context.

Session context

Resolve two values at runtime with the shell tool before Phase 1 session-history filtering. Run each as its own command and read its exit status. A non-zero exit is a normal state here, not an error to route around:

  • Git branch: run git rev-parse --abbrev-ref HEAD. Use the branch name to filter session history in Phase 1. If it returns HEAD (detached) or exits non-zero (not a git repo), skip branch filtering.
  • Repo root: run git rev-parse --show-toplevel. Use it as the session-history repo filter in Phase 1. If it exits non-zero (not a git repo), fall back to the working directory.

4. Session History (internal flow after dispatching the Related Docs Finder; automatic in Full mode, including non-interactive)

  • This is a two-stage probe: the cheap discovery+metadata pass below always executes, and the expensive extraction+synthesis executes only when the probe clears the relevance bar (see Escalation check below).
  • Run session discovery, branch/keyword filtering, scan-window selection, deep-dive selection, and per-session extraction directly inside this skill using scripts/session-history/.
  • Read the skill-local synthesis prompt at references/agents/session-historian.md, then dispatch a generic subagent using that prompt content. Do not dispatch a standalone agent by type/name.

Keep the session-history payload tight. A long, keyword-rich payload invites the flow to widen its search. Use this shape:

  • Session context (only if the values resolved cleanly above; otherwise omit): repo name, current git branch.
  • Time window: explicit 7 days unless the documented problem clearly spans a longer arc.
  • Problem topic: one sentence naming the concrete issue — error message, module name, what broke and how it was fixed. Not a paragraph; not a bullet list of related topics.
  • Filter rule (one line): "Only surface findings directly relevant to this specific problem. Ignore unrelated work from the same sessions or branches."
  • Output schema:

``` Structure your response with these sections (omit any with no findings):

  • What was tried before
  • What didn't work
  • Key decisions
  • Related context ```

Do not append additional context blocks, exclusion lists, or topic-keyword bullets. Verbose payloads let the session-history flow keep widening the search, which rapidly compounds wall time. If keyword search is needed, the internal flow decides that from the topic.

  • Returns a structured digest, or no relevant prior sessions. Either is a valid final Phase 1 input, and the documentation gets written without session context when it is the latter.

Script resolution. Set SKILL_DIR to the absolute path of the directory containing the SKILL.md you just read, and run the bundled scripts from "$SKILL_DIR/scripts/session-history/". Set SKILL_DIR inline in each bash block below (shell state does not persist between commands). If the bundled scripts are genuinely not present on disk under "$SKILL_DIR/scripts/session-history/", skip session history visibly with: "Session history bundled scripts were not found in this skill's directory; skipping the session-history probe for this run." Continue Phase 2 without session context.

Discovery pipeline. Infer the scan window from the problem topic, starting with 7 days. Run discovery and metadata extraction:

bash SKILL_DIR="<absolute path of the directory containing the SKILL.md you just read>"; if [ -f "$SKILL_DIR/scripts/session-history/discover-sessions.sh" ] && [ -f "$SKILL_DIR/scripts/session-history/extract-metadata.py" ]; then PY="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"; [ -n "$PY" ] || { echo "no working Python 3 interpreter on PATH" >&2; exit 1; }; REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd); REPO_NAME=$(basename "$REPO_ROOT"); SCAN_DAYS="7"; bash "$SKILL_DIR/scripts/session-history/discover-sessions.sh" "$REPO_NAME" "$SCAN_DAYS" --cwd "$REPO_ROOT" | tr '\n' '\0' | xargs -0 "$PY" "$SKILL_DIR/scripts/session-history/extract-metadata.py" --cwd-filter "$REPO_ROOT"; else echo "Session history bundled scripts were not found in this skill's directory; skipping the session-history probe for this run."; fi

The command prints JSONL. xargs may split a long file list across several runs of the script; each run prints one object per kept session, then its own _meta line. Parse the output one line at a time, because the stream as a whole is not one JSON document. A pass's files_processed total is the sum across its _meta lines; a --keyword re-run is a new pass, not more files. Optional fields are omitted, not set to null, so a missing key is not an error. Rank recency by last_ts, falling back to ts. If you process the output with code, look at a few lines first and use the keys you see.

Claude sessions live under ~/.claude/projects/ unless CLAUDE_CONFIG_DIR is set, in which case they live under that directory's projects/. Codex sessions live under ~/.codex/sessions/ unless CODEX_HOME is set, in which case they live under that directory's sessions/; ~/.agents/sessions/ is also scanned. Pi sessions are included when present under ~/.pi/agent/sessions/ (PI_CODING_AGENT_DIR / PI_CODING_AGENT_SESSION_DIR override), and oh-my-pi (omp) sessions under ~/.omp/agent/sessions/ (named profiles: ~/.omp/profiles/<name>/agent/sessions/; XDG: $XDG_DATA_HOME/omp/sessions and $XDG_DATA_HOME/omp/profiles/<name>/sessions; PI_CONFIG_DIR / PI_CODING_AGENT_DIR / PI_CODING_AGENT_SESSION_DIR override). Claude, Codex, Pi, and oh-my-pi (omp) sessions carry a recorded cwd (Claude also has git branch; Pi/omp do not). --cwd-filter keeps a session when that cwd is the repo root, an ancestor of it, or a path inside it (path-component boundaries: my-repo vs my-repo-old do not match). Claude, Codex, Pi, and omp sessions with no recorded cwd are dropped. Cursor has no cwd and stays. Do not drop a Claude session because its project folder name lacks the repo basename. That is how Claude stores parent-started sessions. If the first pass's files_processed total is 0, return no relevant prior sessions. If the first pass finds no relevant branch matches, or if processing Codex, Pi, or oh-my-pi (omp) sessions, derive 2-4 keywords from the topic and re-run metadata extraction with --keyword K1,K2,.... Keep at most 5 sessions across Claude Code, Codex, Cursor, Pi, and oh-my-pi (omp), ranked by branch match, keyword match count, file size over 30KB, and recency. Exclude the current session.

Escalation check. The discovery+metadata pass above is the cheap probe and always runs in Full mode. Escalate to the extraction and synthesis stages below only when at least one retained candidate clears the relevance bar: a current-branch match, or ≥2 topic-keyword matches. If no candidate clears the bar (including a files_processed total of 0), stop here, record no relevant prior sessions as the session-history input, and skip extraction and synthesis. This check is what keeps the always-on probe cheap. The expensive synthesis runs only when a prior session is genuinely relevant.

Extraction pipeline. Create SCRATCH=$(mktemp -d "${TMPDIR:-/tmp}/ce-compound-sessions-XXXXXX"). For each selected session, write extracted content to scratch files:

bash SKILL_DIR="<absolute path of the directory containing the SKILL.md you just read>"; if [ -f "$SKILL_DIR/scripts/session-history/extract-skeleton.py" ]; then PY="$(for c in python3 python py; do command -v "$c" >/dev/null 2>&1 && "$c" -c '' >/dev/null 2>&1 && { echo "$c"; break; }; done)"; [ -n "$PY" ] || { echo "no working Python 3 interpreter on PATH" >&2; exit 1; }; "$PY" "$SKILL_DIR/scripts/session-history/extract-skeleton.py" --output "$SCRATCH/<session-id>.skeleton.txt" < <session-file>; else echo "Session history bundled scripts were not found in this skill's directory; skipping the session-history probe for this run."; fi

Use extract-errors.py selectively when dead ends or recurring errors are likely useful. Pass only the scratch file paths and metadata to the synthesis subagent.

Synthesis dispatch. Build a generic subagent prompt containing:

  • the full content of references/agents/session-historian.md
  • problem_topic
  • scratch_dir
  • a sessions array with extracted file paths and metadata
  • the output schema above
  • the filter rule above

The subagent reads only the scratch paths, **writes its prose findings to {run_dir}/session-history.md, and returns only that artifact path once the write is confirmed** (the same #956 reliability reason applies, because session-history findings are long-form prose prone to summary-collapse). If {run_id} did not resolve or the artifact write failed, it returns the prose inline instead (per the inline-fallback rule above). If synthesis fails, note the failure and continue without session context.

Raw lines 3 to 72
Starts an agent dispatching :10
Runs code scripts/session-history/ :12
Starts an agent dispatch :13
Starts an agent subagent :13
Runs code scripts/session-history/discover-sessions.sh :40
Runs code scripts/session-history/extract-metadata.py :40
Runs code scripts/session-history/extract-skeleton.py :56