mcpField
S
session-learning

session-learning

github.com/rysweetエージェントワークフロー76150 回インストール21 週間前に更新
リポジトリ

session-learning について

amplihack のセッション学習スキルです。会話記録から知見を抽出し、後のセッションで関連する内容を提示します。知見はカテゴリ別の YAML に保存し、意味検索ではなくキーワードで照合します。

主な機能

  1. 01セッション終了時の知見抽出
  2. 02開始時の関連知見の注入
  3. 03カテゴリ別の YAML 保存
  4. 04コマンドによる知見管理
  5. 05フック失敗時も継続する設計

活用シーン

  1. 01デバッグ時に過去の解決策を参照
  2. 02プロジェクトのワークフロー知見を再利用
  3. 03保存した知見の確認や検索

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rysweet/amplihack --skill session-learning

インストール後、Claude Code で/session-learningを入力して読み込まれたか確認します。

同梱ファイルREADME.md

詳細

セッション学習スキル

目的

このスキルは、次の方法でセッションをまたいだ学習を実現します。

  1. Stop フックでセッションのトランスクリプトから学びを抽出します
  2. 学びを構造化された YAML 形式(~/.amplihack/.claude/data/learnings/)で保存します
  3. タスクの類似性に基づき、SessionStart で関連する過去の学びを注入します
  4. /amplihack:learnings 機能で学びを管理します

設計思想

徹底的にシンプルなアプローチ:

  • 学習カテゴリごとに YAML ファイルを 1 つ使用します(セッションごとではありません)
  • 関連性の判定にはシンプルなキーワードマッチングを使用します(複雑な ML は使用しません)
  • 既存の DISCOVERIES.md/PATTERNS.md を補完します。置き換えるものではありません
  • フェイルセーフ:セッションの開始や終了を妨げることはありません

学習カテゴリ

学びは次の 5 つのカテゴリに保存されます。

カテゴリファイル目的
errorserrors.yamlエラーパターンとその解決策
workflowsworkflows.yamlワークフローに関する知見と近道
toolstools.yamlツールの使用パターンと注意点
architecturearchitecture.yaml設計上の決定とトレードオフ
debuggingdebugging.yamlデバッグ戦略と根本原因

YAML スキーマ

各学習ファイルは次の構造に従います。

# .claude/data/learnings/errors.yaml
category: errors
last_updated: "2025-11-25T12:00:00Z"
learnings:
  - id: "err-001"
    created: "2025-11-25T12:00:00Z"
    keywords:
      - "import"
      - "module not found"
      - "circular dependency"
    summary: "Circular imports cause 'module not found' errors"
    insight: |
      When module A imports from module B and module B imports from module A,
      Python raises ImportError. Solution: Move shared code to a third module
      or use lazy imports.
    example: |
      # Bad: circular import
      # utils.py imports from models.py
      # models.py imports from utils.py

      # Good: extract shared code
      # shared.py has common functions
      # both utils.py and models.py import from shared.py
    confidence: 0.9
    times_used: 3

このスキルを使用するタイミング

自動使用(フック経由):

  • セッション終了時:トランスクリプトから学びを抽出します
  • セッション開始時:プロンプトのキーワードに基づいて関連する学びを注入します

手動使用:

  • 学びを表示または管理したい場合
  • デバッグ中に過去の解決策を確認したい場合
  • プロジェクト固有のパターンを把握するためにオンボーディングする場合

学びの抽出プロセス

ステップ 1:セッションのトランスクリプトを分析する

セッション終了時に、次の内容を確認します。

  1. エラーパターン:発生したエラーとその解決方法
  2. ワークフローに関する知見:うまくいった手順、またはうまくいかなかった手順
  3. ツールに関する発見:ツールを効果的に使う新しい方法
  4. アーキテクチャ上の決定:設計上の選択とその根拠
  5. デバッグ戦略:根本原因分析のパターン
ステップ 2:構造化された学びを抽出する

