---
name: reflect-session
description: Extract knowledge from the current dev session into vault notes. Scans conversation context as primary source, git diffs as supplementary evidence. Works across multiple repos. Triggers on "/reflect-session", automatically from /finishing-branch.
user-invocable: true
context: conversation
allowed-tools: Read, Write, Edit, Grep, Glob, Bash
---

## Runtime Configuration (Step 0 — before any processing)

Read these files to configure domain-specific behavior:

1. **`ops/derivation-manifest.md`** — vocabulary mapping, platform hints
   - Use `vocabulary.notes` for the notes folder name
   - Use `vocabulary.note` / `vocabulary.note_plural` for note type references
   - Use `vocabulary.cmd_reflect` for the next-phase suggestion

2. **`ops/config.yaml`** — processing depth, pipeline chaining
   - `processing.depth`: deep | standard | quick
   - `processing.chaining`: manual | suggested | automatic
   - `processing.extraction.selectivity`: strict | moderate | permissive

If these files don't exist, use universal defaults.

**Processing depth adaptation:**

| Depth | Behavior |
|-------|----------|
| deep | Full session scan. Extract all categories with strict duplicate checking. Create task files per note. |
| standard | Balanced. Full scan, moderate selectivity. Standard duplicate checking. |
| quick | Compressed. Extract highest-value findings only. Skip semantic duplicate checking. |

## EXECUTE NOW

**Target: $ARGUMENTS**

Parse immediately:
- If target contains `--handoff`: output RALPH HANDOFF block at end
- If target contains `--dry-run`: preview what would be extracted without creating anything
- If target is empty: full session reflection

**Extraction categories:**

| Category | Destination | Example |
|----------|-------------|---------|
| gotcha | `notes/<subfolder>/` | "API X doesn't support Y when Z" |
| decision | `notes/<subfolder>/` | "Chose Redis over in-memory because..." |
| pattern | `notes/<subfolder>/` | "This testing approach works well for..." |
| config-fact | `notes/<subfolder>/` | "Service X needs env var Y set to Z" |
| tool-knowledge | `notes/<subfolder>/` | "CLI flag --foo does unexpected thing" |
| research | `notes/<subfolder>/` | "Found that LLM X performs better at Y" |
| methodology | `ops/methodology/` | "Always check PR status before pushing" |

**Folder routing — pick the right subfolder based on domain:**

Route each note to a subfolder under `notes/` that matches its domain. Examples:

| Domain | Subfolder |
|--------|-----------|
| Backend API, services | `notes/backend/` |
| Frontend, UI components | `notes/frontend/` |
| Infrastructure, deploy, CI/CD | `notes/infrastructure/` |
| LLMs, AI research | `notes/research/` |
| Tools, CLIs, developer experience | `notes/tooling/` |
| Vault scaffolding, methodology | `notes/_meta/` |

Adapt these to your project structure. If no existing subfolder fits, create a new one. The structure should grow organically.

**Execute these steps:**

1. **Read runtime config** — `ops/derivation-manifest.md`, `ops/config.yaml`
2. **Scan conversation (PRIMARY)** — extract all knowledge from the full conversation
3. **Gather git context (SUPPLEMENTARY)** — diffs from ALL repos touched in session
4. **Classify candidates** — identify atomic claims, classify by category
5. **Duplicate check** — scan `notes/` (recursively) and `ops/methodology/` for existing coverage
6. **Create notes** — atomic notes to `notes/<subfolder>/` (pick by domain) or methodology notes to `ops/methodology/`
7. **Create task files** — for vault notes, create queue entries for pipeline processing
8. **Update session JSON** — enrich existing session snapshot with `reflected: true` marker
9. **Report** — structured output showing what was captured

**Anti-shortcut warning:** Do NOT skip conversation scanning. Do NOT rely solely on git diffs. Do NOT create notes whose claims are already covered by existing notes. Do NOT update MEMORY.md — everything goes to vault.

**START NOW.** Reference below explains methodology.

---

# Reflect Session

Extract knowledge from the current dev session. This is `/extract` for work sessions — the conversation itself is the primary source material.

## Philosophy

**Sessions are ephemeral. Knowledge shouldn't be.**

Every dev session produces findings: architectural decisions, gotchas discovered, patterns that worked, configurations figured out. Without systematic capture, this knowledge dies when the session ends. The next session starts from zero.

`/reflect-session` treats the session as a source document. Same decomposition philosophy as `/extract` — atomic claims, quality gates, proper routing — but the source is the conversation + git diffs instead of a file.

## CRITICAL: Conversation-First Extraction

