SuperAPI AI Directory

orca-onboard

Coding & development

View repository

Updated 10-15 22:10

About this skill

orca-onboard

🧭 Dispatch backend — choose a cheap agent/model, run multiple workers in parallel, opencode/orchestration syntax → see orca-dispatch-reference (single source of truth, don't duplicate syntax here).

Onboard codebase via distilled understand-anything pipeline (graph + git history, no plugin), then domain enrichment + wiki + HTML.

WHAT

Purpose and context

  • Purpose: onboard any codebase into usable knowledge: knowledge graph (scan + git history + batch analyze + layers/tour, no plugin), domain graph (domain → flow → step), wiki llmwiki/wiki/ and HTML docs pages — the reasoning part in the Claude main thread, the mechanical part dispatched to opencode + DeepSeek Flash v4.
  • Trigger (when to use): "onboard codebase", "analyze codebase", "knowledge graph", "guided tour", /orca-onboard.
  • Non-goals: do not install the Understand-Anything plugin; do not dispatch reasoning (domain, architecture, layers/tour) to opencode/agy; do not write raw HTML yourself (always via skeleton v2); do not invent file paths or file:line; do not duplicate dispatch syntax (the source of truth is orca-dispatch-reference).

Mental model

Phase 0 pre-flight/bootstrap → Phase 0.5 GATE (draft + dispatch board → user duyệt) → 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. Draft llmwiki/wiki/draft/orca/<DATE>-onboard-<slug>.md is the state log: each phase pending → in-progress → done, resume reads back from there.

Input and output contract

Field Required? Meaning
In <path> no (default .) target project directory; @<draft> = resume from an existing draft
In --full no delete .overstack/graph/ then rebuild
In --update no only re-analyze files changed since the previous run (requires graph + meta.json to be available)
In --language <lang> no output language (vi, en, zh, ...)
In --skip-wiki no skip wiki generation
In user approval at Phase 0.5 yes after the dispatch board + proposed content have been printed to the terminal
In opencode, skill docs-site-macos yes missing → Phase 0 exit 1 with install command
Out .overstack/graph/knowledge-graph.json, ONBOARDING.md, meta.json yes Phase 1 (gate at end of Phase 1 checks the first 2 files)
Out .overstack/onboard/intermediate/domain-graph.json yes Phase 2
Out .overstack/onboard/intermediate/surface.json + coverage.json yes Phase 2 — real surface @commit + coverage log; output report printed in N/M mục bề mặt được phủ (skill surface-coverage)
Out llmwiki/wiki/ (index, concepts, entities) yes except --skip-wiki Phase 3; every page has ## Origin + index line
Out llmwiki/html/onboarding-<slug>.html + llmwiki/html/wiki-graph.html yes (vector fail-open) Phase 4
Out draft status + index/log line yes update after EVERY phase

"Done" = 4 phases done in draft, HTML exists, output report written.

Rules and capabilities

  • RULE-01 (MUST): DO NOT run Phase 0.5 or Phases 1–4 until Phase 0 completes. Hard order, no reversal: Phase 0 (verify llmwiki/ exists) → Phase 0.5 (create draft BEFORE asking user) → Phases 1–4.
  • RULE-02 (MUST): llmwiki/ missing → bootstrap at Phase 0, NEVER defer; bootstrap fail → STOP entirely, report error.
  • RULE-03 (MUST): After EVERY phase → update draft status IMMEDIATELY, don't defer to the end.
  • RULE-04 (MUST): Dispatch board + propose content MUST be printed via bash (visible in terminal) before the gate question; the Agent Task Assignment line in the draft must match the board.
  • RULE-05 (MUST): Reasoning tasks MUST stay in Claude main thread. NO reasoning to opencode/agy. opencode + DeepSeek: template fill, wiki render, HTML only.
  • RULE-06 (MUST): READ BEFORE ACT — each phase reads all inputs in READ FIRST block before any action. Never ask user about something already in a file.
  • RULE-07 (MUST): NO full knowledge-graph.json reads after Phase 1 — use ONBOARDING.md instead.
  • RULE-08 (MUST): Real file paths only — never fabricate; domain graph only references real file:line, verify against code.
  • RULE-12 (MUST): Domain graph coverage reported as diff against real surface (surface-coverage.py check), in the form N/M mục; never report flow/article counts as if the whole app has been explained.
  • RULE-09 (MUST): Wiki: wikilink format [[page-name]]; tour: 5-15 steps, start with project overview.
  • RULE-10 (MUST): Phase 4 NEVER writes raw HTML itself — always via skeleton v2.
  • RULE-11 (MUST): code-graph only indexes when dep-health.py --json reports status == "ok" — declared in config ≠ live server.
  • Capabilities: read target repo + VCS history; run local scripts (bash/python); dispatch cheap LLM for mechanical work; write .overstack/, llmwiki/; network for bootstrap/installing dependencies.

Failure boundaries

  • Missing dependency (opencode, docs-site-macos) or project root does not exist → blocked (exit 1 + install command).
  • --update but no graph/ yet →meta.json → blocked, tell them to run without --update first.
  • Bootstrap fail → failed, STOP entirely.
  • User does not approve at gate → cancelled, only draft remains.
  • Batch analyze fails 2 times → drop batch, write PHASE_WARNINGS → partial graph (partial graph > no graph).
  • Phase 1 gate missing knowledge-graph.json/ONBOARDING.md → failed Phase 1.
  • No HTTP/CLI/event entry point → empty domains (narrow succeeded).
  • Draw wiki-graph.html error → fail-open, does not block onboard.

HOW

Main workflow

Step Type Inputs Action Outputs/exit Failure/next
W01 deterministic args, machine Phase 0 — dependency check, resume/root, update mode, bootstrap llmwiki+harness, create dirs, count files, probe agent environment variables + files.txt missing dep/root → exit 1
W02 effect W01 results Phase 0.5 Gate — create draft FIRST, index+log, print dispatch board + propose, ask user draft pending, approved not approved → cancelled
W03 deterministic repo Phase 1 1.1 SCAN + 1.2 GIT HISTORY (bash) + 1.3 ANALYZE (static parse; opencode only enriches) + 1.4 MERGE (python) assembled-graph.json batch fail → retry 1 → drop, PHASE_WARNINGS
W04 judgment assembled graph, dir tree, README 1.5 LAYERS + TOUR (Claude main thread) layers + tour 5-15 steps —
W05 deterministic graph 1.6 VALIDATE + SAVE + final Phase 1 gate knowledge-graph.json, meta.json, ONBOARDING.md missing file → exit 1
W06 judgment ONBOARDING.md, layers, surface.json Phase 2 real surface (surface-coverage.py scan) → domain enrichment (Claude) → gate check domain-graph.json + coverage.json, line N/M mục no entry point → empty domains; check red after 3 rounds → partial with list of UNCOVERED
W07 effect ONBOARDING + domain graph Phase 3 wiki (opencode, template fill) llmwiki/wiki/ opencode error → Claude fallback
W08 effect ONBOARDING + domain graph + skeleton Phase 4 STEP A JSON → STEP B fill skeleton (python) → STEP C vector HTML + wiki-graph.html skeleton missing → exit 1; vector error → fail-open
W09 effect results Output Report + update status + sync push final draft, index/log —

Step-by-step details (source of truth for W01–W09):

Triggers

  • "onboard codebase", "analyze codebase", "knowledge graph", "guided tour"

Options

  • --full — Delete .overstack/graph/ and rebuild
  • --update — Incremental: re-analyze only changed files since last run
  • --language <lang> — Output language (vi, en, zh, ...)
  • --skip-wiki — Skip wiki generation
  • <path> — Target directory (default: .)

Progress

[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)...

⚠️ HARD RULES

⛔ DO NOT run Phase 0.5 or Phases 1–4 until Phase 0 completes.

Strict order — no reversal:

  1. Phase 0 → complete, verify llmwiki/ exists ✅
  2. Phase 0.5 (Gate) → create draft file FIRST, then ask user
  3. Phases 1–4 → execute, update status after EACH phase immediately
  • llmwiki/ missing → bootstrap in Phase 0, NEVER defer
  • Bootstrap fail → STOP completely, report error
  • After EACH phase → update draft status NOW, never at end

Dispatch Rules

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

Reasoning tasks MUST stay in Claude main thread. NO reasoning to opencode/agy. opencode + DeepSeek: template fill, wiki render, HTML only.


Agent Binaries

Agent Binary Default model Check
Antigravity agy Claude (Sonnet/Opus) agy --version
OpenCode opencode Configurable opencode --version
Kiro kiro-cli — kiro-cli --version

No need for the Understand-Anything plugin. Phase 1 uses the method distilled from Understand-Anything (scan → batch analyze → merge → layers → tour → validate) written directly in this skill — run with bash/python + pure opencode prompt + Claude main thread. Install nothing extra into agy/opencode.

OpenCode with DeepSeek Flash v4:

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

Status Update Helper

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 — Pre-flight & Setup

# --- 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 — Gate

Required: create draft file FIRST, then ask user. Never reverse this order.

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"

⛔ The dispatch board AND the propose file content above MUST be printed via bash (visible in terminal) — restating them only in chat or only in the draft file is NOT sufficient. The user gates orchestration based on this board + propose. The draft's Agent Task Assignment rows must match the board (e.g. if Phase 1 is rerouted to opencode for >100 files, the draft must say opencode, not agy).

Ask for confirmation before continuing.


Phase 1 — Graph Generation (distilled understand-anything — NO plugin needed)

Pipeline: scan (bash) → git history (bash) → batch analyze (opencode + DeepSeek) → merge (python) → layers + tour (Claude main thread) → validate + save (python + Claude). Method distilled from Understand-Anything; every prompt/schema is right below — do not dispatch /understand, do not install the plugin.

Required output:

  • .overstack/graph/knowledge-graph.json (nodes, edges, layers, tour)
  • .overstack/graph/ONBOARDING.md (~20k tokens distilled)
  • .overstack/graph/meta.json

Skip check: RESUME_MODE=true + PHASE1_STATUS=done → skip to Phase 2.

Decision table:

Graph exists Flag Action
No (none) full pipeline
Yes (none) skip Phase 1, use existing graph
Yes --update re-analyze only git diff <meta.gitCommitHash>..HEAD --name-only files, merge into existing graph
Yes --full delete .overstack/graph/, full pipeline
1.1 SCAN (bash — no 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 — no LLM)

Git history signals enrich the graph — what static analysis lacks:

# 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

Apply: top churn → tag node hot; in recent.txt → tag recent; co-change pairs ≥3 → edge related (weight 0.5); tour + ONBOARDING prioritize files hot; recent-subjects for the "What's being worked on" section.

1.3 ANALYZE — PRIMARY: static parse (0 token) · opencode only for enrichment

By default use python static parse (lesson from run 120626-zca-bridge — both cheap and deterministic): regex import/export ... from + require() → resolve relative path → edges imports; test/**.test.ts → tested_by; summary = leading comment of file / list of exports / md heading; type by extension (file/config/document). Imports are mechanical work — LLM is no more accurate than regex. Only dispatch opencode when a richer semantic summary is needed for complex files (optional enrichment):

Split the file list into batches of ~25 files (related files in the same batch: Dockerfile+compose, migrations, CI configs, docs). Dispatch each batch:

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 (inject enough context — DeepSeek does not read anything on its own beyond the assigned list):

Analyze these files in project (, languages: ). For EACH file produce GraphNode {id, type, name, filePath, summary (1-2 câu), tags[]} and GraphEdges {source, target, type, weight} for imports/calls/configures/documents visible in file content. Read each listed file. Write ONLY valid JSON {"nodes":[...], "edges":[...]} to .overstack/onboard/tmp/batch-<i>.json. ID convention: file:<relpath>, config:<relpath>, document:<relpath>. Files: <list with line counts>

At most 5 batches in parallel. Batch fail → retry once → fail again then skip, log PHASE_WARNINGS (partial graph > no graph). opencode unavailable → Claude main thread analyzes the batch itself.

1.4 MERGE + NORMALIZE (python inline — no LLM)

Claude writes script .overstack/onboard/tmp/merge.py (logic distilled from Understand-Anything's merge-batch-graphs.py): read every batch-*.json → merge nodes/edges → normalize ID prefixes (remove double-prefix, add missing prefix) → dedupe nodes by id (keep last), edges by (source,target,type) → drop dangling edges (log to stderr) → add edges related from co-change (1.2) → write assembled-graph.json.

1.5 LAYERS + TOUR (Claude main thread — REASONING, no dispatch)

From assembled-graph + dir tree + README:

  • Layers: [{id: "layer:<kebab>", name, description, nodeIds[]}] — each file-level node belongs to EXACTLY ONE layer; directory structure is the strongest evidence.
  • Tour: 5-15 steps [{order, title, description, nodeIds[]}] — step 1 is always the project overview (README), then entry point, prioritize files hot; tell the same story the README tells but through real code.
1.6 VALIDATE + SAVE (python + Claude)

Validate deterministic (script): no duplicate node ID, no dangling edge, every file node in exactly 1 layer, tour nodeIds exist, count orphans. Auto-fix what can be fixed (drop dangling, fill default), the rest log a warning — partial graph still saves.

Write:

  • knowledge-graph.json: {version, project: {name, languages, frameworks, description, analyzedAt, gitCommitHash}, nodes, edges, layers, tour}
  • meta.json: {lastAnalyzedAt, gitCommitHash, analyzedFiles}
  • ONBOARDING.md (Claude distill, ~20k tokens): overview, layers + descriptions, key flows, hot files + reasons (churn), "What's being worked on" (recent-subjects), tour narrative, stats.

Finally: delete batch-*.json, report summary (files analyzed, nodes/edges by type, layers, tour steps, warnings).

Schema (distilled from Understand-Anything)
  • Node types: file, function, class, module, concept, config, document, service, table, endpoint, pipeline, schema, resource — ID: <type>:<relpath>[:<name>]
  • Main edge types: imports, exports, contains, inherits, implements, calls, reads_from, writes_to, depends_on, tested_by, configures, related, documents, deploys, triggers, routes, defines_schema
  • Weights: contains 1.0 · inherits/implements 0.9 · calls/exports 0.8 · imports 0.7 · depends_on/configures 0.6 · rest 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 INDEX (optional — only when server code-graph is in mcpServers)

Code relationship query layer exact by line supplements the graph distill above: search_symbols, get_callers/callees for instant impact-check. Server code-graph (~/.claude.json → mcpServers) writes 1 SQLite db per repo at <repo>/.graph-agent/index.db.

When to run: project has a submodule/real code repo (Go/TS/Py…) and code-graph is ACTUALLY usable — check with python3 harness/scripts/dep-health.py --json and require status == "ok", DO NOT just check whether it's declared in ~/.claude.json or not. Declared in config ≠ server alive: 0-byte DB, DB missing table symbols, or a dead server all still count as "declared" (lesson 2026-07-20 — code-graph was broken for weeks yet every session still got herded into it). degraded/absent then skip this step.

# 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"

Durability harness: hook SessionStart code_graph_keeper.py (installed with install-harness.sh) auto re-registers the repo if it drops from the registry + warns when the repo isn't indexed. Fail-open, no-op if the project doesn't use code-graph — the condition is having a .graph-agent/index.db usable (opens + has table symbols/files), not just having the file: an empty DB once caused the keeper to write a wrong registry entry and also silenced the "not indexed" warning. Do NOT reindex per-edit (the watcher handles it, debounce 2s). Then write 1 wiki concept page concepts/code-graph-nav.md (how to use the tool + caller trace example) so the team knows how to use it.

Freshness is automatic afterwards: edit file → watcher reindexes ~2s. No need to reindex manually unless it's a fresh clone or a bulk change while the server was off.


Phase 2 — Domain Enrichment

Agent: Claude main thread (no dispatch) | Model: Sonnet

READ FIRST (in order, before writing anything):

  1. .overstack/graph/ONBOARDING.md — full read (~20k tokens)
  2. .overstack/graph/knowledge-graph.json — read layers array + entry-point tagged nodes ONLY (⛔ NOT full file — context overflow)
  3. If UPDATE_MODE=true: read existing .overstack/onboard/intermediate/domain-graph.json (merge, don't overwrite)

DO: 0. Real surface BEFORE choosing flow (skill surface-coverage, GH#191 — 18 flows once reported as covering an entire app of 62 pages + 37 modules): python3 "$FDK_TOOLS/surface-coverage.py" scan "$PROJECT_ROOT" [--modules '<thư mục module API>/*'] --out .overstack/onboard/intermediate/surface.json with FDK_TOOLS=$([ -f fdk/tools/surface-coverage.py ] && echo fdk/tools || echo "$HOME/.claude/harness/fdk/tools") (framework repo → version in repo; client machine → global engine). Framework not file-based → write script listing routes then merge into same file.

  1. From entry points → identify HTTP endpoints / CLI commands / events / cron jobs — each item in surface.json must be covered by a flow or excluded with reason
  2. Reverse-engineer: entry point → flow (process) → steps (actions @ file:line)
  3. Build domain → flow → step hierarchy
  4. Write .overstack/onboard/intermediate/domain-graph.json + coverage ledger .overstack/onboard/intermediate/coverage.json ({"commit", "items": {"page:/x": {"by": ["flow:…"]} | {"exclude": "lý do"}}})
  5. Gate: python3 "$FDK_TOOLS/surface-coverage.py" check surface.json coverage.json --flows domain-graph.json --root "$PROJECT_ROOT" — rc 1 (item NOT COVERED, wrong flow id, file:line wrong) → next code pass fills it, max 3 rounds; still red then Phase 2 = partial. Final report (W09) prints the line verbatim N/M mục bề mặt được phủ, K loại trừ + list of NOT COVERED — NEVER report a bare flow count as if it were sufficient.

Domain graph schema:

{
  "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 }
          ]
        }
      ]
    }
  ]
}

Output: .overstack/onboard/intermediate/domain-graph.json

Skip check: RESUME_MODE=true + PHASE2_STATUS=done → skip to Phase 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

Phase 3 — Wiki Generation

Agent: opencode | Model: opencode/deepseek-v4-flash-free

READ FIRST (inject into SPEC before dispatch — DeepSeek won't read files unless injected):

  1. .overstack/graph/ONBOARDING.md — full read
  2. .overstack/onboard/intermediate/domain-graph.json — full read
  3. If UPDATE_MODE=true: grep llmwiki/wiki/ for refs to CHANGED_FILES → identify stale pages
  • ⛔ DO NOT read .overstack/graph/knowledge-graph.json — too large, context overflow

DO: Fill wiki templates from distilled content. No reasoning — mechanical template fill.

Output structure:

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)

Skip check: RESUME_MODE=true + PHASE3_STATUS=done → skip to Phase 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 Docs (skeleton v2 + JSON island)

Agent: assemble JSON = opencode (mechanical) / Claude fallback · fill skeleton = python (no LLM)

How it works (DIFFERENT from old version — prevent shallowness + broken UX): DO NOT let the model generate raw HTML (DeepSeek invents CSS/JS → loses the "mirror", clicks don't work, output 173–816 lines unstable). Instead: model ONLY emits one JSON object per schema; UI by skeleton v2 frozen (assets/docs-site-skeleton.html, already applied correct design-system /docs-site-macos) render. Skeleton = FIXED nav (Overview/What & How/Architecture/Guided Tour/Modules/Docker; What & How hidden when JSON lacks both what and how) + sidebar fixed + collapse + scroll-spy + tour master-detail + draggable diagram; Modules/Docker auto- hide when mono. Child content (layer/tour/module/docker) DATA-DRIVEN from JSON.

READ FIRST (RICH source — inject into SPEC; DeepSeek does not read files itself):

  1. .overstack/graph/ONBOARDING.md — full (overview, hot files, flows, tour narrative)
  2. .overstack/onboard/intermediate/domain-graph.json — domain→flow→step (tour + lifecycle)
  3. knowledge-graph.json only layers + tour + node entry-point (⛔ NOT full — overflow) ⛔ Do NOT use thin wiki md as the main source (that is why the old version was sketchy).

Skip check: RESUME_MODE=true + PHASE4_STATUS=done → skip.

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

Fallback: opencode dead/hung → Claude main thread reads it itself ONBOARDING.md + domain-graph.json, writes $JSON_OUT per schema (this is data assembly, OK in Claude), then run STEP B. NEVER write raw HTML yourself — always via skeleton v2.

STEP C — draw vector wiki-graph.html (wiki just generated in Phase 3 → now there ARE concepts to draw):

Onboard generates wiki but does NOT draw relation vectors itself — draw RIGHT HERE so a code-only project finishes onboard with vectors already (the right bottleneck: build-wiki-graph.py reads llmwiki/wiki/*.md + code, does not read code directly to generate concepts). Fail-open, does not block onboard.

# 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

After completion:

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"

Rules

  • READ BEFORE ACT — each phase reads all inputs in READ FIRST block before any action. Never ask user about something already in a file.
  • NO full knowledge-graph.json reads after Phase 1 — use ONBOARDING.md instead
  • Real file paths only — never fabricate
  • Domain graph: only reference real file:line, verify against code
  • Wiki: wikilink format [[page-name]]
  • Tour: 5-15 steps, start with project overview
  • Reasoning tasks (domain, architecture): Claude main thread only

Errors

  • Phase 1 batch fail (opencode) → retry once, fail again → Claude main thread analyzes that batch itself; write PHASE_WARNINGS
  • Phase 1 fail (no graph) → check whether batch-*.json exists; merge script error → read stderr, fix, rerun
  • Phase 2 domain empty → no HTTP/CLI/event entry points found; write empty domains array
  • Phase 3 fail → check opencode model config; fallback Claude main thread
  • Phase 4 fail → fallback: invoke docs-site-macos skill directly in Claude

Output Report

After all phases complete, write propose draft to wiki.

1. Filename: DDMMYY-<ten>.md — today's date + 2-4 kebab-case summary words

2. Write 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. Update wiki index & log:

  • llmwiki/wiki/index.md — append: | [DDMMYY-<ten>](draft/orca/DDMMYY-<ten>.md) | draft | YYYY-MM-DD |
  • llmwiki/wiki/log.md — append: ## YYYY-MM-DD — orca-onboard — <ten>

4. Update statuses & sync push — REQUIRED:

  • Update Status column in draft file to reflect actual run
  • Clone rheinmir/setup branch orca, copy updated SKILL.md, push:
    git clone git@github.com: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
    

Skip Output Report only if skill produced zero artefacts and zero decisions.


Output Report

After all phases complete, write propose draft to wiki.

1. Filename: DDMMYY-<ten>.md — today's date + 2-4 kebab-case summary words

2. Write 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. Update wiki index & log:

  • llmwiki/wiki/index.md — append: | [DDMMYY-<ten>](draft/orca/DDMMYY-<ten>.md) | draft | YYYY-MM-DD |
  • llmwiki/wiki/log.md — append: ## YYYY-MM-DD — orca-onboard — <ten>

4. Update statuses & sync push — REQUIRED:

  • Update Status column in draft file to reflect actual run
  • Clone rheinmir/setup branch orca, copy updated SKILL.md, push:
    git clone git@github.com: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
    

Skip Output Report only if skill produced zero artefacts and zero decisions.

Branches

ID Kind Guard Behavior Skip / failure Rejoin
B01 user_optional @<draft> (RESUME_MODE) read status of each phase from draft, phase done then skip draft missing Project root: → empty root → exit 1 first phase not yet done
B02 user_optional --update + graph already exists only re-analyze changed files, merge into existing graph/domain/wiki no graph/ yetmeta.json → exit 1; changedFiles empty → full rebuild W03
B03 user_optional --full delete .overstack/graph/, full pipeline — W03
B04 conditional_required graph exists, no flag skip Phase 1, use old graph — W06
B05 capability_optional code-graph dep-health.py --json reports status == "ok" 1.7 CODE-GRAPH MCP INDEX: reindex_repo each code repo, verify get_stats() >0, write concepts/code-graph-nav.md degraded/absent → skip W06
B06 recovery opencode unavailable/hung at 1.3, Phase 3, Phase 4 STEP A Claude main thread does it itself (analyze batch / wiki / assemble JSON) — Phase 4 still goes through skeleton Phase 4 fails entirely → invoke docs-site-macos directly next step of that phase
B07 user_optional --skip-wiki skip Phase 3 — W08
B08 conditional_required mono repo (N_SVC ≤ 1) modules:[], docker:null → skeleton auto-hides Modules/Docker tab multi-service → has Docker tab W08

Validation and stopping

Deterministic check by script: final Phase 1 gate (2 required files), validate graph 1.6 (no duplicate ID, no dangling edge, each file node exactly 1 layer, tour nodeIds exist), assert all replaced {{TITLE}}/{{ONBOARD_JSON}} at STEP B, ls "$OUT" at end of Phase 4. Needs review: layers/tour, domain graph (cross-check real file:line), wiki quality. Stop when 4 phases done in draft; retry batch at most 1 time.

Examples

  • Positive: /orca-onboard ~/code/zca-bridge on a repo with 180 files, has opencode → draft + dispatch board in terminal → user "ok" → graph 180 nodes + 7 layers + tour 9 steps → domain-graph.json 3 domains → wiki concepts/entities → llmwiki/html/onboarding-zca-bridge.html + wiki-graph.html; draft 4 phases done.
  • Boundary/failure: /orca-onboard --update on a repo never onboarded → Phase 0 outputs "❌ --update requires existing graph. Run without --update first." and exit 1, does not create draft.
  • Boundary: opencode hangs at Phase 4 STEP A → Claude writes onboard.json according to schema skeleton then runs STEP B; does not write raw HTML.