# Np Chunk Context Check

> stripHeaders 文脈欠落チェックの検知ロジック・重症度判定・出力フォーマットのリファレンス。エントリポイントは /np:chunk-context-check コマンド。

- Skill: `kayac/np-chunk-context-check` (Agent Skill)
- Install (CLI): `npx skillmds@latest add kayac/np-chunk-context-check`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kayac/np-chunk-context-check/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: kayac (https://skillmd.com/u/kayac)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kayac/np-chunk-context-check

---


# np:chunk-context-check - stripHeaders 文脈欠落チェック

## 概要

Mastra RAG の markdown chunking（`stripHeaders: true` デフォルト）により、`#`/`##`/`###` 見出しがチャンクテキストから除外される。
見出しが提供していた文脈（「何月か」「何の料金か」「何年度か」等）がチャンク本文から消失した結果、Vectorize のセマンティック検索で正しいチャンクを返せなくなる問題を**検知**するスキル。

## 背景

### Mastra の chunking 仕様

```typescript
// server/src/services/knowledge/embedding.ts
await doc.chunk({
  strategy: "markdown",
  headers: [["#", "title"], ["##", "section"], ["###", "subsection"]],
  // stripHeaders: true（デフォルト）→ 見出しはテキストから除外
});
```

- `getText()` → 本文のみ（見出しなし）→ **この文字列が embedding される**
- `getMetadata()` → `{ title, section, subsection }` → **Vectorize の metadata に格納されるが検索には使われない**

### 問題が発生する条件

以下の**両方**を満たすとき、チャンクの検索精度が著しく低下する:

1. **見出しが文脈の主要な識別子** — 見出しを除くと「何についてのデータか」が本文から判別できない
2. **同一ファイル内に構造的に類似したチャンクが複数** — embedding がほぼ同一ベクトルになり、どのチャンクも同スコアで返される

### 具体例

| ファイル | 見出し | 本文 | 問題 |
|---------|--------|------|------|
| ゴミカレンダー | `## 4月（2026年）` | `[{"日付":"1日",...}]` | 全12月のJSONが同構造。4月を聞いても7月が返る |
| 広報イベント | `## 2025年2月号` | イベントリスト | 年月が本文にない場合、号の区別不能 |
| 料金表ページ | `## 入浴料金` | 金額テーブル | 「何の料金か」が本文にない |

## 検知ロジック

### Phase 1: チャンク分割シミュレーション

ファイルを `##` で分割し、各セクションについて:
- 見出しテキスト（section）
- 本文テキスト（content）
を抽出。実際の Mastra chunk と同等の分割を再現する。

### Phase 2: 文脈欠落スコアリング

各チャンクに対して「見出しの情報が本文にどれだけ含まれるか」をスコアリング:

```
context_coverage = (見出しの主要キーワードのうち本文に含まれる数) / (見出しの主要キーワード数)
```

- 主要キーワード = 見出しから助詞・記号を除いた名詞・数詞
- 例: `## 4月（2026年）` → キーワード: `["4月", "2026年"]`
- 例: `## 入浴料金` → キーワード: `["入浴", "料金"]`

### Phase 3: 構造類似度チェック

同一ファイル内のチャンク間で構造類似度を計算:
- JSONチャンク: キー名の集合が一致するか
- テーブルチャンク: カラム名が一致するか
- プレーンテキスト: 先頭パターン（箇条書き構造等）が一致するか

### 重症度判定

| レベル | 条件 | 意味 |
|--------|------|------|
| **CRITICAL** | context_coverage = 0 かつ 同構造チャンク3+ | 見出し情報が完全に欠落し、embedding で区別不能 |
| **WARNING** | context_coverage = 0 かつ 同構造チャンク2以下 | 見出し情報は欠落だが、構造でユニーク性あり |
| **WARNING** | context_coverage < 0.5 かつ 同構造チャンク3+ | 部分的に識別可能だが不十分 |
| **INFO** | context_coverage < 0.5 かつ 同構造チャンク2以下 | 軽微。改善の余地あり |

## 出力フォーマット

```
🔍 ナレッジ X線検査レポート
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

スキャン対象: {対象パス} ({ファイル数}ファイル)
検出: XX 件（CRITICAL: X, WARNING: X, INFO: X）

─── CRITICAL ─────────────────────────
⚠️  {ファイルパス}
    {同構造チャンク数}チャンクが文脈欠落（context_coverage=0）
    見出し例: "{section1}", "{section2}", ...
    本文構造: {構造の説明}（JSONキー/テーブルカラム等）
    キーワード欠落: {見出しにあるが本文にないキーワード}

─── WARNING ──────────────────────────
⚠️  {ファイルパス}:{行番号付近}
    section: "{section}"
    context_coverage: {スコア}
    欠落キーワード: {リスト}

─── 統計 ──────────────────────────────
スキャンチャンク数: {total}
CRITICAL: {count} ({percent}%)
WARNING: {count} ({percent}%)
INFO: {count} ({percent}%)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```

## 修正について

このスキルは**検知のみ**を行う。修正は検知結果を見て人間が判断する。

修正の一般的なアプローチ:
- **データ側の修正**: 見出し情報を含む要約文をチャンク本文の冒頭に追加
- **コード側の修正**: `embedding.ts` で `stripHeaders: false` にする、または metadata filter を search.ts に追加
- **ハイブリッド**: 特に CRITICAL な箇所のみデータ修正、コード側は別タスクで対応

いずれの場合も、修正後に再度 `/np:chunk-context-check` でスキャンして CRITICAL/WARNING が解消されたことを確認する。