**The conversation is the PRIMARY source. Git diffs are SUPPLEMENTARY.**

Why this matters:
- Sessions often span **multiple repos** — git diffs from one repo miss work in others
- The conversation contains the **WHY** behind decisions — diffs only show the WHAT
- By the time `/reflect-session` runs, you may be on a different branch or repo than where the work happened
- Knowledge about architecture, patterns, debugging insights, and tool behavior lives in the conversation, NOT in diffs

**Extraction order:**
1. **First:** Read the full conversation. Extract ALL knowledge candidates.
2. **Then:** Gather git diffs as evidence to enrich conversation-extracted candidates.
3. **Never:** Skip a conversation finding just because it doesn't appear in diffs.

## Data Sources

### Source 1: Conversation Context (PRIMARY)

Scan the **entire conversation** for:

| Signal | What to Extract |
|--------|----------------|
| Problem → Solution sequences | Gotchas with Symptom/Cause/Fix |
| "I chose X because Y" moments | Architectural decisions with rationale |
| Debugging breakthroughs | Patterns or tool-knowledge |
| Configuration discoveries | Config-facts with exact values |
| Workflow corrections | Methodology (agent behavioral learnings) |
| Research findings | Research claims with specifics |
| Repeated friction | Methodology notes for future sessions |
| New tools/CLIs/systems built | Architecture decisions + patterns |
| Cross-repo work | Config-facts about deployment, integration |

**Multi-repo awareness:**
- The conversation may reference work across multiple repositories
- Track which repos were touched by looking for: `git clone`, `cd`, worktree creation, `npm link`, `scp`, VPS deploys
- Extract knowledge from ALL repos, not just the current working directory

### Source 2: Git Diffs (SUPPLEMENTARY)

Gather diffs from repos touched in the session:

```bash
# Current repo
INTEGRATION=$(git config --get branch.$(git branch --show-current).merge 2>/dev/null | sed 's|refs/heads/||' || echo "staging")
git log --oneline ${INTEGRATION}..HEAD 2>/dev/null
git diff ${INTEGRATION}...HEAD --stat 2>/dev/null
```

**Multi-repo diffs:** If the conversation shows work in other repos, check those too:

```bash
# Example: if session touched ~/projects/my-other-repo
git -C ~/projects/my-other-repo log --oneline --since="8 hours ago" 2>/dev/null
```

Use `--since="8 hours ago"` (or similar) as a fallback when you can't determine the integration branch for external repos.

**If not in a git repo or no branch divergence exists:** That's fine — the conversation is the primary source. Extract from conversation only.

## Workflow

### Phase 1: Scan Conversation (PRIMARY)

**This is the most important phase. Do not rush it.**

1. Read the **full conversation** from start to end
2. For each message exchange, ask: "Did the user or I learn something here that would be useful in a future session?"
3. Pay special attention to:
   - Newly created systems (CLIs, agents, services) — these are almost always worth capturing
   - Integration patterns (how system A connects to system B)
   - Debugging sessions where the root cause was non-obvious
   - Configuration values that took effort to discover
   - Decisions between alternatives where the rationale matters
4. Compile a candidate list with **specific claims**, not vague summaries

**Examples of good vs bad candidates:**

| Bad (too vague) | Good (specific, arguable) |
|----------------|--------------------------|
| "Built a CLI" | "The CLI uses TTY detection (process.stdout.isTTY) to auto-switch between human-readable and JSON output" |
| "Fixed a timezone bug" | "Node.js toISOString() converts to UTC, but setHours() uses local time — mixing them shifts date ranges by timezone offset" |
| "Updated config" | "Config file lives in ~/.myapp/ (the real one) AND ~/project/config/ (repo copy) — only the ~/.myapp/ version is loaded at runtime" |

### Phase 2: Gather Git Context (SUPPLEMENTARY)

1. Run git commands for the current repo
2. If conversation shows work in other repos, check those diffs too
3. Use diffs to **enrich** conversation candidates with specifics (file paths, exact changes)
4. Diffs may also surface changes you didn't notice in conversation — add those as candidates too

### Phase 3: Extract & Classify

For each candidate finding, apply quality gates:

**Quality gates (ALL must pass):**
1. Is this claim specific enough to argue with? (not "configuration matters" but "the agentId field is not valid inside channels.telegram.accounts")
2. Does this claim stand alone? (can be understood without the session context)
3. Would this be useful in a future session? (not session-specific trivia like "renamed variable X to Y")
4. Is this genuinely new? (not covered by existing notes)

