agentleFS
trappletrapple/skills/user-journey/SKILL.md

user-journey

Skill0 starsChanged 4 months agoMITView on GitHub

プロジェクトで「ユーザーが何をできるか / どんな体験をするか」を、SQLite (data/user_journey.db) に体験レベルの短文で蓄積したナレッジベースを検索・追加する。記録するのは常に「ユーザーは◯◯できる」という高レベルの振る舞い・体験であり、システムの関数・アーキテクチャ・内部実装・仕様パラメータには触れない。**設計ドキュメントを書く前 / コード実装に着手する前 / 仕様判断に迷ったときに必ず関連キーワードで検索し、過去にユーザーが表明した体験像と整合を取る**。ユーザーが新しい振る舞い・体験を望んだときは、体験レベルに抽象化して 1 レコードとして追加する (追加は write 操作なので必ずユーザーの許可を得る)。Use when user says "要件確認", "ジャーニー検索", "user_journey", "ユーザージャーニー", "○○の要件は", "○○の方針は", "○○でユーザーは何ができる", "user-journey", or when starting design / implementation work on any feature in this project.

  • Installs packages

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Files
SKILL.md

user-journey

このプロジェクトで「ユーザーが繰り返し参照したい振る舞い・体験」—— すなわち「ユーザーは◯◯できる」という高レベルのユーザージャーニー——を、 SQLite (data/user_journey.db) に体験レベルの短文で蓄積したナレッジベース。 仕様判断の根拠として AI と人間が共通参照する。コミット対象。

このナレッジベースはユーザー体験の現行像だけを保持する。 システムの関数・クラス・アーキテクチャ・内部実装・仕様パラメータは記録しない (詳細は後述「記録の抽象度」)。実装の「どう作るか」は docs / コード / commit に委ね、 ここには「ユーザーにとって何が起きるか」だけを残す。

なぜあるか

  • 「ユーザーは今どう振る舞える / 何を望んでいるか」の現行像を瞬時に引ける
  • 設計・実装が個々の技術判断に沈む前に、常にユーザー体験の全体像へ立ち戻れる
  • 設計書 (docs/) や DESIGN.md に書くほどではない短い体験前提を集約する
  • 現行像 1 本に保つことが目的なので、原則として古いレコードは残さず UPDATE / DELETE で上書きする (履歴は git 履歴で十分。明示指示があった時だけ INSERT で履歴保持)

いつ使うか (必須)

  • 設計ドキュメントを書く前 → 関連キーワードで検索し、想定ユーザー体験と矛盾しないか確認
  • コード実装に着手する前 → 同上
  • 仕様判断に迷ったとき → 対応する体験像が既に記録されていないか確認
  • ユーザーが新しい振る舞い・体験を望んだとき → 体験レベルに抽象化して追加 (write 操作なので要許可)

記録の抽象度 — 常に「ユーザー体験」レベルに抽象化する

このスキルの中心原則。各レコードは 「ユーザー(利用者・閲覧者などの役割)が何をできるか / どんな体験をするか」 を記述する。仕様やシステムの都合をそのまま書かない。

必ずこう書く:

  • 主語は原則ユーザー(または「閲覧者」「管理者」など利用者の役割)。
  • 「ユーザーは〜できる」「ユーザーは〜を選べる」「〜したユーザーは〜を受け取る」のような 観測可能な振る舞い・体験の形にする。
  • ユーザーが画面 / CLI / 成果物 / 通知を通して実際に体験・観測できることだけを書く。

書いてはならない (システム内部への言及は禁止):

  • 関数名・クラス名・テーブル名・API エンドポイント・ライブラリ / フレームワーク名
  • アーキテクチャ構造(レイヤー分割、モジュール構成、フェーズ分割などの内部骨格)
  • 内部データ形式・HTTP ステータスコード・アルゴリズム名・リトライ回数などの実装パラメータ
  • 「どう作るか(実装方針)」——理由や手段はここではなく docs / コードコメント / commit へ

判定テスト: その 1 文を読んで問う—— 「これはユーザーが観測・体験できることか? それともシステムの都合・実装詳細か?」。 ユーザーが体験できないもの(運用・実装の都合)は、そもそも記録しない。

変換例 (仕様寄り → ユーザー体験):

