# 22 Substitution Frontmatter

> Single-quote isolation probe to fill team-report §1.2 unverified cells. Tests Claude Code pre-substitution in plugin-level hook + skill frontmatter hook + skill body for SESSION_ID, PROJECT_DIR, SKILL_DIR, and user_config.KEY.

- Skill: `kazukinagata/22-substitution-frontmatter` (Agent Skill)
- Install (CLI): `npx skillmds@latest add kazukinagata/22-substitution-frontmatter`
- Raw SKILL.md: https://api.skillmd.com/api/skills/kazukinagata/22-substitution-frontmatter/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Docs & Writing
- Author: kazukinagata (https://skillmd.com/u/kazukinagata)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/kazukinagata/22-substitution-frontmatter

---


# 22-substitution-frontmatter

§1.2 マトリクスの未検証セルを single-quote isolation で観測する probe。

## 観測の仕組み

`'${CLAUDE_SESSION_ID}'` のように **single-quote 内**に `${VAR}` を書くと：
- 事前置換あり → Claude Code 本体が string を書き換え、shell には実値が渡る → log に実値
- 事前置換なし → string そのまま shell に渡る、single-quote で shell expansion 抑止 → log に literal `${...}`

期待結果（v2.1.146 推測）：

| tier | SESSION_ID | PROJECT_DIR | SKILL_DIR | user_config.KEY |
|---|:---:|:---:|:---:|:---:|
| plugin-level | ? | ✅ | ? | ✅ |
| frontmatter | ? | ? | ? | — |
| body | ✅ | ✅ | ✅ | ? |

## step 1: body tier の事前置換を観測 + 直近 log を表示

```bash
proj="${CLAUDE_PROJECT_DIR:-$PWD}"
ver="${VERIFIER_VERSION_DIR:-v-unknown}"
out_dir="$proj/findings/$ver/probe-22"
mkdir -p "$out_dir"

# body tier — single-quote isolation
echo '[BODY] USER_CONFIG_HELLO=${user_config.hello_message}' >> "$out_dir/subst.log"
echo '[BODY] USER_CONFIG_API=${user_config.api_secret}' >> "$out_dir/subst.log"
echo '[BODY] SESSION_ID=${CLAUDE_SESSION_ID}' >> "$out_dir/subst.log"
echo '[BODY] PROJECT_DIR=${CLAUDE_PROJECT_DIR}' >> "$out_dir/subst.log"
echo '[BODY] SKILL_DIR=${CLAUDE_SKILL_DIR}' >> "$out_dir/subst.log"

# show all results
echo "=== subst.log (tier=plugin: SessionStart 経路, tier=fm: 自スキル frontmatter 経路, tier=body: 直前 echo) ==="
cat "$out_dir/subst.log"
```

## 判定ロジック

各行を見て：
- 値が UUID (例: `9307ae27-...`) → 事前置換 ✅
- 値が絶対パス (例: `/home/...`) → 事前置換 ✅
- 値が空 → 事前置換 ✅ だが値が unset
- 値が literal `${CLAUDE_SESSION_ID}` 等 → 事前置換 ❌

完了したら exit。