重要な知見ごとに、次の処理を行います。

  1. カテゴリとタイムスタンプに基づいて一意の ID を生成します
  2. コンテキストからキーワードを抽出します(関連性の高い用語を 3~5 個)
  3. 1 文の要約を作成します
  4. 説明を添えて詳しい知見を記述します
  5. 該当する場合はコード例を含めます
  6. 信頼度スコアを割り当てます(0.5~1.0)
ステップ 3:既存の学びと統合する
  1. キーワードの重複を使って学びの重複を確認します
  2. 類似する学びが見つかった場合(キーワード一致率が 60% 超)、信頼度を更新します
  3. それ以外の場合は、新しい学びをカテゴリファイルに追加します

学びの注入プロセス

ステップ 1:タスクのキーワードを抽出する

セッション開始時のプロンプトから、次の内容を抽出します。

  • 技術用語(言語、フレームワーク、ツール)
  • 問題を示す語句(error、fix、debug、implement)
  • ドメインキーワード(api、database、auth など)
ステップ 2:関連する学びを探す

各学習カテゴリについて、次の処理を行います。

  1. YAML から学びを読み込みます
  2. タスクとのキーワードの重複度を計算します
  3. overlap_score * confidence * recency_weight で順位付けします
  4. 関連性が最も高い学びを上位 3 件選択します
ステップ 3:コンテキストを注入する

関連する学びをコンテキストとして整形します。

## Past Learnings Relevant to This Task

### [Category]: [Summary]

## [Insight with example if helpful]

使用例

例 1:自動抽出
Session: Debugging circular import issue in Neo4j module
Duration: 45 minutes
Resolution: Moved shared types to separate file

Extracted Learning:
- Category: errors
- Keywords: [import, circular, neo4j, type]
- Summary: Circular imports in Neo4j types cause ImportError
- Insight: When Neo4jNode imports from connection.py which imports
  Node types, move types to separate types.py module
- Example: types.py with dataclasses, connection.py imports from types.py
例 2:自動注入
Session Start Prompt: "Fix the import error in the memory module"

Matched Learnings:
1. errors/err-001: "Circular imports cause 'module not found' errors" (85% match)
2. debugging/dbg-003: "Use `python -c` to isolate import issues" (60% match)

Injected Context:
## Past Learnings Relevant to This Task

### Errors: Circular imports cause 'module not found' errors
When module A imports from module B and B imports from A, Python raises
ImportError. Solution: Move shared code to a third module or use lazy imports.
---
例 3:手動管理
User: Show me what I've learned about testing

Claude (using this skill):
1. Reads .claude/data/learnings/workflows.yaml
2. Filters learnings with keywords containing "test"
3. Displays formatted list with summaries and examples

キーワードマッチングアルゴリズム

シンプルで効果的なマッチングです。

def calculate_relevance(task_keywords: set, learning_keywords: set) -> float:
    """Calculate relevance score between 0 and 1."""
    if not task_keywords or not learning_keywords:
        return 0.0

    # Count overlapping keywords
    overlap = task_keywords & learning_keywords

    # Score: overlap / min(task, learning) to not penalize short queries
    return len(overlap) / min(len(task_keywords), len(learning_keywords))

統合ポイント

Stop フックとの統合

Stop フックは、このスキルを呼び出して学びを抽出できます。

  1. トランスクリプトを解析し、重要なイベントを特定します
  2. エラーパターン、解決策、知見を識別します
  3. 適切なカテゴリの YAML に保存します
  4. 抽出の概要を記録します
Session Start フックとの統合

Session Start フックは、関連する学びを注入できます。

  1. 初期プロンプトを解析してキーワードを抽出します
  2. 各カテゴリから一致する学びを探します
  3. コンテキスト注入用に整形します
  4. セッションのコンテキストに含めます
/amplihack:learnings コマンドを使用する場合

学習管理用のコマンドインターフェイス:

  • /amplihack:learnings show [category] - 学習内容を表示
  • /amplihack:learnings search <query> - すべてのカテゴリを対象に検索
  • /amplihack:learnings add - 学習内容を手動で追加
  • /amplihack:learnings stats - 学習統計を表示

品質ガイドライン

抽出する場合