仕様・実装寄り (NG)ユーザー体験 (OK)
エクスポートは CSV を既定フォーマットにするユーザーは追加設定なしで、書き出したデータをそのまま表計算ソフトで開ける
ファイル名に YYYY-MM-DD プレフィックスを付けるユーザーは書き出したファイルを、いつ出力したものか一目で見分けられる
失敗時は 3 回まで指数バックオフでリトライするユーザーは一時的な通信の乱れがあっても、操作をやり直さずに処理を完了できる
認証は OAuth2 / 認可コードフローで行うユーザーは既存のアカウントでそのままサインインでき、新しいパスワードを作らずに済む
ジョブを非同期キューに載せて分割処理するユーザーは大きな処理を投げても画面が固まらず、完了を待たずに他の操作を続けられる
ログは構造化 JSON で出力する(記録しない — ユーザー体験ではなく運用・実装の都合)

追加フローで要約案を作るときは、ユーザーが述べた仕様・実装の言葉をそのまま写さず、 必ずこの変換を通して「ユーザーは何をできるようになるか」へ言い換えてから提示する。

セットアップ

スキーマ:

CREATE TABLE user_journey (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  text TEXT NOT NULL
);

初回利用時のみ: DB ファイルとテーブルが無ければ作成する (read 操作より前に一度だけ)。

mkdir -p data
sqlite3 data/user_journey.db "CREATE TABLE IF NOT EXISTS user_journey (id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT NOT NULL)"

data/user_journey.db やテーブルが無い状態で検索すると Error: no such table: user_journey になるため、最初の操作時にテーブルの存在を確認し、無ければ上記で作成してから進める (CREATE TABLE IF NOT EXISTS なので既存環境では無害)。

操作

検索 (read - 許可不要)

単一キーワード:

sqlite3 data/user_journey.db "SELECT id, text FROM user_journey WHERE text LIKE '%<keyword>%'"

複数キーワード AND(例: 「エクスポート機能でユーザーが何を選べるか」を引き出す):

sqlite3 data/user_journey.db "SELECT id, text FROM user_journey WHERE text LIKE '%エクスポート%' AND text LIKE '%選べる%'"

複数キーワード OR(例: 「サインインまわりでユーザーが体験すること」を集める):

sqlite3 data/user_journey.db "SELECT id, text FROM user_journey WHERE text LIKE '%サインイン%' OR text LIKE '%ログイン%'"

スコープの原則: 機能名・対象ドメインのキーワードを主軸にする。振る舞いの動詞や状態語 (選べる / できる / 受け取る など)は複数ドメインに登場するため単独 OR で引くと無関係な行を 巻き込む。動詞・状態語は主軸キーワードとの AND 絞り込みに使い、OR でヒットした 行は各レコード冒頭の機能名 / 役割で関連性を再判定してから提示する(無関係ドメインの行は除外)。

全件列挙 (read - 許可不要)

sqlite3 data/user_journey.db "SELECT id, text FROM user_journey ORDER BY id"

検索結果の返し方