**Classify each passing candidate:**
- Categories `gotcha`, `decision`, `pattern`, `config-fact`, `tool-knowledge`, `research` → vault note in `notes/<subfolder>/` (pick subfolder by domain — see folder routing table above)
- Category `methodology` → methodology note in `ops/methodology/`

### Phase 4: Duplicate Check

Before creating anything:

**For vault notes — check `notes/` recursively (includes all subfolders):**

```bash
# Search for key terms from each candidate (recursive through subfolders)
grep -rl "key term" notes/ --include="*.md" | head -10
```

**For methodology notes — check `ops/methodology/`:**

```bash
ls -1 ops/methodology/*.md 2>/dev/null
# Read and compare each existing methodology note against candidates
```

| Check Result | Action |
|-------------|--------|
| No existing coverage | Create new note |
| Existing note covers different aspect | Create new note, link to existing |
| Existing note covers same claim | Skip (report as duplicate) |
| Existing note could be enriched | Extend existing note with new evidence |

### Phase 5: Create Vault Notes

For each vault note candidate (gotcha, decision, pattern, config-fact, tool-knowledge, research):

**Use exact same format as `/extract`:**

```markdown
---
description: [one sentence adding mechanism/scope/implication beyond the title]
type: [gotcha|decision|config|pattern|tool-knowledge|research]
domain: [your-domain — e.g. backend|frontend|infrastructure|research]
status: active
created: YYYY-MM-DD
source: session-reflection
topics: ["[[relevant-map]]"]
---

# [claim as prose title]

[Body: 100-300 words developing the claim with reasoning. Use inline wiki links to connect to related existing notes where genuine connections exist.]

---

Relevant Notes:
- [[related note]] — [relationship context]

Topics:
- [[relevant-map]]
```

**Anti-shortcuts (same as /extract):**
- Do NOT create notes with "notes:" in the description (circular)
- Do NOT create notes whose body just restates the title
- Do NOT use generic relationship labels like "related" — specify the relationship
- Do NOT create wiki links to notes that don't exist yet

### Phase 6: Create Methodology Notes

For methodology candidates, **use exact same format as `/remember`:**

```markdown
---
description: [what this methodology note teaches — specific enough to be actionable]
type: methodology
category: [processing | capture | connection | maintenance | voice | behavior | quality]
source: session-reflection
created: YYYY-MM-DD
status: active
---

# [prose-as-title describing the learned behavior]

## What to Do

[Clear, specific guidance. Not "be careful" but "when encountering X, do Y instead of Z."]

## What to Avoid

[The specific anti-pattern this note prevents.]

## Why This Matters

[What goes wrong without this guidance.]

## Scope

[When does this apply? Always? Only for certain content types?]

---

Related: [[methodology]]
```

After creating methodology notes:
1. Update `ops/methodology.md` MOC (same as /remember Step 4)
2. Check pattern threshold (same as /remember Step 5)

### Phase 7: Create Task Files

For each vault note (NOT methodology notes), create a task file in `ops/queue/`:

```markdown
---
id: [note-basename]
type: claim
source: session-reflection
created: [UTC timestamp]
current_phase: connect
completed_phases: [create]
---

# Extract [note-basename]

## Create
**Created:** [UTC timestamp]
Note: notes/<subfolder>/[note-filename].md
Claim: [note title]

## Connect
(filled by /connect)

## Update
(filled by /update)

## Verify
(filled by /verify)
```

Update `ops/queue/queue.json` with entries:

```json
{
  "id": "[note-basename]",
  "type": "claim",
  "status": "pending",
  "target": "[note title]",
  "batch": "session-[YYYYMMDD-HHMMSS]",
  "file": "[note-basename].md",
  "current_phase": "connect",
  "completed_phases": ["create"]
}
```

### Phase 8: Update Session JSON

**Session snapshots are scoped by conversation ID.** Each Claude Code conversation has a unique `${CLAUDE_SESSION_ID}`. Snapshots from other conversations are invisible to this one.

**Step 8a: Resolve conversation ID**

```bash
# ${CLAUDE_SESSION_ID} is provided by Claude Code runtime
# Use the first 8 chars as short ID for filenames
CONV_ID="${CLAUDE_SESSION_ID}"
CONV_SHORT="${CLAUDE_SESSION_ID:0:8}"
```

**Step 8b: Find existing snapshot for THIS conversation**

```bash
# Only look at snapshots belonging to this conversation
grep -l "\"conversation_id\": \"${CONV_ID}\"" ops/sessions/*.json 2>/dev/null
```

If a matching snapshot exists AND has `"reflected": true`, warn:
- "This conversation was already reflected. Re-running will create duplicates."
- Ask for confirmation before proceeding.