次の場合に学習内容を抽出します。

  • 問題の解決に10分以上かかった
  • 一見してわかりにくいツールの動作を発見した
  • 広く応用できるパターンを見つけた
  • トレードオフを伴うアーキテクチャ上の決定を行った
抽出しない場合

次の場合は抽出を見送ります。

  • 問題が単純なタイプミスや構文エラーだった
  • 解決方法がすでに DISCOVERIES.md または PATTERNS.md に記載されている
  • 再利用するには知見がプロジェクト固有すぎる
  • 確信度が低い(<0.5)
学習内容の品質チェックリスト
  • キーワードが具体的で検索しやすい
  • 要約が明確な一文になっている
  • 知見で「何を」だけでなく「なぜ」を説明している
  • 例が最小限で、そのまま実行できる
  • 確信度が実際の確かさを反映している

ファイルの場所

.claude/
  data/
    learnings/
      errors.yaml        # Error patterns and solutions
      workflows.yaml     # Workflow insights
      tools.yaml         # Tool usage patterns
      architecture.yaml  # Design decisions
      debugging.yaml     # Debugging strategies
      _stats.yaml        # Usage statistics (auto-generated)

既存システムとの比較

機能DISCOVERIES.mdPATTERNS.mdセッション学習
形式MarkdownMarkdownYAML
対象ユーザー人間人間エージェントと人間
保存場所単一ファイル単一ファイルカテゴリごとのファイル
マッチング手動で読み込み手動で読み込みキーワードベースの自動処理
注入手動手動自動
範囲重要な発見実証済みのパターン役立つあらゆる知見

併用方法:

  • 重要で十分に文書化された発見には DISCOVERIES.md を使用します
  • 実証済みで再利用可能なコード付きのパターンには PATTERNS.md を使用します
  • 今後のセッションに役立つちょっとした知見には Session Learning を使用します

エラー処理

YAML の解析エラー

学習ファイルが破損したり無効になったりした場合:

import yaml
from pathlib import Path

def safe_load_learnings(filepath: Path) -> dict:
    """Load learnings with graceful error handling."""
    try:
        content = filepath.read_text()
        data = yaml.safe_load(content)
        if not isinstance(data, dict) or "learnings" not in data:
            print(f"Warning: Invalid structure in {filepath}, using empty learnings")
            return {"category": filepath.stem, "learnings": []}
        return data
    except yaml.YAMLError as e:
        print(f"Warning: YAML error in {filepath}: {e}")
        # Create backup before recovery
        backup = filepath.with_suffix(".yaml.bak")
        filepath.rename(backup)
        print(f"Backed up corrupted file to {backup}")
        return {"category": filepath.stem, "learnings": []}
    except Exception as e:
        print(f"Warning: Could not read {filepath}: {e}")
        return {"category": filepath.stem, "learnings": []}
ファイルが見つからない場合

learnings ディレクトリが存在しない場合は、作成します。

def ensure_learnings_directory():
    """Create learnings directory and empty files if missing."""
    learnings_dir = Path(".claude/data/learnings")
    learnings_dir.mkdir(parents=True, exist_ok=True)

    categories = ["errors", "workflows", "tools", "architecture", "debugging"]
    for cat in categories:
        filepath = learnings_dir / f"{cat}.yaml"
        if not filepath.exists():
            filepath.write_text(f"category: {cat}\nlearnings: []\n")
フェイルセーフの原則

学習システムは、フェイルセーフ設計に従います。

  • セッションの開始を妨げない:注入に失敗しても、セッションは通常どおり続行します
  • セッションの終了を妨げない:抽出に失敗しても、セッションは通常どおり終了します
  • 警告をログに記録して処理を続行する:エラーはログに記録され、例外は発生しません
  • 変更前にバックアップを作成する:破損したファイルは保持されます

フックとの統合

Stop フック:学習内容の抽出

Stop フックに学習内容の抽出を追加します。

# .claude/tools/amplihack/hooks/stop_hook.py