ヒット件数によって user への提示の粒度を変える。長文の貼り付けは避け、id 付きで簡潔に。

  • 0 件: 「該当する既存の体験像はありません。新しいユーザー体験として追加候補か確認します」と伝え、 ユーザーが新しい振る舞いを望んでいる文脈なら追加 (write) の提案フローに進む。
  • 1〜3 件: 各レコードの id と text をそのまま箇条書きで提示。
    関連する既存のユーザー体験:
    - id 7: ユーザーはデータを書き出すとき、追加設定なしでそのまま表計算ソフトで開ける
    - id 8: ユーザーは書き出したファイルを、いつ出力したものか一目で見分けられる
  • 4〜9 件: 件数を伝えて重要度の高い 3〜5 件だけ抜粋、残りは「他 N 件」と要約。 ユーザーが全件を求めたら追加で列挙する。
  • 10 件以上: フラットな抜粋では情報が落ちすぎるので、カテゴリ別に整理して提示してよい (体験の軸で束ねる。例: 「できること 5 件 / 選べること 2 件 / 受け取れる結果・通知 3 件 / ...」)。
    • 件数の方針: カテゴリ別整理なら 全件提示してよい(落とすと設計判断材料が欠落するため)。 ただし関連度が極端に低いカテゴリは「他 N 件」と要約で省略可。
    • カテゴリ内の順序: 重要度の高いものから並べる。
    • カテゴリ間の順序: 重要度の高いカテゴリを先頭に。設計着手前なら 中心となる体験(何ができるか) → 選べること・分岐 → 受け取れる結果・通知 → 利用の前提・制約 の順が標準。体験の変更・追加時は 「矛盾しうるカテゴリ」を最優先 に並べ替える。
    • 各レコードのカテゴリ割り当て: 「ユーザーがどんな体験の局面にいるか」で振り分ける。代表例: 主要な行動ができる → 中心となる体験 / 複数の選択肢から選べる → 選べること / 成果物・通知・フィードバックを受け取る → 受け取れる結果・通知 / 利用できる範囲・状態の前提 → 利用の前提・制約。境界ケースは「設計でどの判断に使うか」で寄せる。
  • 重要度の判定基準: 「現在のタスクへの関連度」。
    • 設計着手前なら「ユーザーが中心的に何をできるか / どの体験の分岐があるか」が高、 周辺の細かな体験は低。
    • 新しい体験の追加・変更時なら「矛盾しうる既存の体験像」が最優先。
    • 迷ったら「user が次の判断に使う情報か?」で切り分ける。
  • いずれの場合も検索に使ったキーワードを 1 行で添えて「他にどの語で引きたいか」を ユーザーが指示しやすくする。

追加 (write - 必ずユーザーの許可を得てから)

ユーザーが新しい振る舞い・体験を望んだら、以下のフローで進める:

  1. 体験レベルへ抽象化した要約案を提示 — ユーザーが述べた仕様・実装の言葉を写さず、 「記録の抽象度」の変換を通して「ユーザーは何をできるようになるか」へ言い換える。 AskUserQuestion で確認する。標準テンプレ:
    {
      "header": "user_journey 追加",
      "question": "○○ に関するユーザー体験として『<体験レベルの要約文>』を追加してよいですか?",
      "options": [
        { "label": "はい、この文面で追加", "description": "提示した要約文のまま INSERT を実行" },
        { "label": "文面を直したい",       "description": "要約文を修正してから追加(差し戻し)" },
        { "label": "追加しない",           "description": "今回はナレッジベースに残さない" }
      ]
    }
  2. 承諾されたら INSERT を実行(RETURNING id で新 id を同時取得):
    sqlite3 data/user_journey.db "INSERT INTO user_journey(text) VALUES('<体験レベルの短文 1〜2 文>') RETURNING id"
    RETURNING が使えない古い SQLite なら別途 SELECT last_insert_rowid() で取得。
  3. 新 id を user に報告 — 「id N として登録しました」と返す。後で他文書から参照しやすい。

text の規約 (それぞれ理由付き):

  • ユーザー体験レベルで書く — 「記録の抽象度」の原則を満たすこと。システムの関数・ アーキテクチャ・実装詳細に触れる文は、体験レベルに言い換えるか、記録しない。
  • 1 レコード = 1 つの体験 (複数まとめない) — 検索で一方だけ引きたいときに片方が埋もれるのを防ぐ。 id で粒度よく引用できる。
  • 短文 1〜2 文 — 全文 LIKE 検索なので、長文だとノイズが増えてヒット率が下がる。
  • 文脈に依存しない自己完結した記述 — 「これ」「先ほどの」のような指示語を使わない。 キーワード検索でいきなり 1 件だけ引いても意味が通るように。
  • 機能名や対象ドメインを冒頭に含める (例: 「エクスポートで〜」「サインインで〜」) — ドメイン横断のキーワード検索で確実にヒットさせるため。
  • シングルクォート ' を含む場合は '' でエスケープ — SQLite の文字列リテラル仕様。

更新・削除 (write - 必ずユーザーの許可を得てから)

user_journey は「現行のユーザー体験像」を 1 本で表すナレッジベースなので、 原則として既存レコードを UPDATE / DELETE で上書きする。陳腐化した過去版を残すと 検索のたびに「どれが現行か」を判定するノイズになり、現行像を引きにくくなる。 履歴は git 履歴 (commit log) で十分追える。

明示的に「履歴を残して」「過去版も追えるようにして」と言われた場合のみ INSERT で 新レコードを追加する (この場合 id 連番が時系列の代理)。