If a matching snapshot exists WITHOUT `"reflected": true`, update it with the reflection fields.

If NO matching snapshot exists, create a new one.

**Step 8c: Create or update the snapshot**

Filename format: `{YYYYMMDD-HHMMSS}-{CONV_SHORT}.json`

The snapshot must include:
- `"conversation_id"`: full `${CLAUDE_SESSION_ID}` — **required, this is the ownership key**
- `"session_id"`: same as filename stem
- `"date_start"`, `"date_end"`: ISO timestamps
- `"slug"`: human-readable session description
- `"git_branch"`, `"cwd"`: context
- `"summary"`: what was done
- `"reflected": true`
- `"reflection_summary"`: brief description of what was captured
- `"reflection_date"`: ISO timestamp

Use Write tool for new snapshots, Edit tool to update existing ones.

**IMPORTANT:** Never read or update snapshots from other conversations. The `conversation_id` field is the ownership boundary.

### Phase 9: Report

```
--=={ reflect-session }==--

Session: [branch name or "no git context"]
Conversation: [CONV_SHORT] (${CLAUDE_SESSION_ID} first 8 chars)
Repos touched: [list of repos worked on]
Commits: [N] ([first commit]..[last commit])
Files changed: [N]

Extracted: [N] notes
  gotchas: [N]
  decisions: [N]
  config-facts: [N]
  patterns: [N]
  tool-knowledge: [N]
  research: [N]
  methodology: [N]

Skipped (existing coverage): [N]
  - [[existing note]] covers [session finding]

Enrichments: [N]
  - [[existing note]] extended with [new evidence]

Notes created:
  - [[note title 1]] → notes/<subfolder>/
  - [[note title 2]] → notes/<subfolder>/
  - [[methodology title]] → ops/methodology/

Session snapshot: ops/sessions/[filename].json (marked reflected)

Next: /connect [first-note] (or /ralph --batch session-[timestamp] to process all)
```

---

## Dry Run Mode

When invoked with `--dry-run`:

1. Execute Phases 1-4 (gather, extract, classify, duplicate check) normally
2. **Skip** Phases 5-8 (no files created or modified)
3. Report what WOULD be created:

```
--=={ reflect-session — dry run }==--

Session: [branch name]
Repos touched: [list]

Would extract: [N] notes
  - [note title 1] (gotcha) → notes/<subfolder>/
  - [note title 2] (decision) → notes/<subfolder>/
  - [methodology title] (methodology) → ops/methodology/

Would skip: [N] (existing coverage)
  - [[existing note]] covers [finding]

Run /reflect-session (without --dry-run) to create these notes.
```

---

## Output: RALPH HANDOFF Format

When invoked with `--handoff`:

```
=== RALPH HANDOFF: reflect-session ===
Target: session reflection

Work Done:
- Notes extracted: [N]
- Methodology notes created: [M]
- Enrichments: [K]
- Duplicates skipped: [J]
- Task files created: [N]

Files Modified:
- notes/<subfolder>/[note-1].md (created)
- notes/<subfolder>/[note-2].md (created)
- ops/methodology/[note].md (created)
- ops/queue/queue.json ([N] tasks added)
- ops/sessions/[session].json (reflected marker)

Learnings:
- [Friction]: [description] | NONE
- [Surprise]: [description] | NONE
- [Methodology]: [description] | NONE
- [Process gap]: [description] | NONE

Queue Updates:
- [N] new tasks added with current_phase: connect
=== END HANDOFF ===
```

---

## Edge Cases

### No Git Context

If not in a git repo or no branch divergence:
- Skip git analysis entirely
- Extract only from conversation context — **this is still fully valid**
- Report "No git context available — extracted from conversation"

### Multi-Repo Sessions

If session touched multiple repos:
- Extract knowledge from ALL repos mentioned in conversation
- Check git diffs for each repo when accessible
- Domain tag notes appropriately (different repos may map to different domains)

### Empty Session

If no extractable findings in conversation:

```
--=={ reflect-session }==--

No extractable findings in this session.
Session was either too short, purely exploratory, or findings were already captured.
```

### No Session JSON

If `ops/sessions/` has no matching session file:
- Skip Phase 8 (session update)
- Note in report: "No session snapshot found to update"

### Already Reflected

If a snapshot for the **current conversation** (`${CLAUDE_SESSION_ID}`) already has `"reflected": true`:
- Warn: "This conversation was already reflected. Re-running will create duplicates."
- Ask for confirmation before proceeding

**Note:** Snapshots from other conversations are ignored entirely. Each conversation only sees its own snapshots.
