orca-onboard について
コードベースをコードグラフ、ドメイングラフ、Wiki、HTMLドキュメントに整理するワークフロー用スキルです。ユーザー確認を挟んで段階的に実行し、既存分析の更新にも対応します。
主な機能
- 01コードとGit履歴のスキャン
- 02ナレッジグラフとガイドツアーの生成
- 03ドメイングラフの構築と網羅率確認
- 04WikiとHTMLドキュメントの生成
- 05全再構築と差分更新
活用シーン
- 01新規プロジェクトの概要作成
- 02ドメインフローとコード位置の整理
- 03既存コード分析とドキュメントの更新
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rheinmir/ setup --skill orca-onboardインストール後、Claude Code で/orca-onboardを入力して読み込まれたか確認します。
同梱ファイルassets/docs-site-skeleton.html
詳細
orca-onboard
🧭 ディスパッチバックエンド — 低コストのエージェント/モデルを選択し、複数のワーカーを並列実行します。opencode/オーケストレーションの構文については orca-dispatch-reference を参照してください(唯一の信頼できる情報源です。ここで構文を複製しないでください)。
蒸留された understand-anything パイプライン(グラフ+Git 履歴、プラグインなし)を通じてコードベースをオンボーディングし、ドメイン情報の拡充+Wiki+HTML を生成します。
WHAT
目的とコンテキスト
- 目的: 任意のコードベースを、活用可能な知識に変換します。ナレッジグラフ(スキャン+Git 履歴+バッチ分析+レイヤー/ツアー、プラグインなし)、ドメイングラフ(ドメイン → フロー → ステップ)、Wiki
llmwiki/wiki/、HTML ドキュメントを作成します。推論は Claude のメインスレッドで行い、機械的な処理は opencode+DeepSeek Flash v4 にディスパッチします。 - トリガー(使用するタイミング): 「コードベースをオンボーディング」「コードベースを分析」「ナレッジグラフ」「ガイド付きツアー」「/orca-onboard」。
- 対象外: Understand-Anything プラグインはインストールしません。推論(ドメイン、アーキテクチャ、レイヤー/ツアー)を opencode/agy にディスパッチしません。HTML の生コードを直接書きません(必ず skeleton v2 を使用します)。ファイルパスや file:line を捏造しません。ディスパッチ構文を複製しません(信頼できる唯一の情報源は
orca-dispatch-referenceです)。
メンタルモデル
Phase 0 pre-flight/bootstrap → Phase 0.5 GATE(ドラフト+ディスパッチボード → ユーザー承認) → Phase 1 graph(scan → git history → analyze → merge → layers+tour → validate → [code-graph index]) → Phase 2 domain graph → Phase 3 wiki → Phase 4 HTML(JSON → skeleton v2 → wiki-graph vector) → output report。ドラフト llmwiki/wiki/draft/orca/<DATE>-onboard-<slug>.md は状態管理台帳です。各フェーズの状態は pending → in-progress → done と変化し、再開時にはそこから読み込みます。
入力と出力の契約
| Field | Required? | 意味 | |
|---|---|---|---|
| In | <path> | いいえ(デフォルトは .) | 対象プロジェクトのディレクトリ。@<draft> = 既存のドラフトから再開 |
| In | --full | いいえ | .overstack/graph/ を削除して再構築 |
| In | --update | いいえ | 前回実行時から変更されたファイルのみ再分析(既存のグラフ+meta.json が必要) |
| In | --language <lang> | いいえ | 出力言語(vi、en、zh など) |
| In | --skip-wiki | いいえ | Wiki の生成をスキップ |
| In | Phase 0.5 でのユーザー承認 | はい | ディスパッチボード+提案内容がターミナルに表示された後 |
| In | opencode、スキル docs-site-macos | はい | 不足している場合 → Phase 0 が終了コード 1 で終了し、インストールコマンドを表示 |
| Out | .overstack/graph/knowledge-graph.json、ONBOARDING.md、meta.json | はい | Phase 1(Phase 1 の最終ゲートで最初の 2 ファイルを確認) |
| Out | .overstack/onboard/intermediate/domain-graph.json | はい | Phase 2 |
| Out | .overstack/onboard/intermediate/surface.json + coverage.json | はい | Phase 2 — 実際のサーフェス @commit+カバレッジ台帳。出力レポートには N/M 項目のサーフェスをカバー と表示(スキル surface-coverage) |
| Out | llmwiki/wiki/(index、concepts、entities) | はい。ただし --skip-wiki の場合を除く | Phase 3。すべてのページに ## Origin +インデックス行を含めます |
| Out | llmwiki/html/onboarding-<slug>.html + llmwiki/html/wiki-graph.html | はい(ベクターは fail-open) | Phase 4 |
| Out | 状態ドラフト+インデックス/ログ行 | はい | 各フェーズの後に更新 |
「完了」とは、ドラフトで 4 つのフェーズが done になり、HTML が存在し、出力レポートが記録されている状態です。
ルールと機能
- RULE-01 (MUST): Phase 0 が完了するまで、Phase 0.5 または Phases 1–4 を実行してはいけません。 順序は固定で、変更できません:Phase 0(
llmwiki/の存在を確認)→ Phase 0.5(ユーザーに尋ねる前にドラフトを作成)→ Phases 1–4。 - RULE-02 (MUST):
llmwiki/が存在しない場合は、Phase 0 でブートストラップします。決して後回しにしてはいけません。ブートストラップに失敗した場合は、完全に STOP してエラーを報告します。 - RULE-03 (MUST): 各 phase の後、ドラフトのステータスを直ちに更新します。最後まで先送りしてはいけません。
- RULE-04 (MUST): ゲートの質問をする前に、ディスパッチボードと提案内容を bash 経由で出力しなければなりません(ターミナルに表示されること)。ドラフト内の Agent Task Assignment の行はボードと一致していなければなりません。
- RULE-05 (MUST): 推論タスクは Claude のメインスレッド内で行わなければなりません。推論を opencode/agy に委任してはいけません。 opencode + DeepSeek の用途は、テンプレートへの入力、Wiki のレンダリング、HTML のみです。
- RULE-06 (MUST): 行動する前に読む — 各 phase では、何らかの行動を起こす前に
READ FIRSTブロック内のすべての入力を読みます。ファイルにすでに記載されている内容について、ユーザーに尋ねてはいけません。 - RULE-07 (MUST): Phase 1 の後は
knowledge-graph.json全体を読み込んではいけません — 代わりにONBOARDING.mdを使用します。 - RULE-08 (MUST): 実在するファイルパスのみを使用します。捏造してはいけません。ドメイングラフでは実在するファイルと行のみを参照し、コードと照合して確認します。
- RULE-12 (MUST): ドメイングラフのカバレッジは、実際の表面との差分(
surface-coverage.py check)でN/M 項目の形式で報告します。アプリのすべてを説明したかのように、フローやページの数を報告してはいけません。 - RULE-09 (MUST): Wiki では wikilink 形式
[[page-name]]を使用します。ツアーは 5-15 ステップとし、プロジェクトの概要から始めます。 - RULE-10 (MUST): Phase 4 で生の HTML を直接書いてはいけません。必ず skeleton v2 を使用します。
- RULE-11 (MUST): code-graph のインデックス作成は、
dep-health.py --jsonがstatus == "ok"を返した場合に限ります。設定に記述されていることは、サーバーが稼働していることを意味しません。 - 機能:対象リポジトリと VCS の履歴の読み取り、ローカルスクリプト(bash/python)の実行、機械的な作業への低コスト LLM のディスパッチ、
.overstack/とllmwiki/への書き込み、ブートストラップや依存関係のインストールのためのネットワーク利用。
失敗時の境界
- 依存関係(opencode、docs-site-macos)が不足している、またはプロジェクトルートが存在しない → blocked(exit 1 + インストールコマンド)。
--updateを指定したが、グラフまたはmeta.jsonが存在しない → blocked。先に--updateを付けずに実行するよう伝えます。- ブートストラップに失敗 → failed、完全に STOP します。
- ゲートでユーザーが承認しない → cancelled。ドラフトのみが残ります。
- バッチ分析に 2 回失敗 → バッチを中止し、PHASE_WARNINGS に記録 → partial グラフ(グラフなしより partial graph を優先)。
- Phase 1 のゲートで
knowledge-graph.jsonまたはONBOARDING.mdが不足 → Phase 1 は failed。 - HTTP/CLI/event のエントリーポイントがない → ドメインは空(限定的に succeeded)。
wiki-graph.htmlの描画に失敗 → fail-open。オンボーディングを妨げません。
HOW
メインワークフロー
| ステップ | 種別 | 入力 | アクション | 出力/終了 | 失敗時/次の処理 |
|---|---|---|---|---|---|
| W01 | 決定的 | args, マシン | Phase 0 — 依存関係チェック、resume/root、update mode、llmwiki+harness のブートストラップ、ディレクトリ作成、ファイル数カウント、エージェントのプローブ | 環境変数 + files.txt | 依存関係/root が不足 → exit 1 |
| W02 | 副作用あり | W01 の結果 | Phase 0.5 Gate — まずドラフトを作成し、インデックスとログを作成、dispatch board を表示して提案し、ユーザーに確認 | ドラフト pending、承認 | 承認されない → cancelled |
| W03 | 決定的 | リポジトリ | Phase 1 1.1 SCAN + 1.2 GIT HISTORY(bash)+ 1.3 ANALYZE(静的解析。opencode は補足のみ)+ 1.4 MERGE(python) | assembled-graph.json | バッチ失敗 → 1 回再試行 → 破棄、PHASE_WARNINGS |
| W04 | 判断 | assembled graph、ディレクトリツリー、README | 1.5 LAYERS + TOUR(Claude のメインスレッド) | レイヤー + 5~15 ステップのツアー | — |
| W05 | 決定的 | graph | 1.6 VALIDATE + SAVE + Phase 1 最終ゲート | knowledge-graph.json、meta.json、ONBOARDING.md | ファイル不足 → exit 1 |
| W06 | 判断 | ONBOARDING.md、layers、surface.json | Phase 2 実際の表面領域(surface-coverage.py scan)→ ドメイン補強(Claude)→ check ゲート | domain-graph.json + coverage.json、N/M 項目 の行 | エントリーポイントなし → domains は空。3 回の試行後も check が赤 → 未カバー項目の一覧を付けて partial |
| W07 | 副作用あり | ONBOARDING + domain graph | Phase 3 wiki(opencode、テンプレートへの入力) | llmwiki/wiki/ | opencode エラー → Claude にフォールバック |
| W08 | 副作用あり | ONBOARDING + domain graph + skeleton | Phase 4 STEP A JSON → STEP B skeleton に入力(python)→ STEP C vector | HTML + wiki-graph.html | skeleton 不足 → exit 1。vector エラー → fail-open |
| W09 | 副作用あり | 結果 | 出力レポート + ステータス更新 + sync push | 最終ドラフト、インデックス/ログ | — |
各ステップの詳細(W01~W09 の信頼できる情報源):
トリガー
- 「onboard codebase」、「analyze codebase」、「knowledge graph」、「guided tour」
オプション
--full—.overstack/graph/を削除して再構築--update— 増分更新:前回の実行以降に変更されたファイルのみを再解析--language <lang>— 出力言語(vi、en、zh、...)--skip-wiki— wiki の生成をスキップ<path>— 対象ディレクトリ(デフォルト:.)
進捗
[Phase 1/4] Graph generation (scan + git history + batch analyze + layers/tour)...
[Phase 2/4] Domain enrichment (Claude)...
[Phase 3/4] Wiki generation (opencode + DeepSeek Flash v4)...
[Phase 4/4] HTML docs (opencode + DeepSeek Flash v4)...
⚠️ 厳守ルール
⛔ Phase 0 が完了するまで、Phase 0.5 または Phase 1~4 を実行してはいけません。
厳密な順序 — 逆順は禁止:
- Phase 0 → 完了し、
llmwiki/の存在を確認 ✅ - Phase 0.5(ゲート) → まずドラフトファイルを作成してから、ユーザーに確認
- Phase 1~4 → 実行し、各 Phase の直後にステータスを更新
llmwiki/がない → Phase 0 でブートストラップし、決して後回しにしない- ブートストラップ失敗 → 完全に停止し、エラーを報告
- 各 Phase の直後 → 今すぐドラフトのステータスを更新し、最後まで待たない
ディスパッチルール
TASK TYPE → AGENT → MODEL
──────────────────────────────────────────────────────
Scan + git history → bash/python direct → (no LLM)
Batch file analyze → python static parse → (no LLM — PRIMARY; opencode chỉ enrich)
Merge + validate → python inline → (no LLM)
Layers / tour → Claude main thread → Sonnet (never dispatch out)
Domain reasoning → Claude main thread → Sonnet (never dispatch out)
Wiki / HTML render → opencode → opencode/deepseek-v4-flash-free
推論タスクは必ず Claude のメインスレッドで実行してください。opencode/agy で推論してはいけません。 opencode + DeepSeek:テンプレートへの入力、wiki のレンダリング、HTML のみ。
エージェントのバイナリ
| エージェント | バイナリ | デフォルトモデル | 確認コマンド |
|---|---|---|---|
| Antigravity | agy | Claude (Sonnet/Opus) | agy --version |
| OpenCode | opencode | 設定可能 | opencode --version |
| Kiro | kiro-cli | — | kiro-cli --version |
Understand-Anything プラグインは不要です。 Phase 1 では、Understand-Anything から抽出した手法(scan → batch analyze → merge → layers → tour → validate)をこのスキル内に直接記述して使用します。bash/python + 純粋な opencode prompt + Claude のメインスレッドで実行します。agy/opencode への追加インストールは不要です。
DeepSeek Flash v4 での OpenCode:
opencode run "$SPEC" --model opencode/deepseek-v4-flash-free < /dev/null \
# Fallback if flag unsupported:
echo "$SPEC" | opencode --model opencode/deepseek-v4-flash-free
# Last resort: Claude main thread
ステータス更新ヘルパー
update_phase_status() {
local keyword="$1"
local status="$2"
[ -z "$DRAFT_FILE" ] && echo "[WARN] DRAFT_FILE unset" && return 0
local f=$(echo "$DRAFT_FILE" | tr '\\' '/')
[ ! -f "$f" ] && echo "[WARN] DRAFT_FILE not found: $f" && return 0
perl -i -pe "s/(\Q$keyword\E.*?)\| (?:pending|in-progress|done)/\$1| $status/g if /\Q$keyword\E/" "$f" \
|| sed -i "s/\(.*$(echo "$keyword" | sed 's/[^^]/[&]/g').*\)| [a-z-]*/\1| $status/" "$f" \
|| echo "[WARN] status update failed for: $keyword"
}
Phase 0 — 事前確認とセットアップ
# --- 1. Dependency check (agy optional — Phase 1 dùng distilled pipeline, không cần agy) ---
MISSING=()
opencode --version >/dev/null 2>&1 || MISSING+=("opencode")
ls ~/.agents/skills/docs-site-macos/SKILL.md >/dev/null 2>&1 || MISSING+=("docs-site-macos skill")
if [ ${#MISSING[@]} -gt 0 ]; then
echo "❌ Missing dependencies:"
for dep in "${MISSING[@]}"; do echo " - $dep"; done
echo ""
echo "docs-site-macos: npx skills add rheinmir/setup@orca --skill docs-site-macos --global -y"
exit 1
fi
# --- 2. Resume Mode check & Project Root resolution ---
if [[ "$1" == @* ]]; then
DRAFT_FILE="${1#@}"
DRAFT_FILE=$(echo "$DRAFT_FILE" | tr '\\' '/')
RESUME_MODE=true
PROJECT_ROOT=$(grep "Project root:" "$DRAFT_FILE" | grep -oP '(?<=`)[^`]+(?=`)' | head -1)
PROJECT_ROOT=$(echo "$PROJECT_ROOT" | tr '\\' '/')
else
RESUME_MODE=false
PROJECT_ROOT=${1:-.}
PROJECT_ROOT=$(echo "$PROJECT_ROOT" | tr '\\' '/')
fi
test -d "$PROJECT_ROOT" || { echo "❌ Project root directory not found: $PROJECT_ROOT"; exit 1; }
# --- 3. Update Mode check ---
UPDATE_MODE=false
for arg in "$@"; do
[ "$arg" = "--update" ] && UPDATE_MODE=true
done
if [ "$UPDATE_MODE" = "true" ]; then
[ ! -f "$PROJECT_ROOT/.overstack/graph/knowledge-graph.json" ] \
&& echo "❌ --update requires existing graph. Run without --update first." && exit 1
[ ! -f "$PROJECT_ROOT/.overstack/graph/meta.json" ] \
&& echo "❌ --update requires meta.json. Run without --update first." && exit 1
echo "[update] Incremental mode — reading changed files from meta.json"
CHANGED_FILES=$(python3 -c "
import json, sys
meta = json.load(open('$PROJECT_ROOT/.overstack/graph/meta.json'))
changed = meta.get('changedFiles', meta.get('changed', []))
print('\n'.join(changed))
" 2>/dev/null || echo "")
if [ -z "$CHANGED_FILES" ]; then
echo "[update] no changedFiles in meta.json — falling back to full rebuild"
UPDATE_MODE=false
else
echo "[update] Changed files:"; echo "$CHANGED_FILES"
fi
fi
# --- 4. Bootstrap llmwiki + harness if missing ---
# Harness có 2 mode: GLOBAL (~/.claude/harness + hooks trong ~/.claude/settings.json,
# bảo vệ mọi project llmwiki trên máy này) và PER-PROJECT (harness/ commit vào repo,
# bảo vệ teammate). Global đủ cho máy dev cá nhân — chỉ WARN per-project khi cả 2 thiếu.
GLOBAL_HARNESS=false
[ -f "$HOME/.claude/harness/hooks/pre_tool_use.py" ] \
&& grep -q 'harness/hooks/pre_tool_use.py' "$HOME/.claude/settings.json" 2>/dev/null \
&& GLOBAL_HARNESS=true
echo "[harness] global=$GLOBAL_HARNESS project=$([ -d "$PROJECT_ROOT/harness" ] && echo yes || echo no)"
if [ -f "$PROJECT_ROOT/.llmwiki/.harness-stamp" ]; then
# Dự án layout DOT (cài bằng bootstrap v4): wiki ở .llmwiki/, engine ở GLOBAL — KHÔNG chép llmwiki/ trần, KHÔNG gọi đường per-project
# (install-harness.sh sẽ tự dừng rc 5). Thiếu/cũ thì cập nhật bằng: curl -fsSL …/harness/poc-vendor-neutral/bootstrap.sh | bash
echo "[orca-onboard] dự án dot-layout đã có overstack (.llmwiki/.harness-stamp) — bỏ qua bootstrap"
elif [ ! -d "$PROJECT_ROOT/llmwiki" ] || { [ "$GLOBAL_HARNESS" = "false" ] && [ ! -d "$PROJECT_ROOT/harness" ]; }; then
echo "[orca-onboard] bootstrapping llmwiki + harness..."
git clone https://github.com/rheinmir/setup.git /tmp/orca-llmwiki-bootstrap --depth 1 -b orca -q
[ ! -d "$PROJECT_ROOT/llmwiki" ] && cp -r /tmp/orca-llmwiki-bootstrap/llmwiki "$PROJECT_ROOT/llmwiki"
if [ "$GLOBAL_HARNESS" = "false" ] && [ ! -d "$PROJECT_ROOT/harness" ]; then
bash /tmp/orca-llmwiki-bootstrap/harness/scripts/install-harness.sh "$PROJECT_ROOT" \
&& echo "[orca-onboard] harness installed OK" \
|| echo "[WARN] harness install failed/denied — đường khuyên dùng: curl -fsSL https://raw.githubusercontent.com/Rheinmir/setup/orca/harness/poc-vendor-neutral/bootstrap.sh | bash (cài global + kéo orca-graph); hoặc 'install-harness.sh --global'"
fi
rm -rf /tmp/orca-llmwiki-bootstrap
echo "[orca-onboard] bootstrap done"
fi
# --- 5. Create dirs ---
mkdir -p $PROJECT_ROOT/.overstack/onboard/{intermediate,tmp}
mkdir -p $PROJECT_ROOT/llmwiki/wiki/draft/{cave,uiux,orca}
# --- 6. File count & availability check ---
git rev-parse HEAD 2>/dev/null > $PROJECT_ROOT/.overstack/onboard/tmp/commit.txt
git ls-files > $PROJECT_ROOT/.overstack/onboard/tmp/files.txt 2>/dev/null \
|| find $PROJECT_ROOT -type f \
! -path "*/.overstack/onboard/*" ! -path "*/llmwiki/*" ! -path "*/.git/*" \
> $PROJECT_ROOT/.overstack/onboard/tmp/files.txt
FILE_COUNT=$(wc -l < $PROJECT_ROOT/.overstack/onboard/tmp/files.txt | tr -d ' ')
# Probe agent availability
AGY_OK=$(agy --version 2>/dev/null && echo "✅ usable" || echo "❌ not found")
OC_OK=$(opencode --version 2>/dev/null && echo "✅ usable" || echo "❌ not found")
KIRO_OK=$(kiro-cli --version 2>/dev/null && echo "✅ usable" || echo "❌ not found")
echo "[pre-flight] $FILE_COUNT files | agy=$AGY_OK | opencode=$OC_OK"
# Parse statuses if in resume mode
parse_status() {
local keyword="$1"
awk '/## Agent Task Assignment/{p=1} p && /^## [^A]/{p=0} p' "$DRAFT_FILE" \
| grep "$keyword" | grep -oE 'pending|in-progress|done' | head -1
}
if [ "$RESUME_MODE" = true ]; then
PHASE1_STATUS=$(parse_status "Phase 1 —")
PHASE2_STATUS=$(parse_status "Phase 2 —")
PHASE3_STATUS=$(parse_status "Phase 3 —")
PHASE4_STATUS=$(parse_status "Phase 4 —")
echo "[Resume] P1=$PHASE1_STATUS P2=$PHASE2_STATUS P3=$PHASE3_STATUS P4=$PHASE4_STATUS"
fi
Phase 0.5 — ゲート
必須:まずドラフトファイルを作成してから、ユーザーに確認してください。この順序を逆にしてはいけません。
DATE=$(date +%d%m%y)
PROJECT_SLUG=$(basename "$PROJECT_ROOT" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
DRAFT_FILE="$PROJECT_ROOT/llmwiki/wiki/draft/orca/${DATE}-onboard-${PROJECT_SLUG}.md"
# Graph = distilled pipeline (no plugin): scan/history bash → batch opencode → layers/tour Claude
OC_AVAIL=$(opencode --version 2>/dev/null && echo "yes" || echo "no")
if [ "$OC_AVAIL" = "yes" ]; then
AGENT_GRAPH="distilled pipeline: bash + opencode (batch) + Claude (layers/tour)"
else
AGENT_GRAPH="distilled pipeline: bash + Claude main thread (opencode unavailable)"
fi
cat > "$DRAFT_FILE" << EOF
---
type: draft
title: ${DATE}-onboard-${PROJECT_SLUG}
status: proposed
tags: [orca-onboard, output-report]
timestamp: $(date +%Y-%m-%d)
---
# ${DATE}-onboard-${PROJECT_SLUG}
**Status:** proposed
## Agent CLI Availability
| Agent | Binary | Status |
|-------|--------|--------|
| Antigravity | \`agy\` | $AGY_OK |
| OpenCode | \`opencode\` | $OC_OK |
| Kiro | \`kiro-cli\` | $KIRO_OK |
## Agent Task Assignment
| Task | Agent | Model | Status |
|------|-------|-------|--------|
| Phase 1 — Graph generation ($FILE_COUNT files) | $AGENT_GRAPH | DeepSeek Flash v4 + Sonnet | pending |
| Phase 2 — Domain enrichment | Claude main thread | Sonnet | pending |
| Phase 3 — Wiki generation | opencode | DeepSeek Flash v4 | pending |
| Phase 4 — HTML docs | opencode | DeepSeek Flash v4 | pending |
## What
Onboard \`$PROJECT_ROOT\` — understand-anything graph, domain enrichment, wiki, HTML.
## Output
- \`.overstack/graph/knowledge-graph.json\` (tree-sitter + Louvain)
- \`.overstack/graph/ONBOARDING.md\` (~20k tokens distilled)
- \`.overstack/onboard/intermediate/domain-graph.json\`
- \`llmwiki/wiki/\` (index, concepts, entities, architecture, tours)
- \`llmwiki/html/onboarding-${PROJECT_SLUG}.html\`
- \`llmwiki/html/wiki-graph.html\` (vector quan hệ concept↔code — STEP C)
## Files
| File | Action |
|------|--------|
| \`.overstack/graph/knowledge-graph.json\` | created by Phase 1 pipeline |
| \`.overstack/graph/ONBOARDING.md\` | created by Phase 1 pipeline |
| \`.overstack/onboard/intermediate/domain-graph.json\` | created by Claude |
| \`llmwiki/wiki/index.md\` | created/modified |
| \`llmwiki/wiki/concepts/architecture.md\` | created |
| \`llmwiki/wiki/concepts/*.md\` | created |
| \`llmwiki/wiki/entities/*.md\` | created |
| \`llmwiki/wiki/concepts/onboarding-tour.md\` | created |
| \`llmwiki/html/onboarding-${PROJECT_SLUG}.html\` | created |
| \`llmwiki/html/wiki-graph.html\` | created by STEP C (vector) |
## Notes
- Invoked via: \`/orca-onboard\` skill
- Project root: \`$PROJECT_ROOT\`
- Files tracked: $FILE_COUNT
- Reasoning phases in Claude main thread — NOT dispatched to cheap models
- Mechanical phases: opencode + DeepSeek Flash v4
## Cost Estimate
| Phase | Agent | Est. tokens | Est. cost |
|-------|-------|-------------|-----------|
| Phase 1 (graph) | bash + opencode batches + Claude layers/tour | ~1.5M (DeepSeek) + ~50k (Sonnet) | ~\$0.50 |
| Phase 2 (domain) | Claude Sonnet | ~50k | ~\$0.50 |
| Phase 3 (wiki) | DeepSeek Flash | ~100k | ~\$0.02 |
| Phase 4 (HTML) | DeepSeek Flash | ~50k | ~\$0.01 |
## Origin
- **Draft:** \`wiki/draft/orca/${DATE}-onboard-${PROJECT_SLUG}.md\`
- **Commit:** _(filled by verify-before-commit)_
- **Date promoted:** _(filled by verify-before-commit)_
EOF
# Update wiki index + log
echo "| [${DATE}-onboard-${PROJECT_SLUG}](draft/orca/${DATE}-onboard-${PROJECT_SLUG}.md) | draft | $(date +%Y-%m-%d) |" >> "$PROJECT_ROOT/llmwiki/wiki/index.md"
echo "## $(date +%Y-%m-%d) — orca-onboard — onboard-${PROJECT_SLUG}" >> "$PROJECT_ROOT/llmwiki/wiki/log.md"
echo "DRAFT_FILE=$DRAFT_FILE"
# --- Terminal dispatch board (REQUIRED — must print in terminal BEFORE the gate question) ---
P1_NOTE="(distilled pipeline: 1.1-1.2 bash, 1.3 opencode batches, 1.4/1.6 python, 1.5 Claude)"
echo ""
echo "==================== ORCA-ONBOARD DISPATCH BOARD ===================="
echo " Project : $PROJECT_SLUG"
echo " Files : $FILE_COUNT"
echo " Draft : $DRAFT_FILE"
echo "----------------------------------------------------------------------"
printf " %-7s %-22s %-24s %-20s %s\n" "PHASE" "TASK" "AGENT" "MODEL" "EST.COST"
printf " %-7s %-22s %-24s %-20s %s\n" "1" "Graph generation" "bash+opencode+Claude" "DeepSeek+Sonnet" "~\$0.50"
printf " %-7s %-22s %-24s %-20s %s\n" "2" "Domain enrichment" "Claude main thread" "Sonnet" "~\$0.50"
printf " %-7s %-22s %-24s %-20s %s\n" "3" "Wiki generation" "opencode" "DeepSeek Flash v4" "~\$0.02"
printf " %-7s %-22s %-24s %-20s %s\n" "4" "HTML docs" "opencode" "DeepSeek Flash v4" "~\$0.01"
[ -n "$P1_NOTE" ] && echo " Phase 1 $P1_NOTE"
echo "======================================================================"
# --- Print propose file path + content (REQUIRED — user reviews this before approving) ---
echo ""
echo "PROPOSE FILE: $DRAFT_FILE"
echo "----------------------------------------------------------------------"
cat "$DRAFT_FILE"
⛔ 上記のディスパッチボードと提案ファイルの内容は、bash 経由で出力しなければなりません(ターミナルに表示)。チャット内だけ、またはドラフトファイル内だけで改めて記載しても不十分です。ユーザーはこのボードと提案に基づいてオーケストレーションの可否を判断します。ドラフトの Agent Task Assignment の行はボードと一致させてください(例:Phase 1 の対象ファイルが100件を超えるため opencode に振り分けた場合、ドラフトには agy ではなく opencode と記載します)。
続行する前に確認を求めてください。
Phase 1 — グラフ生成(蒸留版 Understand-Anything — プラグイン不要)
パイプライン: スキャン(bash)→ git 履歴(bash)→ バッチ分析(opencode + DeepSeek)→ マージ(python)→ レイヤー + ツアー(Claude のメインスレッド)→ 検証 + 保存(python + Claude)。Understand-Anything から手法を蒸留しています。プロンプトとスキーマはすべて以下に記載されています。/understand はディスパッチせず、プラグインもインストールしません。
必須の出力:
.overstack/graph/knowledge-graph.json(ノード、エッジ、レイヤー、ツアー).overstack/graph/ONBOARDING.md(蒸留版、約20kトークン).overstack/graph/meta.json
スキップ判定: RESUME_MODE=true + PHASE1_STATUS=done → Phase 2 に進みます。
判断表:
| グラフの有無 | フラグ | アクション |
|---|---|---|
| なし | (none) | パイプライン全体を実行 |
| あり | (none) | Phase 1 をスキップし、既存のグラフを使用 |
| あり | --update | git diff <meta.gitCommitHash>..HEAD --name-only のファイルのみを再分析し、既存のグラフにマージ |
| あり | --full | .overstack/graph/ を削除し、パイプライン全体を実行 |
1.1 SCAN(bash — LLM 不使用)
mkdir -p "$PROJECT_ROOT/.overstack/graph" "$PROJECT_ROOT/.overstack/onboard/tmp"
git -C "$PROJECT_ROOT" ls-files > "$PROJECT_ROOT/.overstack/onboard/tmp/files.txt"
# Loại file nhị phân/lock/vendor; phân loại theo extension: code/config/docs/infra/data/script
# Đọc context: README (3000 chars đầu), manifest (package.json/pyproject.toml/Cargo.toml/go.mod), dir tree 2 cấp
# Detect entry point: src/index.ts, main.py, app.py, main.go, src/main.rs, cmd/*/main.go, manage.py, __main__.py...
1.2 GIT HISTORY(bash — LLM 不使用)
git 履歴のシグナルでグラフを充実させます。これは静的解析では得られない情報です。
# Churn — file nóng (hay sửa nhất, 365 ngày)
git -C "$PROJECT_ROOT" log --since="365 days ago" --name-only --pretty=format: \
| grep -v '^$' | sort | uniq -c | sort -rn | head -40 > "$PROJECT_ROOT/.overstack/onboard/tmp/churn.txt"
# Recent — file vừa đổi (30 ngày)
git -C "$PROJECT_ROOT" log --since="30 days ago" --name-only --pretty=format: | grep -v '^$' | sort -u \
> "$PROJECT_ROOT/.overstack/onboard/tmp/recent.txt"
# Commit subjects gần nhất — chủ đề đang phát triển
git -C "$PROJECT_ROOT" log --since="90 days ago" --pretty=format:'%s' | head -50 \
> "$PROJECT_ROOT/.overstack/onboard/tmp/recent-subjects.txt"
# Co-change — python đọc `git log --name-only` theo commit, đếm cặp file đổi cùng nhau, ngưỡng ≥3
適用方法:churn 上位のファイルにはノードタグ hot を付与し、recent.txt 内のファイルにはタグ recent を付与します。3件以上の同時変更ペアにはエッジ related(weight 0.5)を追加します。ツアーと ONBOARDING では hot ファイルを優先し、recent-subjects は「What's being worked on」の項目に使用します。
1.3 ANALYZE — 主方式:静的解析(トークン消費なし)・opencode は情報強化のみ
デフォルトでは python による静的解析を使用します(run 120626-zca-bridge の教訓です。低コストで決定的な結果が得られます)。
正規表現で import/export ... from と require() を検出 → 相対パスを解決 → エッジ imports を作成します。
test/**.test.ts → tested_by。summary = ファイル冒頭のコメント/export 一覧/md の見出し。
拡張子に基づいて type(file/config/document)を判定します。Imports は機械的な処理であり、LLM の精度が正規表現を上回ることはありません。
複雑なファイルについて、より意味的に豊かな summary が必要な場合に限り、opencode をディスパッチします(任意の情報強化)。
ファイル一覧を約25ファイルずつのバッチに分割します(関連ファイルは同じバッチにまとめます:Dockerfile+compose、migrations、CI configs、docs)。各バッチをディスパッチします。
opencode run "$BATCH_SPEC" --model opencode/deepseek-v4-flash-free < /dev/null
# ⚠ KHÔNG thêm --dangerously-skip-permissions: Claude Code auto-mode classifier sẽ DENY lệnh dispatch.
# opencode treo chờ permission / bị chặn → dùng STATIC PARSE fallback bên dưới (ưu tiên mặc định).
BATCH_SPEC(必要なコンテキストをすべて埋め込みます。DeepSeek は割り当てられた一覧以外を自分で読み込まないためです):
プロジェクト (、言語:)に含まれる以下のファイルを分析してください。各ファイルについて、GraphNode
{id, type, name, filePath, summary (1-2 câu), tags[]}と、ファイル内容から確認できる imports/calls/configures/documents を表す GraphEdges{source, target, type, weight}を生成してください。一覧にあるファイルをすべて読み込んでください。有効な JSON{"nodes":[...], "edges":[...]}のみを.overstack/onboard/tmp/batch-<i>.jsonに書き込んでください。ID の規則:file:<relpath>、config:<relpath>、document:<relpath>。ファイル:<行数付きの一覧>
並列実行は最大5バッチです。バッチが失敗した場合は1回再試行し、それでも失敗した場合はスキップして PHASE_WARNINGS に記録します(部分的なグラフでも、グラフがないよりは有用です)。opencode が利用できない場合は、Claude のメインスレッドが自分でバッチを分析します。
1.4 MERGE + NORMALIZE(python インライン — LLM 不使用)
Claude は .overstack/onboard/tmp/merge.py スクリプトを作成します(Understand-Anything の merge-batch-graphs.py から蒸留したロジック)。すべての batch-*.json を読み込み → ノード/エッジを統合 → ID の prefix を正規化(二重 prefix を削除し、不足している prefix を追加)→ id ごとにノードを重複排除(最後のものを保持)、(source,target,type) ごとにエッジを重複排除 → 孤立したエッジを破棄(stderr に記録)→ co-change(1.2)から related エッジを追加 → assembled-graph.json に書き込みます。
1.5 レイヤー + ツアー(Claude メインスレッド — 推論、ディスパッチなし)
assembled-graph + ディレクトリツリー + README から:
- レイヤー:
[{id: "layer:<kebab>", name, description, nodeIds[]}]— 各ファイルレベルのノードは必ず1つのレイヤーに属します。ディレクトリ構造が最も強い根拠になります。 - ツアー: 5~15ステップの
[{order, title, description, nodeIds[]}]— ステップ1は必ずプロジェクトの概要(README)とし、エントリーポイントに沿って、hotファイルを優先します。README が語るのと同じストーリーを、実際のコードを通して伝えます。
1.6 検証 + 保存(python + Claude)
決定論的に検証します(スクリプト):ノード ID の重複がないこと、エッジの参照先が存在しない状態がないこと、すべてのファイルノードがちょうど1つのレイヤーに属していること、ツアーの nodeIds が存在すること、孤立ノードの数を確認します。自動修正できるものは修正し(参照先のないエッジを削除、デフォルト値を補完)、それ以外は警告として記録します。不完全なグラフでも保存します。
書き込むファイル:
knowledge-graph.json:{version, project: {name, languages, frameworks, description, analyzedAt, gitCommitHash}, nodes, edges, layers, tour}meta.json:{lastAnalyzedAt, gitCommitHash, analyzedFiles}ONBOARDING.md(Claude による要約、約20kトークン):概要、レイヤー + 説明、主要なフロー、ホットファイル + その理由(変更頻度)、「現在取り組んでいること」(recent-subjects)、ツアーのナラティブ、統計。
最後に:batch-*.json を削除し、サマリー(解析したファイル数、種類別のノード/エッジ数、レイヤー数、ツアーのステップ数、警告)を報告します。
スキーマ(Understand-Anything から要約)
- ノードタイプ:
file, function, class, module, concept, config, document, service, table, endpoint, pipeline, schema, resource— ID:<type>:<relpath>[:<name>] - 主なエッジタイプ: imports, exports, contains, inherits, implements, calls, reads_from, writes_to, depends_on, tested_by, configures, related, documents, deploys, triggers, routes, defines_schema
- 重み: contains 1.0 · inherits/implements 0.9 · calls/exports 0.8 · imports 0.7 · depends_on/configures 0.6 · その他 0.5
# Gate cuối Phase 1
[ ! -f "$PROJECT_ROOT/.overstack/graph/knowledge-graph.json" ] \
&& echo "❌ Phase 1 FAIL: knowledge-graph.json missing" && exit 1
[ ! -f "$PROJECT_ROOT/.overstack/graph/ONBOARDING.md" ] \
&& echo "❌ Phase 1 FAIL: ONBOARDING.md missing" && exit 1
echo "✅ Phase 1 done"
# update_phase_status "Phase 1 —" "done"
1.7 CODE-GRAPH MCP インデックス(任意 — code-graph サーバーが mcpServers にある場合のみ)
上記の要約グラフを補完する、行単位で正確なコード関係のクエリ層です。search_symbols、get_callers/callees により、影響を即座に確認できます。code-graph サーバー(~/.claude.json → mcpServers)は、リポジトリごとに <repo>/.graph-agent/index.db に SQLite DB を1つ作成します。
実行するタイミング: プロジェクトに実際のコードを含むサブモジュール/リポジトリ(Go/TS/Py など)があり、code-graph が本当に使用可能な場合に限ります。python3 harness/scripts/dep-health.py --json で確認し、status == "ok" を必須とします。~/.claude.json に宣言されているかどうかだけで判断してはいけません。設定に宣言されていることと、サーバーが稼働していることは別です。0バイトの DB、symbols テーブルのない DB、停止したサーバーも、依然として「宣言済み」と見なされます(2026-07-20 の教訓 — code-graph が何週間も壊れていたのに、すべてのセッションで利用を強いられていました)。degraded/absent の場合はこのステップをスキップします。
# 1. Index từng repo code (auto-detect root từ .git/go.mod/package.json).
# Gọi MCP tool reindex_repo(<abs path repo>, force=true) cho MỖI repo code.
# Lưu ý: code có thể nằm ở SUBDIR của submodule (vd <sub>/<svc>/go.mod chứ không phải <sub>/).
# → trỏ vào thư mục chứa go.mod/package.json, không phải submodule root rỗng.
# 2. reindex_repo tự thêm repo vào registry ~/.graph-agent/repos.txt
# → server --watch re-watch sau restart (durability).
# 3. Verify: get_stats() phải thấy symbols thật (>0), không phải stub.
echo "[1.7] code-graph: gọi reindex_repo cho mỗi repo code có manifest"
永続性ハーネス: SessionStart フック code_graph_keeper.py(install-harness.sh と一緒にインストール)は、レジストリから登録が外れたリポジトリを自動で再登録し、未インデックスのリポジトリに警告を出します。フェイルオープンで、プロジェクトが code-graph を使用しない場合は何もしません。条件となるのは、.graph-agent/index.db が使用可能であること(開けること + symbols/files テーブルがあること)であり、ファイルがあるだけでは不十分です。空の DB によって keeper がレジストリに誤って記録し、「未インデックス」の警告も抑止されてしまったことがあります。編集のたびに再インデックスしてはいけません(watcher がすでに処理し、2秒間デバウンスします)。その後、チームが使い方を把握できるよう、wiki のコンセプトページ concepts/code-graph-nav.md(ツールの使い方 + caller trace の例)を1つ書きます。
以降の鮮度維持は自動です。ファイルを編集すると、watcher が約2秒で再インデックスします。新しいクローンを作成した場合や、サーバー停止中に大量の変更を行った場合を除き、手動での再インデックスは不要です。
フェーズ 2 — ドメインの拡充
エージェント: Claude main thread(ディスパッチなし) | モデル: Sonnet
最初に読む(以下の順に、何かを書く前に):
.overstack/graph/ONBOARDING.md— 全文を読む(約 20k トークン).overstack/graph/knowledge-graph.json—layers配列とentry-pointタグ付きノードのみを読む(⛔ ファイル全体は読まない — コンテキストがあふれます)UPDATE_MODE=trueの場合:既存の.overstack/onboard/intermediate/domain-graph.jsonを読む(上書きせず、マージする)
実行事項:
0. フローを選ぶ前に、実際のサーフェスを確認(スキル surface-coverage、GH#191 — 18 個のフローで、62 ページと 37 モジュールからなるアプリ全体をカバーしたかのように報告していた事例があります):
python3 "$FDK_TOOLS/surface-coverage.py" scan "$PROJECT_ROOT" [--modules '<API モジュールのディレクトリ>/*'] --out .overstack/onboard/intermediate/surface.json
FDK_TOOLS=$([ -f fdk/tools/surface-coverage.py ] && echo fdk/tools || echo "$HOME/.claude/harness/fdk/tools") を指定します(フレームワークリポジトリではリポジトリ内のものを、顧客のマシンではグローバルエンジンを使用)。ファイルベースではないフレームワークの場合は、ルートを列挙するスクリプトを書き、同じファイルに統合します。
- エントリーポイントから、HTTP エンドポイント/CLI コマンド/イベント/cron job を特定します —
surface.jsonの各項目をフローでカバーするか、理由を示して除外する必要があります - リバースエンジニアリングします:エントリーポイント → フロー(プロセス)→ ステップ(
file:lineにあるアクション) domain → flow → stepの階層を構築します.overstack/onboard/intermediate/domain-graph.jsonと、カバレッジ台帳.overstack/onboard/intermediate/coverage.json({"commit", "items": {"page:/x": {"by": ["flow:…"]} | {"exclude": "理由"}}})を書き込みます- ゲート:
python3 "$FDK_TOOLS/surface-coverage.py" check surface.json coverage.json --flows domain-graph.json --root "$PROJECT_ROOT"— 終了コード 1(未カバー項目、誤ったフロー ID、誤ったfile:line)の場合は、次のコーディングパスで修正します。最大 3 回までとし、それでも失敗する場合、フェーズ 2 は partial です。最終レポート(W09)にはN/M 個のサーフェス項目をカバー、K 個を除外の行をそのまま出力し、未カバー項目を一覧表示します — カバーできたかのようにフロー数だけを報告してはいけません。
ドメイングラフのスキーマ:
{
"domains": [
{
"id": "domain:order-management",
"name": "Order Management",
"flows": [
{
"id": "flow:create-order",
"name": "Create Order",
"steps": [
{ "order": 0.1, "id": "step:validate-input", "file": "src/orders/validator.ts", "line": 42 },
{ "order": 0.2, "id": "step:check-inventory", "file": "src/inventory/checker.ts", "line": 15 }
]
}
]
}
]
}
出力: .overstack/onboard/intermediate/domain-graph.json
スキップ条件: RESUME_MODE=true + PHASE2_STATUS=done → フェーズ 3 に進みます。
if [ "$RESUME_MODE" != "true" ] || [ "$PHASE2_STATUS" != "done" ]; then
update_phase_status "Phase 2 —" "in-progress"
# Claude main thread — no dispatch
if [ "$UPDATE_MODE" = "true" ] && [ -n "$CHANGED_FILES" ]; then
echo "[Phase 2] Update mode: re-enrich domain steps for changed files only"
# Read existing domain-graph.json
# Filter steps with filePath in CHANGED_FILES
# Re-analyze those steps from ONBOARDING.md
# Merge back into domain-graph.json (keep unchanged steps)
else
echo "[Phase 2] Full domain enrichment from ONBOARDING.md"
# Read ONBOARDING.md + layers from knowledge-graph.json, write new domain-graph.json
fi
update_phase_status "Phase 2 —" "done"
fi
フェーズ 3 — Wiki の生成
エージェント: opencode | モデル: opencode/deepseek-v4-flash-free
最初に読む(ディスパッチ前に SPEC に挿入 — DeepSeek は注入しない限りファイルを読みません):
.overstack/graph/ONBOARDING.md— 全文を読む.overstack/onboard/intermediate/domain-graph.json— 全文を読むUPDATE_MODE=trueの場合:llmwiki/wiki/を検索してCHANGED_FILESへの参照を調べ、古くなったページを特定します
- ⛔
.overstack/graph/knowledge-graph.jsonは読まないでください — 大きすぎてコンテキストがあふれます
実行事項: 抽出済みの内容から Wiki テンプレートを埋めます。推論は行わず、機械的にテンプレートを埋めます。
出力構造:
llmwiki/wiki/
├── index.md
├── concepts/ ← architecture.md, message-sync/flows, onboarding-tour.md (R5: KHÔNG tạo folder architecture/ hay tours/ — validator folder_structure chặn)
└── entities/ ← domain entities + project-structure.md
# Mọi trang PHẢI có '## Origin' (R2) và row trong index.md (R3)
スキップ条件: RESUME_MODE=true + PHASE3_STATUS=done → フェーズ 4 に進みます。
if [ "$RESUME_MODE" != "true" ] || [ "$PHASE3_STATUS" != "done" ]; then
update_phase_status "Phase 3 —" "in-progress"
if [ "$UPDATE_MODE" = "true" ] && [ -n "$CHANGED_FILES" ]; then
STALE_PAGES=$(grep -rl "$CHANGED_FILES" "$PROJECT_ROOT/llmwiki/wiki/" 2>/dev/null | tr '\n' ' ')
if [ -n "$STALE_PAGES" ]; then
echo "[Phase 3] Stale wiki pages: $STALE_PAGES"
SPEC="Update these wiki pages based on changes in ONBOARDING.md: $STALE_PAGES
Changed source files: $CHANGED_FILES
Do NOT regenerate unchanged pages. Preserve existing content in unchanged pages."
else
echo "[Phase 3] No stale wiki pages — skipping"
update_phase_status "Phase 3 —" "done"
fi
else
SPEC="Generate wiki pages from .overstack/graph/ONBOARDING.md and .overstack/onboard/intermediate/domain-graph.json.
Create: llmwiki/wiki/index.md, llmwiki/wiki/concepts/*.md (architecture.md + flow pages + onboarding-tour.md),
llmwiki/wiki/entities/*.md (domain entities + project-structure.md).
R5: chỉ được ghi vào concepts/ hoặc entities/. R2: mọi trang có '## Origin'. R3: cập nhật index.md.
Use wikilink format [[page-name]]. Do NOT read knowledge-graph.json directly."
fi
opencode run "$SPEC" --model opencode/deepseek-v4-flash-free < /dev/null \
|| echo "[WARN] opencode unavailable — Claude main thread fallback for wiki"
update_phase_status "Phase 3 —" "done"
fi
Phase 4 — HTML ドキュメント(skeleton v2 + JSON island)
エージェント: JSON の組み立て = opencode(機械的)/Claude をフォールバックとして使用 · スケルトンへの入力 = python(LLM 不使用)
動作の仕組み(旧版とは異なります — 内容の粗さと UX の断絶を防止): モデルに生の HTML を生成させません
(DeepSeek が独自に CSS/JS を作るため、「gương」が失われ、クリックしても反応せず、出力が 173〜816 行と不安定になります)。
代わりに、モデルはスキーマに従った1 つの JSON オブジェクトのみを出力します。UI は、設計システム /docs-site-macos を適用済みの
assets/docs-site-skeleton.html にある固定の skeleton v2 によってレンダリングされます。
スケルトン = 固定ナビゲーション(Overview/What & How/Architecture/Guided Tour/Modules/Docker。JSON に what と how の両方がない場合は What & How を非表示)+ 固定サイドバー
- 折りたたみ + スクロールスパイ + ツアーのマスター・ディテール + ドラッグ可能な図。モノリポジトリの場合、Modules/Docker は自動的に非表示になります。 子コンテンツ(レイヤー/ツアー/モジュール/Docker)は JSON からデータ駆動で生成されます。
先にお読みください(情報量の多いソース — SPEC に注入します。DeepSeek はファイルを自動で読み込みません):
.overstack/graph/ONBOARDING.md— 全文(概要、重要なファイル、フロー、ツアーの説明).overstack/onboard/intermediate/domain-graph.json— domain→flow→step(ツアー + ライフサイクル)knowledge-graph.jsonはlayers+tour+ ノードのエントリーポイントのみ(⛔ 全文は禁止 — 容量超過) ⛔ 主な情報源として、内容の薄い wiki md を使用しないでください(旧版が内容不足だった原因です)。
スキップ条件: RESUME_MODE=true + PHASE4_STATUS=done → スキップ。
if [ "$RESUME_MODE" != "true" ] || [ "$PHASE4_STATUS" != "done" ]; then
update_phase_status "Phase 4 —" "in-progress"
# --- locate skeleton v2 ---
SKELETON=$(ls ~/.agents/skills/orca-onboard/assets/docs-site-skeleton.html \
~/.claude/skills/orca-onboard/assets/docs-site-skeleton.html \
"$PROJECT_ROOT/skills/orca-onboard/assets/docs-site-skeleton.html" 2>/dev/null | head -1)
[ -z "$SKELETON" ] && echo "❌ Phase 4: skeleton v2 not found" && exit 1
# --- detect Docker (multi-service → tab Docker; mono → docker:null, Modules:[]) ---
DKFILE=$(ls "$PROJECT_ROOT"/docker-compose.y*ml "$PROJECT_ROOT"/compose.y*ml 2>/dev/null | head -1)
N_SVC=0; [ -n "$DKFILE" ] && N_SVC=$(grep -cE '^ [a-zA-Z0-9_-]+:' "$DKFILE" 2>/dev/null || echo 0)
echo "[Phase 4] skeleton=$SKELETON | compose=$DKFILE | services=$N_SVC"
# --- STEP A: assemble ONBOARD_JSON (model emit JSON ONLY → file) ---
JSON_OUT="$PROJECT_ROOT/.overstack/onboard/tmp/onboard.json"
SPEC="Đọc .overstack/graph/ONBOARDING.md + .overstack/onboard/intermediate/domain-graph.json.
Phát ra MỘT object JSON (KHÔNG markdown, KHÔNG giải thích) theo ĐÚNG schema trong header của
$SKELETON, ghi vào $JSON_OUT. Yêu cầu chất lượng:
- project: name/subtitle/about thật; stack[] + versions[] từ manifest; stats[] (files, services, layers, tour steps).
- project.what = 2–4 câu LỜI THƯỜNG: dự án làm gì, cho ai, giải quyết vấn đề gì (không thuật ngữ nội bộ); project.how[] = 3–7 bước {t,d} kể luồng chạy đầu→cuối bằng lời người — hiện thành mục What & How NGAY SAU Overview.
- architecture.layers[] = layers thật; architecture.diagram.nodes[] (toạ độ trong ~760×rộng, rect≥70×30) + edges[] theo luồng.
- tour[] 5–15 bước, MỖI bước GIÀU: role(1-2 câu), file+line THẬT, in[]/out[], hot(churn), narr — KHÔNG 1–2 dòng.
- modules[] = mỗi container/image (đọc $DKFILE): name,img,meta(port/env/volume),life[[read|proc|write,desc]],arch. Repo mono ($N_SVC≤1) → modules:[].
- docker = {strategy, cmd[[text,c|p|]], table[[svc,img,cmd/port,deps]], order[]} nếu có compose; mono → docker:null."
opencode run "$SPEC" --model opencode/deepseek-v4-flash-free < /dev/null 2>/dev/null \
|| echo "[Phase 4] opencode unavailable — Claude main thread tự assemble $JSON_OUT theo schema skeleton"
# Nếu opencode treo/trống → Claude main thread đọc 2 nguồn trên, tự viết $JSON_OUT (reasoning OK ở đây).
# --- STEP B: fill skeleton (python, no LLM) — thay {{TITLE}} + {{ONBOARD_JSON}} ---
OUT="$PROJECT_ROOT/llmwiki/html/onboarding-${PROJECT_SLUG}.html"
mkdir -p "$PROJECT_ROOT/llmwiki/html"
python3 - "$SKELETON" "$JSON_OUT" "$OUT" <<'PY'
import json,sys,html
sk=open(sys.argv[1]).read(); data=json.load(open(sys.argv[2]))
name=(data.get("project") or {}).get("name","Project")
out=sk.replace("{{TITLE}}",html.escape(name)).replace("{{ONBOARD_JSON}}",json.dumps(data,ensure_ascii=False))
assert "{{ONBOARD_JSON}}" not in out and "{{TITLE}}" not in out, "token chưa thay hết"
open(sys.argv[3],"w").write(out); print("✅ filled →",sys.argv[3],len(out),"bytes")
PY
ls "$OUT" && echo "✅ Phase 4 done" || echo "❌ Phase 4 FAIL: HTML not found"
update_phase_status "Phase 4 —" "done"
fi
フォールバック: opencode が停止/ハングした場合 → Claude のメインスレッドが
ONBOARDING.md+domain-graph.jsonを読み取り、スキーマに従って$JSON_OUTを作成し(データの組み立てなので Claude で問題ありません)、 STEP B を実行します。生の HTML を自分で書くことは絶対にせず、必ず skeleton v2 を使用してください。
STEP C — ベクター wiki-graph.html を描画する(Phase 3 で生成した wiki に、ここで初めて描画用の概念がそろいます):
オンボーディングで wiki は生成されますが、関係性のベクターは自動で描画されません。コードのみのプロジェクトでオンボーディングが完了した時点でベクターもそろうよう、ここでただちに描画します
(ボトルネックの解消:build-wiki-graph.py は llmwiki/wiki/*.md + コードを読み込みますが、コードを直接読み込んで概念を生成するわけではありません)。失敗しても処理を続行し、オンボーディングをブロックしません。
# engine: repo-local → global (cùng thứ tự hook Stop resolve)
WG=$(ls "$PROJECT_ROOT/fdk/tools/build-wiki-graph.py" \
"$HOME/.claude/harness/fdk/tools/build-wiki-graph.py" 2>/dev/null | head -1)
if [ -n "$WG" ] && [ -d "$PROJECT_ROOT/llmwiki/wiki" ]; then
ALSO=""; [ -d "$PROJECT_ROOT/fdk/wiki" ] && ALSO="--also fdk/wiki"
( cd "$PROJECT_ROOT" && python3 "$WG" llmwiki/wiki $ALSO --code-root . ) \
&& echo "✅ vector: llmwiki/html/wiki-graph.html (concept↔code)" \
|| echo "⚠️ wiki-graph vẽ lỗi — không chặn onboard (Stop hook sẽ vẽ khi wiki/code đổi)"
else
echo "⚠️ bỏ vẽ vector — thiếu engine build-wiki-graph.py (cài harness global) hoặc chưa có llmwiki/wiki"
fi
完了後:
lsof -ti :8765 >/dev/null 2>&1 || nohup npx serve -p 8765 > /tmp/serve.log 2>&1 &
echo "→ http://localhost:8765/llmwiki/html/onboarding-${PROJECT_SLUG}.html"
ルール
- 実行前に読む — 各フェーズでは、処理を開始する前に
READ FIRSTブロックの入力をすべて読みます。ファイルにすでに記載されていることをユーザーに尋ねないでください。 - Phase 1 の後は
knowledge-graph.json全文を読み込まない — 代わりにONBOARDING.mdを使用します。 - 実在するファイルパスのみを使用し、捏造しないでください。
- ドメイングラフでは、実在するファイルと行番号のみ参照し、コードと照合してください。
- Wiki:wikilink 形式
[[page-name]] - ツアー:5〜15 ステップで、プロジェクトの概要から始めます。
- 推論を要するタスク(ドメイン、アーキテクチャ)は Claude のメインスレッドのみで行います。
エラー
- Phase 1 のバッチ失敗(opencode)→ 1 回再試行し、再度失敗したら Claude のメインスレッドで該当バッチを分析し、PHASE_WARNINGS に記録します。
- Phase 1 の失敗(グラフなし)→ batch-*.json が存在するか確認します。マージスクリプトのエラー → stderr を読み、修正して再実行します。
- Phase 2 の domain が空 → HTTP/CLI/イベントのエントリーポイントが見つかりません。空の domains 配列を記述します。
- Phase 3 の失敗 → opencode のモデル設定を確認します。フォールバックとして Claude のメインスレッドを使用します。
- Phase 4 の失敗 → フォールバック:Claude で docs-site-macos スキルを直接呼び出します。
出力レポート
すべてのフェーズ完了後、提案のドラフトを wiki に書き込みます。
1. ファイル名: DDMMYY-<ten>.md — 今日の日付 + kebab-case で要約した単語を 2〜4 個
2. llmwiki/wiki/draft/orca/DDMMYY-<ten>.md に書き込みます:
---
type: draft
title: DDMMYY-<ten>
status: proposed
tags: [orca-onboard, output-report]
timestamp: YYYY-MM-DD
---
# DDMMYY-<ten>
**Status:** proposed
## Agent Task Assignment
| Task | Agent | Model | Status |
|------|-------|-------|--------|
| Phase 1 — Graph generation | agy /understand | Claude (agy) | done |
| Phase 2 — Domain enrichment | Claude main | Sonnet | done |
| Phase 3 — Wiki generation | opencode | DeepSeek Flash v4 | done |
| Phase 4 — HTML docs | opencode | DeepSeek Flash v4 | done |
## What
<One sentence>
## Output
<Key artefacts>
## Files
| File | Action |
|------|--------|
| `.overstack/graph/knowledge-graph.json` | created |
| `llmwiki/wiki/index.md` | created/modified |
| `llmwiki/html/onboarding-<slug>.html` | created |
## Notes
- Invoked via: `/orca-onboard` skill
## Origin
- **Draft:** `wiki/draft/orca/DDMMYY-<ten>.md`
- **Commit:** _(filled by verify-before-commit)_
- **Date promoted:** _(filled by verify-before-commit)_
3. Wiki のインデックスとログを更新します:
llmwiki/wiki/index.md— 次の行を追加:| [DDMMYY-<ten>](draft/orca/DDMMYY-<ten>.md) | draft | YYYY-MM-DD |llmwiki/wiki/log.md— 次の行を追加:## YYYY-MM-DD — orca-onboard — <ten>
4. ステータスを更新して同期プッシュ — 必須:
- ドラフトファイルの Status 列を更新し、実際の実行状況を反映します。
rheinmir/setupのブランチorcaをクローンし、更新済みの SKILL.md をコピーしてプッシュします:git clone [email protected]:rheinmir/setup.git /tmp/rheinmir-setup-sync -b orca --depth 1 cp ~/.agents/skills/orca-onboard/SKILL.md /tmp/rheinmir-setup-sync/skills/orca-onboard/SKILL.md cd /tmp/rheinmir-setup-sync git add . git commit -m "skill: orca-onboard — wrap understand-anything, DeepSeek mechanical dispatch" git push origin orca rm -rf /tmp/rheinmir-setup-sync
スキルが成果物も判断も一切生成しなかった場合に限り、出力レポートを省略します。
出力レポート
すべてのフェーズが完了したら、提案ドラフトを wiki に書き込みます。
1. ファイル名: DDMMYY-<ten>.md — 今日の日付 + 2〜4 個の kebab-case の要約語
2. llmwiki/wiki/draft/orca/DDMMYY-<ten>.md に書き込みます:
---
type: draft
status: proposed
tags: [orca-onboard, output-report]
proposed: YYYY-MM-DD
---
# DDMMYY-<ten>
## Agent Task Assignment
| Task | Agent | Model | Status |
|------|-------|-------|--------|
| Phase 1 — Graph generation | agy /understand | Claude (agy) | done |
| Phase 2 — Domain enrichment | Claude main | Sonnet | done |
| Phase 3 — Wiki generation | opencode | DeepSeek Flash v4 | done |
| Phase 4 — HTML docs | opencode | DeepSeek Flash v4 | done |
## What
<One sentence>
## Output
<Key artefacts>
## Files
| File | Action |
|------|--------|
| `.overstack/graph/knowledge-graph.json` | created |
| `llmwiki/wiki/index.md` | created/modified |
| `llmwiki/html/onboarding-<slug>.html` | created |
## Notes
- Invoked via: `/orca-onboard` skill
## Origin
- **Draft:** `wiki/draft/orca/DDMMYY-<ten>.md`
- **Commit:** _(filled by verify-before-commit)_
- **Date promoted:** _(filled by verify-before-commit)_
3. wiki のインデックスとログを更新します:
llmwiki/wiki/index.md— 次を追記します:| [DDMMYY-<ten>](draft/orca/DDMMYY-<ten>.md) | draft | YYYY-MM-DD |llmwiki/wiki/log.md— 次を追記します:## YYYY-MM-DD — orca-onboard — <ten>
4. ステータスを更新して同期プッシュします — 必須:
- ドラフトファイルの Status 列を、実際の実行状況に合わせて更新します
rheinmir/setupのブランチorcaをクローンし、更新した SKILL.md をコピーしてプッシュします:git clone [email protected]:rheinmir/setup.git /tmp/rheinmir-setup-sync -b orca --depth 1 cp ~/.agents/skills/orca-onboard/SKILL.md /tmp/rheinmir-setup-sync/skills/orca-onboard/SKILL.md cd /tmp/rheinmir-setup-sync git add . git commit -m "skill: orca-onboard — wrap understand-anything, DeepSeek mechanical dispatch" git push origin orca rm -rf /tmp/rheinmir-setup-sync
スキルによって成果物も判断事項も生成されなかった場合のみ、出力レポートをスキップします。
ブランチ
| ID | 種類 | 条件 | 動作 | スキップ/失敗 | 再開位置 |
|---|---|---|---|---|---|
| B01 | ユーザー任意 | @<draft> (RESUME_MODE) | ドラフトから各フェーズのステータスを読み取り、フェーズが done ならスキップします | ドラフトに Project root: がない → root が空 → exit 1 | 最初の未完了フェーズ |
| B02 | ユーザー任意 | --update + graph が存在 | 変更されたファイルのみ再分析し、既存の graph/domain/wiki にマージします | graph/meta.json が存在しない → exit 1;changedFiles が空 → 全体を再構築 | W03 |
| B03 | ユーザー任意 | --full | .overstack/graph/ を削除し、パイプライン全体を実行します | — | W03 |
| B04 | 条件付き必須 | graph が存在し、フラグなし | Phase 1 をスキップし、既存の graph を使います | — | W06 |
| B05 | 機能に応じて任意 | code-graph dep-health.py --json が status == "ok" を報告 | 1.7 CODE-GRAPH MCP INDEX:各コードリポジトリで reindex_repo を実行し、get_stats() >0 を確認して、concepts/code-graph-nav.md に記録します | degraded/absent → スキップ | W06 |
| B06 | リカバリー | 1.3、Phase 3、Phase 4 STEP A で opencode が利用できない/停止 | Claude のメインスレッドが自ら実行します(バッチ分析/wiki/JSON の組み立て)。Phase 4 は引き続きスケルトンを経由します | Phase 4 が完全に失敗 → docs-site-macos を直接呼び出します | そのフェーズの次のステップ |
| B07 | ユーザー任意 | --skip-wiki | Phase 3 をスキップします | — | W08 |
| B08 | 条件付き必須 | モノリポジトリ(N_SVC ≤ 1) | modules:[]、docker:null → スケルトンが Modules/Docker タブを自動的に非表示にします | マルチサービス → Docker タブあり | W08 |
検証と停止
スクリプトによる決定論的なチェック:Phase 1 の最終ゲート(必須の 2 ファイル)、graph 1.6 の検証(ID の重複なし、dangling edge なし、各ファイルノードの layer は 1 つのみ、tour nodeIds が存在)、STEP B ですべての {{TITLE}}/{{ONBOARD_JSON}} が置換されたことのアサート、Phase 4 の最後に ls "$OUT"。レビューが必要な項目:layers/tour、domain graph(実際の file:line と照合)、wiki の品質。ドラフト内の 4 フェーズが done になったら停止します。バッチの再試行は最大 1 回です。
例
- 成功例: 180 ファイルのリポジトリで opencode がある場合に
/orca-onboard ~/code/zca-bridgeを実行 → ターミナルにドラフト + ディスパッチボードを表示 → ユーザーが「ok」 → 180 個のノード + 7 個の layer + 9 ステップの tour を含む graph → 3 つの domain を含むdomain-graph.json→ wiki の concepts/entities →llmwiki/html/onboarding-zca-bridge.html+wiki-graph.html。ドラフトの 4 フェーズはdone。 - 境界/失敗例: 一度もオンボーディングしていないリポジトリで
/orca-onboard --updateを実行 → Phase 0 で「❌ --update requires existing graph. Run without --update first.」を表示して exit 1。ドラフトは作成されません。 - 境界例: Phase 4 STEP A で opencode が停止 → Claude がスケルトンのスキーマに従って
onboard.jsonを自分で記述し、STEP B を実行します。生の HTML は記述しません。