async def extract_session_learnings(transcript: str, session_id: str):
    """Extract learnings from session transcript at stop."""
    from pathlib import Path
    import yaml
    from datetime import datetime

    # Only extract if session was substantive (not just a quick question)
    if len(transcript) < 1000:
        return

    # Use Claude to extract insights (simplified example)
    extraction_prompt = f"""
    Analyze this session transcript and extract any reusable learnings.

    Categories:
    - errors: Error patterns and solutions
    - workflows: Process improvements
    - tools: Tool usage insights
    - architecture: Design decisions
    - debugging: Debug strategies

    For each learning, provide:
    - category (one of the above)
    - keywords (3-5 searchable terms)
    - summary (one sentence)
    - insight (detailed explanation)
    - example (code if applicable)
    - confidence (0.5-1.0)

    Transcript:
    {transcript[:5000]}  # Truncate for token limits
    """

    # ... call Claude to extract ...
    # ... parse response and add to appropriate YAML files ...

def on_stop(session_data: dict):
    """Stop hook entry point."""
    # ... other stop hook logic ...

    # Extract learnings (non-blocking)
    try:
        import asyncio
        asyncio.create_task(
            extract_session_learnings(
                session_data.get("transcript", ""),
                session_data.get("session_id", "")
            )
        )
    except Exception as e:
        print(f"Learning extraction failed (non-blocking): {e}")
セッション開始フック:学習内容の注入

セッション開始フックに学習内容の注入を追加します。

# .claude/tools/amplihack/hooks/session_start_hook.py

def inject_relevant_learnings(initial_prompt: str) -> str:
    """Find and format relevant learnings for injection."""
    from pathlib import Path
    import yaml

    learnings_dir = Path(".claude/data/learnings")
    if not learnings_dir.exists():
        return ""

    # Extract keywords from prompt
    prompt_lower = initial_prompt.lower()
    task_keywords = set()
    for word in prompt_lower.split():
        if len(word) > 3:  # Skip short words
            task_keywords.add(word.strip(".,!?"))

    # Find matching learnings
    matches = []
    for yaml_file in learnings_dir.glob("*.yaml"):
        if yaml_file.name.startswith("_"):
            continue  # Skip _stats.yaml

        try:
            data = yaml.safe_load(yaml_file.read_text())
            for learning in data.get("learnings", []):
                learning_keywords = set(k.lower() for k in learning.get("keywords", []))
                overlap = task_keywords & learning_keywords
                if overlap:
                    score = len(overlap) * learning.get("confidence", 0.5)
                    matches.append((score, learning))
        except Exception:
            continue

    # Return top 3 matches
    matches.sort(key=lambda x: x[0], reverse=True)
    if not matches:
        return ""

    context = "## Past Learnings Relevant to This Task\n\n"
    for score, learning in matches[:3]:
        context += f"### {learning.get('summary', 'Insight')}\n"
        context += f"{learning.get('insight', '')}\n\n"

    return context

def on_session_start(session_data: dict) -> dict:
    """Session start hook entry point."""
    initial_prompt = session_data.get("prompt", "")

    # Inject relevant learnings
    try:
        learning_context = inject_relevant_learnings(initial_prompt)
        if learning_context:
            session_data["injected_context"] = learning_context
    except Exception as e:
        print(f"Learning injection failed (non-blocking): {e}")

    return session_data

制限事項

  1. キーワードマッチングは完璧ではありません - 関連する学習内容を見落としたり、無関係な内容にマッチしたりする場合があります
  2. 意味的な理解は行いません - 表現が異なるものの概念的に似ている知見にはマッチできません
  3. 保存先はローカルです - 学習内容はマシン間で同期されません
  4. 手動での整理が必要です - 古い学習内容や誤った学習内容は定期的に確認する必要があります

今後の改善

必要に応じて、以下を検討してください。

  • より適切なマッチングのための埋め込みベースの類似度判定
  • git によるマシン間同期
  • 時間の経過に伴う確信度の自動低下
  • グラフベースの学習関係を実現するための Neo4j との統合

成功指標

有効性を追跡します。

  • 注入率:関連する学習内容が注入されたセッションの割合
  • 利用率:注入された学習内容が問題解決に役立った頻度
  • 増加率:週ごとの新しい学習内容の数
  • 品質:学習内容の関連性に関するユーザーのフィードバック

コメント