sqlite3 data/user_journey.db "UPDATE user_journey SET text = '<new>' WHERE id = <N>"
sqlite3 data/user_journey.db "DELETE FROM user_journey WHERE id = <N>"

乖離検知時の取り扱い

ユーザーの新しい要望が既存レコードと矛盾するとき:

  1. 関連既存レコードを検索で発見し、id と本文を引用して 矛盾点を明示する (「id N と新ご要望が矛盾します」と冒頭で言い切る)。
  2. AskUserQuestion で取り扱いを確認する。標準テンプレ(4 択):
    {
      "header": "user_journey 乖離検知",
      "question": "id <N> (<既存の体験像>) と新ご要望 (<新しい体験の要約>) が矛盾します。どう取り扱いますか?",
      "options": [
        { "label": "既存 id を UPDATE で上書き",       "description": "既定。user_journey は現行像 1 本で保つ原則どおり、既存レコードを新要約で上書き。履歴は git ログで追える。" },
        { "label": "新ルールを INSERT (既存は残す)",   "description": "履歴保持。古いレコードを残して新 id を発行。最新が現行の体験像。過去の判断根拠を DB 内で遡りたい場合に。" },
        { "label": "追加しない / 一旦保留",             "description": "今回は user_journey に反映せず別途検討。" },
        { "label": "文面を直したい",                   "description": "新要約案を編集してから判断(差し戻し)。" }
      ]
    }
  3. 既定は UPDATE 上書き(SKILL.md の「更新・削除」原則と整合)。 ユーザーが INSERT を明示選択した場合のみ履歴保持 INSERT する。
  4. 関連するコード・docs にも波及する可能性があれば、その旨を併記する (DB 更新と実装変更はセットで対応が必要なケースが多い)。

「AskUserQuestion の選択肢 N 個」は場面に応じて 3〜4 個まで増やしてよい (「追加」フローは 3 択標準、「乖離検知」は 4 択が標準)。

他文書からの引用

docs/, DESIGN.md, README.md, コミットメッセージ等から体験像を参照するときは、 user_journey id N という表記で統一する (例: user_journey id 13)。 これにより:

  • 文書間の整合性確認が grep 一発でできる (rg 'user_journey id')
  • 体験本文を引用先に転記しないので、体験像が更新されても二重管理にならない
  • レビュアが id を見て DB を引けば一次情報に到達できる

複数 id をまとめて参照する場合は user_journey id 1, 7-9 のようにレンジ表記してよい。

推奨ワークフロー

タスク着手の最初:

  1. 関連キーワード 2〜3 個で検索 (機能名 + ドメイン用語 + 振る舞いの動詞 を組み合わせる):
    sqlite3 data/user_journey.db "SELECT id, text FROM user_journey WHERE text LIKE '%エクスポート%'"
    sqlite3 data/user_journey.db "SELECT id, text FROM user_journey WHERE text LIKE '%選べる%' OR text LIKE '%できる%'"
  2. ヒットしたら「検索結果の返し方」に沿って user に報告、体験像を尊重して設計・実装に進む
  3. 矛盾が生じたら、「乖離検知時の取り扱い」フローで既存 id を UPDATE で上書き (既定) するか確認
  4. 新しい体験が確定したら write 操作の許可フロー (上記) で、体験レベルに抽象化してから UPDATE (既存 id があれば) / INSERT (新規ドメインなら)

注意

  • sqlite3 CLI が必要 (未インストールなら brew install sqlite3 等)
  • data/user_journey.db はバイナリ (SQLite)。git diff で内容が見えないので、 追加・更新時はコミットメッセージに具体的な text を書くこと
  • 公開ホスティングするプロジェクトでは data/user_journey.db を配信対象から除外する (例: Cloudflare Pages の .assetsignore、静的サイトジェネレータの ignore 設定など)
  • DB ファイル破損時は git 履歴から復元
  • write 操作 (追加・更新・削除) は必ずユーザーの許可を得る、という本スキルの原則は スキル自身の運用にも適用される
  • 記録するのは常にユーザー体験レベル。システムの関数・アーキテクチャ・実装詳細に 触れる文が混ざりかけたら「記録の抽象度」に戻って言い換えるか、記録対象から外す

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.