🧭 Dispatch backend — chọn agent/model rẻ, chạy nhiều worker song song, cú pháp opencode/orchestration → xem orca-dispatch-reference (nguồn chân lý duy nhất, đừng nhân bản syntax ở đây).
Onboard codebase via distilled understand-anything pipeline (graph + git history, no plugin), then domain enrichment + wiki + HTML.
🧭 调度后端——选择低成本的 agent/model,并行运行多个 worker;opencode/编排语法 → 参见 orca-dispatch-reference(唯一权威来源,请勿在此复制语法)。
通过提炼版 understand-anything 流水线(知识图谱 + git 历史,无需插件)为代码库完成上手,随后进行领域增强 + wiki + HTML。
- Purpose: onboard một codebase bất kỳ thành tri thức dùng được: knowledge graph (scan + git history + batch analyze + layers/tour, không plugin), domain graph (domain → flow → step), wiki và trang HTML docs — phần reasoning ở Claude main thread, phần cơ học dispatch sang opencode + DeepSeek Flash v4.
- Trigger (when to use): "onboard codebase", "analyze codebase", "knowledge graph", "guided tour", .
- Non-goals: không cài plugin Understand-Anything; không dispatch reasoning (domain, architecture, layers/tour) ra opencode/agy; không tự viết HTML thô (luôn qua skeleton v2); không bịa file path hay file:line; không nhân bản cú pháp dispatch (nguồn chân lý là ).
- 目的: 将任意代码库转化为可用的知识:知识图谱(扫描 + git 历史 + 批量分析 + 分层/导览,无需插件)、领域图谱(领域 → 流程 → 步骤)、 wiki 和 HTML 文档页面——推理部分在 Claude 主线程中完成,机械性调度交给 opencode + DeepSeek Flash v4。
- 触发条件(何时使用): “onboard codebase”、“analyze codebase”、“knowledge graph”、“guided tour”、。
- 非目标: 不安装 Understand-Anything plugin;不将领域、架构、分层/导览等推理任务调度给 opencode/agy;不直接编写原始 HTML(始终通过 skeleton v2);不编造 file path 或 file:line;不复制调度语法(唯一权威来源是 )。
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
là sổ trạng thái: mỗi phase
pending → in-progress → done
, resume đọc lại từ đó.
Phase 0 预检/引导 → Phase 0.5 GATE(草稿 + 调度面板 → 用户批准)→ Phase 1 图谱(扫描 → git 历史 → 分析 → 合并 → 分层+导览 → 验证 → [code-graph 索引]) → Phase 2 领域图谱 → Phase 3 wiki → Phase 4 HTML(JSON → skeleton v2 → wiki-graph 向量)→ 输出报告
。草稿
llmwiki/wiki/draft/orca/<DATE>-onboard-<slug>.md
是状态账本:每个 phase 均按
pending → in-progress → done
推进,恢复时重新从此处读取。
Input và output contract
输入输出契约
| Field | Required? | Ý nghĩa |
|---|
| In | | không (mặc định ) | thư mục dự án đích; = resume từ draft có sẵn |
| In | | không | xoá rồi rebuild |
| In | | không | chỉ phân tích lại file đổi từ lần chạy trước (cần graph + có sẵn) |
| In | | không | ngôn ngữ output (vi, en, zh, ...) |
| In | | không | bỏ sinh wiki |
| In | duyệt của user ở Phase 0.5 | có | sau khi dispatch board + nội dung propose đã in ra terminal |
| In | , skill | có | thiếu → Phase 0 exit 1 kèm lệnh cài |
| Out | .overstack/graph/knowledge-graph.json
, , | có | Phase 1 (gate cuối Phase 1 kiểm 2 file đầu) |
| Out | .overstack/onboard/intermediate/domain-graph.json
| có | Phase 2 |
| Out | .overstack/onboard/intermediate/surface.json
+ | có | Phase 2 — bề mặt thật @commit + sổ phủ; output report in (skill ) |
| Out | (index, concepts, entities) | có trừ | Phase 3; mọi trang có + dòng index |
| Out | llmwiki/html/onboarding-<slug>.html
+ llmwiki/html/wiki-graph.html
| có (vector fail-open) | Phase 4 |
| Out | draft trạng thái + dòng index/log | có | cập nhật sau MỖI phase |
"Xong" = 4 phase
trong draft, HTML tồn tại, output report ghi.
| 字段 | 必填? | 含义 |
|---|
| 输入 | | 否(默认 ) | 目标项目目录; 表示从现有草稿恢复 |
| 输入 | | 否 | 删除 后重新构建 |
| 输入 | | 否 | 仅重新分析自上次运行以来变更的文件(需要已有 graph + ) |
| 输入 | | 否 | 输出语言(vi、en、zh 等) |
| 输入 | | 否 | 跳过 wiki 生成 |
| 输入 | 用户在 Phase 0.5 的批准 | 是 | 调度面板和 propose 内容已输出到终端之后 |
| 输入 | 、skill | 是 | 缺失时 Phase 0 以状态码 1 退出并给出安装命令 |
| 输出 | .overstack/graph/knowledge-graph.json
、、 | 是 | Phase 1(Phase 1 最后的 gate 检查前两个文件) |
| 输出 | .overstack/onboard/intermediate/domain-graph.json
| 是 | Phase 2 |
| 输出 | .overstack/onboard/intermediate/surface.json
+ | 是 | Phase 2——真实应用表面与覆盖账本;输出报告包含 (surface-coverage skill) |
| 输出 | (索引、概念、实体) | 是,除非使用 | Phase 3;所有页面都必须包含 和索引行 |
| 输出 | llmwiki/html/onboarding-<slug>.html
+ llmwiki/html/wiki-graph.html
| 是(向量生成失败时 fail-open) | Phase 4 |
| 输出 | 状态草稿 + 索引/日志行 | 是 | 每个 phase 完成后更新 |
“完成” = 草稿中的 4 个 phase 均为
、HTML 存在,并且已写入输出报告。
Rules và capabilities
规则与能力
- RULE-01 (MUST): DO NOT run Phase 0.5 or Phases 1–4 until Phase 0 completes. Thứ tự cứng không đảo: Phase 0 (verify tồn tại) → Phase 0.5 (tạo draft TRƯỚC rồi mới hỏi user) → Phases 1–4.
- RULE-02 (MUST): thiếu → bootstrap ở Phase 0, NEVER defer; bootstrap fail → STOP hoàn toàn, báo lỗi.
- RULE-03 (MUST): Sau MỖI phase → cập nhật status draft NGAY, không dồn tới cuối.
- RULE-04 (MUST): Dispatch board + nội dung propose PHẢI in qua bash (thấy trong terminal) trước câu hỏi gate; dòng Agent Task Assignment trong draft phải khớp 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 block before any action. Never ask user about something already in a file.
- RULE-07 (MUST): NO full reads after Phase 1 — use instead.
- RULE-08 (MUST): Real file paths only — never fabricate; domain graph only references real file:line, verify against code.
- RULE-12 (MUST): Độ phủ của domain graph báo bằng diff với bề mặt thật (
surface-coverage.py check
), dạng ; không bao giờ báo số flow/bài như thể đã giải thích hết app.
- RULE-09 (MUST): Wiki: wikilink format ; tour: 5-15 steps, start with project overview.
- RULE-10 (MUST): Phase 4 KHÔNG bao giờ tự viết HTML thô — luôn qua skeleton v2.
- RULE-11 (MUST): code-graph chỉ index khi báo — khai báo trong config ≠ server sống.
- Capabilities: đọc repo đích + lịch sử VCS; chạy script cục bộ (bash/python); dispatch LLM rẻ cho việc cơ học; ghi , ; mạng để bootstrap/cài phụ thuộc.
- RULE-01(必须):Phase 0 完成前,不得运行 Phase 0.5 或 Phases 1–4。 顺序不可颠倒:Phase 0(验证 存在)→ Phase 0.5(先创建草稿,再询问用户)→ Phases 1–4。
- RULE-02(必须):如果缺少 ,在 Phase 0 执行 bootstrap,绝不推迟;bootstrap 失败 → 完全停止并报告错误。
- RULE-03(必须):每个 phase 结束后,立即更新草稿状态,不得累积到最后。
- RULE-04(必须):在 gate 问题之前,必须通过 bash 输出调度面板和 propose 内容(以便在终端中看到);草稿中的 Agent Task Assignment 行必须与面板一致。
- RULE-05(必须):推理任务必须保留在 Claude 主线程中。不得将推理任务交给 opencode/agy。 opencode + DeepSeek 仅用于模板填充、wiki 渲染和 HTML。
- RULE-06(必须):先读后执行——每个 phase 在执行任何操作前,必须读取 块中的所有输入。绝不能询问用户文件中已经包含的信息。
- RULE-07(必须):Phase 1 之后不得完整读取 ——改用 。
- RULE-08(必须):只能使用真实 file path——绝不编造;领域图谱只能引用真实的 file:line,并对照代码进行验证。
- RULE-12(必须):领域图谱的覆盖率必须通过与真实表面的差异进行报告(
surface-coverage.py check
),格式为 ;绝不能将 flow 或文章数量报告为已解释整个应用。
- RULE-09(必须):Wiki 使用 格式的 wikilink;导览包含 5–15 个步骤,并以项目概览开始。
- RULE-10(必须):Phase 4 绝不直接编写原始 HTML——始终通过 skeleton v2。
- RULE-11(必须):仅当 报告 时才对 code-graph 建立索引——配置中存在声明不等于服务器正在运行。
- 能力:读取目标 repo + VCS 历史;运行本地脚本(bash/python);为机械性任务调度低成本 LLM;写入 、;使用网络进行 bootstrap/安装依赖。
- Thiếu dependency (opencode, docs-site-macos) hoặc project root không tồn tại → blocked (exit 1 + lệnh cài).
- mà chưa có graph/ → blocked, bảo chạy không trước.
- Bootstrap fail → failed, STOP hoàn toàn.
- User không duyệt ở gate → cancelled, chỉ còn draft.
- Batch analyze fail 2 lần → bỏ batch, ghi PHASE_WARNINGS → partial graph (partial graph > no graph).
- Phase 1 gate thiếu / → failed Phase 1.
- Không có entry point HTTP/CLI/event → domains rỗng (succeeded hẹp).
- Vẽ lỗi → fail-open, không chặn onboard.
- 缺少依赖(opencode、docs-site-macos)或项目根目录不存在 → blocked(以状态码 1 退出并给出安装命令)。
- 使用 ,但不存在 graph/ → blocked,提示先在不带 的情况下运行。
- Bootstrap 失败 → failed,完全停止。
- 用户未在 gate 批准 → cancelled,仅保留草稿。
- 批量分析连续失败 2 次 → 放弃该批次,记录 PHASE_WARNINGS → partial 图谱(部分图谱优于没有图谱)。
- Phase 1 gate 缺少 / → Phase 1 failed。
- 没有 HTTP/CLI/event 入口点 → domains 为空(成功但范围较窄)。
- 生成 失败 → fail-open,不阻止代码库上手。
| Step | Type | Inputs | Action | Outputs/exit | Failure/next |
|---|
| W01 | deterministic | args, máy | Phase 0 — dependency check, resume/root, update mode, bootstrap llmwiki+harness, tạo dirs, đếm file, probe agent | biến môi trường + | thiếu dep/root → exit 1 |
| W02 | effect | kết quả W01 | Phase 0.5 Gate — tạo draft TRƯỚC, index+log, in dispatch board + propose, hỏi user | draft , duyệt | không duyệt → cancelled |
| W03 | deterministic | repo | Phase 1 1.1 SCAN + 1.2 GIT HISTORY (bash) + 1.3 ANALYZE (static parse; opencode chỉ enrich) + 1.4 MERGE (python) | | batch fail → retry 1 → bỏ, PHASE_WARNINGS |
| W04 | judgment | assembled graph, dir tree, README | 1.5 LAYERS + TOUR (Claude main thread) | layers + tour 5-15 bước | — |
| W05 | deterministic | graph | 1.6 VALIDATE + SAVE + gate cuối Phase 1 | , , | thiếu file → exit 1 |
| W06 | judgment | , layers, | Phase 2 bề mặt thật () → domain enrichment (Claude) → gate | + , dòng | không entry point → domains rỗng; đỏ sau 3 vòng → partial kèm danh sách CHƯA PHỦ |
| W07 | effect | ONBOARDING + domain graph | Phase 3 wiki (opencode, template fill) | | opencode lỗi → Claude fallback |
| W08 | effect | ONBOARDING + domain graph + skeleton | Phase 4 STEP A JSON → STEP B fill skeleton (python) → STEP C vector | HTML + | skeleton thiếu → exit 1; vector lỗi → fail-open |
| W09 | effect | kết quả | Output Report + cập nhật status + sync push | draft cuối, index/log | — |
Chi tiết từng bước (nguồn chân lý cho W01–W09):
| 步骤 | 类型 | 输入 | 操作 | 输出/退出 | 失败/下一步 |
|---|
| W01 | deterministic | 参数、机器 | Phase 0——依赖检查、恢复/根目录解析、update 模式、bootstrap llmwiki+harness、创建目录、统计文件、探测 agent | 环境变量 + | 缺少依赖/根目录 → 状态码 1 退出 |
| W02 | effect | W01 结果 | Phase 0.5 Gate——先创建草稿,再写入索引+日志,输出调度面板 + propose,询问用户 | 草稿为 ,等待批准 | 未批准 → cancelled |
| W03 | deterministic | repo | Phase 1:1.1 SCAN + 1.2 GIT HISTORY(bash)+ 1.3 ANALYZE(静态解析;opencode 仅用于增强)+ 1.4 MERGE(python) | | 批次失败 → 重试 1 次 → 放弃并写入 PHASE_WARNINGS |
| W04 | judgment | assembled graph、目录树、README | 1.5 LAYERS + TOUR(Claude 主线程) | 分层 + 5–15 步导览 | — |
| W05 | deterministic | graph | 1.6 VALIDATE + SAVE + Phase 1 最终 gate | 、、 | 缺少文件 → 状态码 1 退出 |
| W06 | judgment | 、layers、 | Phase 2:扫描真实表面()→ 领域增强(Claude)→ gate | + ,输出 行 | 没有入口点 → domains 为空; 连续 3 轮失败 → partial,并附带尚未覆盖列表 |
| W07 | effect | ONBOARDING + domain graph | Phase 3:wiki(opencode,模板填充) | | opencode 失败 → Claude fallback |
| W08 | effect | ONBOARDING + domain graph + skeleton | Phase 4:STEP A JSON → STEP B 填充 skeleton(python)→ STEP C 向量 | HTML + | skeleton 缺失 → 状态码 1 退出;向量失败 → fail-open |
| W09 | effect | 执行结果 | 输出报告 + 更新状态 + 同步推送 | 最终草稿、索引/日志 | — |
各步骤的详细信息(W01–W09 的唯一权威来源):
- "onboard codebase", "analyze codebase", "knowledge graph", "guided tour"
- “onboard codebase”、“analyze codebase”、“knowledge graph”、“guided tour”
- — Delete and rebuild
- — Incremental: re-analyze only changed files since last run
- — Output language (vi, en, zh, ...)
- — Skip wiki generation
- — Target directory (default: )
- ——删除 并重新构建
- ——增量模式:仅重新分析自上次运行以来变更的文件
- ——输出语言(vi、en、zh 等)
- ——跳过 wiki 生成
- ——目标目录(默认 )
[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 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)...
⛔ DO NOT run Phase 0.5 or Phases 1–4 until Phase 0 completes.
Strict order — no reversal:
- Phase 0 → complete, verify exists ✅
- Phase 0.5 (Gate) → create draft file FIRST, then ask user
- Phases 1–4 → execute, update status after EACH phase immediately
- missing → bootstrap in Phase 0, NEVER defer
- Bootstrap fail → STOP completely, report error
- After EACH phase → update draft status NOW, never at end
⛔ Phase 0 完成前,不得运行 Phase 0.5 或 Phases 1–4。
严格顺序——不可颠倒:
- Phase 0 → 完成并验证 存在 ✅
- Phase 0.5(Gate) → 先创建草稿文件,再询问用户
- Phases 1–4 → 执行,并在每个 phase 结束后立即更新状态
- 缺少 → 在 Phase 0 执行 bootstrap,绝不推迟
- Bootstrap 失败 → 完全停止并报告错误
- 每个 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
Reasoning tasks MUST stay in Claude main thread. NO reasoning to opencode/agy.
opencode + DeepSeek: template fill, wiki render, HTML only.
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。
Agent Binaries
Agent 二进制文件
| Agent | Binary | Default model | Check |
|---|
| Antigravity | | Claude (Sonnet/Opus) | |
| OpenCode | | Configurable | |
| Kiro | | — | |
Không cần plugin Understand-Anything. Phase 1 dùng phương pháp đã distill từ Understand-Anything (scan → batch analyze → merge → layers → tour → validate) viết thẳng trong skill này — chạy bằng bash/python + opencode prompt thuần + Claude main thread. Không cài thêm gì vào agy/opencode.
OpenCode with DeepSeek Flash v4:
bash
opencode run "$SPEC" --model opencode/deepseek-v4-flash-free < /dev/null \
| Agent | 二进制文件 | 默认模型 | 检查 |
|---|
| Antigravity | | Claude(Sonnet/Opus) | |
| OpenCode | | 可配置 | |
| Kiro | | — | |
无需 Understand-Anything plugin。 Phase 1 使用从 Understand-Anything 提炼出的方法(扫描 → 批量分析 → 合并 → 分层 → 导览 → 验证),直接写在此 skill 中——通过 bash/python + opencode 纯提示词 + Claude 主线程运行。无需向 agy/opencode 安装任何其他内容。
OpenCode 与 DeepSeek Flash v4:
bash
opencode run "$SPEC" --model opencode/deepseek-v4-flash-free < /dev/null \
Fallback if flag unsupported:
Fallback if flag unsupported:
echo "$SPEC" | opencode --model opencode/deepseek-v4-flash-free
echo "$SPEC" | opencode --model opencode/deepseek-v4-flash-free
Last resort: Claude main thread
Last resort: Claude main thread
Status Update Helper
状态更新辅助函数
bash
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"
}
bash
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
Phase 0 — 预检与设置
--- 1. Dependency check (agy optional — Phase 1 dùng distilled pipeline, không cần agy) ---
--- 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
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 ---
--- 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; }
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 ---
--- 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
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 ---
--- 4. Bootstrap llmwiki + harness if missing ---
Harness có 2 mode: GLOBAL (~/.claude/harness + hooks trong ~/.claude/settings.json,
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ệ 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.
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
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 ---
--- 5. Create dirs ---
mkdir -p $PROJECT_ROOT/.overstack/onboard/{intermediate,tmp}
mkdir -p $PROJECT_ROOT/llmwiki/wiki/draft/{cave,uiux,orca}
mkdir -p $PROJECT_ROOT/.overstack/onboard/{intermediate,tmp}
mkdir -p $PROJECT_ROOT/llmwiki/wiki/draft/{cave,uiux,orca}
--- 6. File count & availability check ---
--- 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 ' ')
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
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"
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 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
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
Phase 0.5 — Gate
Required: create draft file FIRST, then ask user. Never reverse this order.
bash
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"
必须:先创建草稿文件,再询问用户。绝不能颠倒此顺序。
bash
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
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)
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}
${DATE}-onboard-${PROJECT_SLUG}
Agent CLI Availability
Agent CLI Availability
| Agent | Binary | Status |
|---|
| Antigravity | `agy` | $AGY_OK |
| OpenCode | `opencode` | $OC_OK |
| Kiro | `kiro-cli` | $KIRO_OK |
| Agent | Binary | Status |
|---|
| Antigravity | `agy` | $AGY_OK |
| OpenCode | `opencode` | $OC_OK |
| Kiro | `kiro-cli` | $KIRO_OK |
Agent Task Assignment
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 |
| 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 |
Onboard `$PROJECT_ROOT` — understand-anything graph, domain enrichment, wiki, HTML.
Onboard `$PROJECT_ROOT` — understand-anything graph, domain enrichment, wiki, HTML.
- `.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)
- `.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)
| 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) |
| 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) |
- 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
- 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
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 |
| 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 |
- Draft: `wiki/draft/orca/${DATE}-onboard-${PROJECT_SLUG}.md`
- Commit: (filled by verify-before-commit)
- Date promoted: (filled by verify-before-commit)
EOF
- 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
Update wiki index + log
echo "| ${DATE}-onboard-${PROJECT_SLUG} | 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"
echo "| ${DATE}-onboard-${PROJECT_SLUG} | 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) ---
--- 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 "======================================================================"
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) ---
--- 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.
---
echo ""
echo "PROPOSE FILE: $DRAFT_FILE"
echo "----------------------------------------------------------------------"
cat "$DRAFT_FILE"
⛔ 上方的调度面板和 propose 文件内容必须通过 bash 输出(用户需在终端中看到)——仅在聊天中复述或仅写入草稿文件均不符合要求。用户根据此面板和 propose 决定是否批准编排。草稿中的 Agent Task Assignment 行必须与面板一致(例如,Phase 1 因文件超过 100 个而改派给 opencode 时,草稿必须写 opencode,而不是 agy)。
继续前请求用户确认。
---
Phase 1 — Graph Generation (distilled understand-anything — KHÔNG cần plugin)
Phase 1 — 图谱生成(提炼版 understand-anything——无需 plugin)
Pipeline: scan (bash) → git history (bash) → batch analyze (opencode + DeepSeek) → merge (python) → layers + tour (Claude main thread) → validate + save (python + Claude). Phương pháp distill từ Understand-Anything; mọi prompt/schema nằm ngay dưới đây — không dispatch
, không cài 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: +
→ skip to Phase 2.
Decision table:
| Graph exists | Flag | Action |
|---|
| No | (none) | full pipeline |
| Yes | (none) | skip Phase 1, use existing graph |
| Yes | | re-analyze only git diff <meta.gitCommitHash>..HEAD --name-only
files, merge into existing graph |
| Yes | | delete , full pipeline |
流水线: 扫描(bash)→ git 历史(bash)→ 批量分析(opencode + DeepSeek)→ 合并(python)→ 分层 + 导览(Claude 主线程)→ 验证 + 保存(python + Claude)。该方法提炼自 Understand-Anything;所有提示词/schema 均直接列于下方——不调度
,也不安装 plugin。
必需输出:
.overstack/graph/knowledge-graph.json
(节点、边、分层、导览)
.overstack/graph/ONBOARDING.md
(提炼后约 20k tokens)
.overstack/graph/meta.json
决策表:
| Graph 是否存在 | 标志 | 操作 |
|---|
| 否 | 无 | 完整流水线 |
| 是 | 无 | 跳过 Phase 1,使用现有 graph |
| 是 | | 仅重新分析 git diff <meta.gitCommitHash>..HEAD --name-only
中的文件,并合并到现有 graph |
| 是 | | 删除 ,运行完整流水线 |
1.1 SCAN (bash — no LLM)
1.1 SCAN(bash——无 LLM)
bash
mkdir -p "$PROJECT_ROOT/.overstack/graph" "$PROJECT_ROOT/.overstack/onboard/tmp"
git -C "$PROJECT_ROOT" ls-files > "$PROJECT_ROOT/.overstack/onboard/tmp/files.txt"
bash
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
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
Đọ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...
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)
1.2 GIT HISTORY(bash——无 LLM)
Tín hiệu lịch sử git làm giàu graph — thứ phân tích tĩnh không có:
使用 git 历史信号丰富图谱——提供静态分析无法获得的信息:
Churn — file nóng (hay sửa nhất, 365 ngày)
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"
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)
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"
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
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"
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 theo commit, đếm cặp file đổi cùng nhau, ngưỡng ≥3
Co-change — python đọc theo commit, đếm cặp file đổi cùng nhau, ngưỡng ≥3
Áp dụng: top churn → tag node `hot`; trong recent.txt → tag `recent`; cặp co-change ≥3 → edge `related` (weight 0.5); tour + ONBOARDING ưu tiên file `hot`; recent-subjects cho mục "What's being worked on".
应用方式:churn 排名靠前的文件 → 为节点添加 `hot` 标签;出现在 recent.txt 中 → 添加 `recent` 标签;共同变更次数 ≥3 的文件对 → 添加 `related` 边(权重 0.5);导览和 ONBOARDING 优先展示 `hot` 文件;recent-subjects 用于“What's being worked on”部分。
1.3 ANALYZE — PRIMARY: static parse (0 token) · opencode chỉ để enrich
1.3 ANALYZE——主要方式:静态解析(0 token)· opencode 仅用于增强
Mặc định dùng python static parse (bài học run 120626-zca-bridge — vừa rẻ vừa deterministic):
regex
+
→ resolve relative path → edges
;
→
; summary = comment đầu file / danh sách exports / heading md;
type theo extension (file/config/document). Imports là việc mechanical — LLM không chính xác hơn regex.
Chỉ dispatch opencode khi cần summary giàu ngữ nghĩa hơn cho file phức tạp (optional enrichment):
Chia file list thành batch ~25 file (file liên quan cùng batch: Dockerfile+compose, migrations, CI configs, docs). Mỗi batch dispatch:
bash
opencode run "$BATCH_SPEC" --model opencode/deepseek-v4-flash-free < /dev/null
默认使用 python 静态解析(run 120626-zca-bridge 的经验——既便宜又确定):
使用 regex 匹配
+
→ 解析相对路径 → 生成
边;
→
;摘要 = 文件开头注释 / exports 列表 / Markdown heading;
根据扩展名确定类型(文件/配置/文档)。Imports 属于机械性工作——LLM 并不会比 regex 更准确。
仅当复杂文件需要更丰富的语义摘要时,才调度 opencode(可选增强):
将文件列表拆分为约 25 个文件一批(相关文件放入同一批:Dockerfile+compose、migrations、CI configs、docs)。每批调度:
bash
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.
⚠ 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).
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 đủ context — DeepSeek không tự đọc gì ngoài danh sách được giao):
> Analyze these files in project <name> (<description>, languages: <langs>). 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 kèm line counts>
Tối đa 5 batch song song. Batch fail → retry 1 lần → fail nữa thì bỏ qua, ghi PHASE_WARNINGS (partial graph > no graph). opencode unavailable → Claude main thread tự analyze batch.
`BATCH_SPEC`(注入完整上下文——DeepSeek 无法自行读取所给列表之外的内容):
> 分析项目 <name>(<description>,语言:<langs>)中的以下文件。对于每个文件,生成 GraphNode `{id, type, name, filePath, summary(1–2 句话), 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 inline — no LLM)
1.4 MERGE + NORMALIZE(内联 python——无 LLM)
Claude viết script
.overstack/onboard/tmp/merge.py
(logic distill từ merge-batch-graphs.py của Understand-Anything): đọc mọi
→ gộp nodes/edges → chuẩn hoá ID prefix (bỏ double-prefix, thêm prefix thiếu) → dedupe node theo id (giữ bản cuối), edge theo (source,target,type) → drop edge dangling (log stderr) → thêm edges
từ co-change (1.2) → ghi
.
Claude 编写脚本
.overstack/onboard/tmp/merge.py
(逻辑提炼自 Understand-Anything 的 merge-batch-graphs.py):读取所有
→ 合并节点/边 → 规范化 ID 前缀(移除重复前缀、补充缺失前缀)→ 按 id 去重节点(保留最新版本),按 (source,target,type) 去重边 → 删除悬空边(写入 stderr)→ 根据 1.2 中的共同变更关系添加
边 → 写入
。
1.5 LAYERS + TOUR (Claude main thread — REASONING, không dispatch)
1.5 LAYERS + TOUR(Claude 主线程——推理,不调度)
Từ assembled-graph + dir tree + README:
- Layers:
[{id: "layer:<kebab>", name, description, nodeIds[]}]
— mỗi file-level node thuộc ĐÚNG MỘT layer; cấu trúc thư mục là bằng chứng mạnh nhất.
- Tour: 5-15 bước
[{order, title, description, nodeIds[]}]
— bước 1 luôn là project overview (README), theo entry point, ưu tiên file ; kể cùng câu chuyện README kể nhưng qua code thật.
根据 assembled graph + 目录树 + README:
- Layers:
[{id: "layer:<kebab>", name, description, nodeIds[]}]
——每个文件级节点必须且只能属于一个 layer;目录结构是最强的证据。
- Tour: 5–15 个步骤,格式为
[{order, title, description, nodeIds[]}]
——第 1 步始终是项目概览(README),随后跟随入口点,并优先选择 文件;应像 README 那样讲述同一个项目故事,但通过真实代码呈现。
1.6 VALIDATE + SAVE (python + Claude)
1.6 VALIDATE + SAVE(python + Claude)
Validate deterministic (script): không duplicate node ID, không dangling edge, mọi file node trong đúng 1 layer, tour nodeIds tồn tại, đếm orphan. Sửa tự động được thì sửa (drop dangling, fill default), còn lại ghi warning — partial graph vẫn save.
Ghi:
- :
{version, project: {name, languages, frameworks, description, analyzedAt, gitCommitHash}, nodes, edges, layers, tour}
- :
{lastAnalyzedAt, gitCommitHash, analyzedFiles}
- (Claude distill, ~20k tokens): overview, layers + mô tả, key flows, hot files + lý do (churn), "What's being worked on" (recent-subjects), tour narrative, stats.
Cuối: xoá
, báo summary (files analyzed, nodes/edges by type, layers, tour steps, warnings).
执行确定性验证(脚本):不得有重复节点 ID,不得有悬空边,每个文件节点必须位于一个 layer 中,tour nodeIds 必须存在,并统计孤立节点。能够自动修复的问题直接修复(删除悬空边、填充默认值),其余写入 warning——仍保存部分图谱。
写入:
- :
{version, project: {name, languages, frameworks, description, analyzedAt, gitCommitHash}, nodes, edges, layers, tour}
- :
{lastAnalyzedAt, gitCommitHash, analyzedFiles}
- (Claude 提炼,约 20k tokens):概览、分层及说明、关键流程、hot 文件及其原因(churn)、“What's being worked on”(recent-subjects)、导览叙述和统计数据。
最后:删除
,输出摘要(已分析文件数、按类型划分的节点/边数、分层数、导览步骤数和 warnings)。
Schema (distill từ Understand-Anything)
Schema(提炼自 Understand-Anything)
- Node types:
file, function, class, module, concept, config, document, service, table, endpoint, pipeline, schema, resource
— ID: <type>:<relpath>[:<name>]
- Edge types chính: 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 · còn lại 0.5
- 节点类型:
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
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"
[ ! -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"
update_phase_status "Phase 1 —" "done"
1.7 CODE-GRAPH MCP INDEX (optional — chỉ khi server có trong mcpServers)
1.7 CODE-GRAPH MCP INDEX(可选——仅当 中存在 server 时执行)
Tầng truy vấn quan hệ code
chính xác theo line bổ sung cho graph distill ở trên:
,
cho impact-check tức thì. Server
(
~/.claude.json → mcpServers
) ghi 1 db SQLite mỗi repo tại
<repo>/.graph-agent/index.db
.
Khi nào chạy: project có submodule/repo code thật (Go/TS/Py…)
và code-graph THẬT SỰ dùng được — kiểm bằng
python3 harness/scripts/dep-health.py --json
và đòi
, ĐỪNG chỉ xem nó có được khai báo trong
hay không. Khai báo trong config ≠ server sống: DB 0 byte, DB thiếu bảng
, hay server đã chết đều vẫn "đang khai báo" (bài học 2026-07-20 — code-graph hỏng nhiều tuần mà mọi phiên vẫn bị lùa vào nó).
/
thì bỏ qua bước này.
这一层提供按行精确的代码关系查询,为上述提炼版图谱提供补充:
、
可用于即时 impact-check。code-graph server(
~/.claude.json → mcpServers
)会为每个 repo 在
<repo>/.graph-agent/index.db
中写入一个 SQLite 数据库。
执行时机: 项目包含真实代码的 submodule/repo(Go/TS/Py 等),并且 code-graph
确实可用——通过
python3 harness/scripts/dep-health.py --json
检查并要求
;不要只查看
中是否声明了它。配置中存在声明不等于服务器正在运行:DB 为 0 字节、DB 缺少
表或服务器已停止,都仍属于“已声明”状态(2026-07-20 的经验——code-graph 损坏数周,但每个会话仍被错误信任)。如果状态为
/
,则跳过此步骤。
1. Index từng repo code (auto-detect root từ .git/go.mod/package.json).
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.
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>/).
Lưu ý: code có thể nằm trong 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.
→ 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
2. reindex_repo tự thêm repo vào registry ~/.graph-agent/repos.txt
→ server --watch re-watch sau restart (durability).
→ server --watch re-watch sau restart (durability).
3. Verify: get_stats() phải thấy symbols thật (>0), không phải stub.
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` (cài kèm install-harness.sh) tự re-register repo nếu rớt registry + cảnh báo repo chưa index. Fail-open, **no-op nếu project không dùng code-graph** — điều kiện là có `.graph-agent/index.db` **dùng được** (mở được + có bảng `symbols`/`files`), không phải chỉ có file: DB rỗng từng khiến keeper ghi nhầm registry và dập tắt luôn cảnh báo "chưa index". KHÔNG reindex per-edit (watcher đã lo, debounce 2s). Sau đó ghi 1 wiki concept page `concepts/code-graph-nav.md` (cách dùng tool + ví dụ caller trace) để team biết dùng.
> Freshness sau đó tự động: edit file → watcher reindex ~2s. Không cần reindex tay trừ khi clone mới hoặc đổi hàng loạt lúc server tắt.
---
echo "[1.7] code-graph: gọi reindex_repo cho mỗi repo code có manifest"
**持久化 harness:** SessionStart hook `code_graph_keeper.py`(随 install-harness.sh 安装)会在 repo 从 registry 丢失时自动重新注册,并警告尚未索引的 repo。该机制 fail-open,**如果项目不使用 code-graph,则不执行任何操作**——前提是 `.graph-agent/index.db` **确实可用**(可打开且包含 `symbols`/`files` 表),而不只是文件存在:空 DB 曾导致 keeper 错误写入 registry,进而错误关闭“尚未索引”警告。不要在每次编辑后重新索引(watcher 已通过 2 秒 debounce 处理)。随后编写一个 wiki concept 页面 `concepts/code-graph-nav.md`(工具使用方式和 caller trace 示例),让团队了解其用法。
> 此后的新鲜度会自动维护:编辑文件 → watcher 约 2 秒后重新索引。除非克隆了新仓库或服务器关闭期间发生批量变更,否则无需手动重新索引。
---
Phase 2 — Domain Enrichment
Phase 2 — 领域增强
Agent: Claude main thread (no dispatch) | Model: Sonnet
READ FIRST (in order, before writing anything):
.overstack/graph/ONBOARDING.md
— full read (~20k tokens)
.overstack/graph/knowledge-graph.json
— read array + tagged nodes ONLY (⛔ NOT full file — context overflow)
- If : read existing
.overstack/onboard/intermediate/domain-graph.json
(merge, don't overwrite)
DO:
0.
Bề mặt thật TRƯỚC khi chọn flow (skill
, GH#191 — 18 flow từng bị báo như phủ hết một app 62 trang + 37 module):
python3 "$FDK_TOOLS/surface-coverage.py" scan "$PROJECT_ROOT" [--modules '<thư mục module API>/*'] --out .overstack/onboard/intermediate/surface.json
với
FDK_TOOLS=$([ -f fdk/tools/surface-coverage.py ] && echo fdk/tools || echo "$HOME/.claude/harness/fdk/tools")
(repo framework → bản trong repo; máy khách → engine global). Khung không file-based → viết script liệt kê route rồi gộp vào cùng file.
- From entry points → identify HTTP endpoints / CLI commands / events / cron jobs — mỗi mục trong phải được một flow phủ hoặc loại trừ có lý do
- Reverse-engineer: entry point → flow (process) → steps (actions @ file:line)
- Build hierarchy
- Write
.overstack/onboard/intermediate/domain-graph.json
+ sổ phủ .overstack/onboard/intermediate/coverage.json
({"commit", "items": {"page:/x": {"by": ["flow:…"]} | {"exclude": "lý do"}}}
)
- Gate:
python3 "$FDK_TOOLS/surface-coverage.py" check surface.json coverage.json --flows domain-graph.json --root "$PROJECT_ROOT"
— rc 1 (mục CHƯA PHỦ, flow id sai, sai) → lần code lấp tiếp, tối đa 3 vòng; vẫn đỏ thì Phase 2 = partial. Báo cáo cuối (W09) in nguyên dòng N/M mục bề mặt được phủ, K loại trừ
+ danh sách CHƯA PHỦ — KHÔNG bao giờ báo số flow trơn như thể đã đủ.
Domain graph schema:
json
{
"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: +
→ skip to Phase 3.
bash
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
Agent: Claude 主线程(不调度) | 模型: Sonnet
READ FIRST(按顺序,在写入任何内容前执行):
.overstack/graph/ONBOARDING.md
——完整读取(约 20k tokens)
.overstack/graph/knowledge-graph.json
——仅读取 数组和带 标签的节点(⛔ 不得读取完整文件——会导致上下文溢出)
- 如果 :读取现有
.overstack/onboard/intermediate/domain-graph.json
(执行合并,不要覆盖)
执行:
0.
选择 flow 前先获取真实表面(surface-coverage skill,GH#191——过去曾将 18 个 flow 错误报告为已覆盖一个包含 62 个页面和 37 个模块的完整应用):
python3 "$FDK_TOOLS/surface-coverage.py" scan "$PROJECT_ROOT" [--modules '<thư mục module API>/*'] --out .overstack/onboard/intermediate/surface.json
其中
FDK_TOOLS=$([ -f fdk/tools/surface-coverage.py ] && echo fdk/tools || echo "$HOME/.claude/harness/fdk/tools")
(repo framework → 使用仓库内版本;客户机器 → 使用全局 engine)。如果框架不基于文件 → 编写脚本列出 routes,然后合并到同一文件。
- 从入口点识别 HTTP endpoints / CLI commands / events / cron jobs—— 中的每一项都必须由某个 flow 覆盖,或给出有理由的排除项
- 逆向推导:入口点 → flow(流程)→ steps(基于 file:line 的操作)
- 构建 层级结构
- 写入
.overstack/onboard/intermediate/domain-graph.json
和覆盖账本 .overstack/onboard/intermediate/coverage.json
({"commit", "items": {"page:/x": {"by": ["flow:…"]} | {"exclude": "lý do"}}}
)
- Gate:
python3 "$FDK_TOOLS/surface-coverage.py" check surface.json coverage.json --flows domain-graph.json --root "$PROJECT_ROOT"
——返回码 1(存在尚未覆盖的项目、flow id 错误或 错误)→ 继续查找代码进行补全,最多 3 轮;仍失败则 Phase 2 = partial。最终报告(W09)必须原样输出 N/M mục bề mặt được phủ, K loại trừ
+ 尚未覆盖列表——绝不能只报告 flow 数量并暗示其已足够。
领域图谱 schema:
json
{
"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
bash
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
Phase 3 — Wiki 生成
Agent: opencode |
Model: opencode/deepseek-v4-flash-free
READ FIRST (inject into SPEC before dispatch — DeepSeek won't read files unless injected):
.overstack/graph/ONBOARDING.md
— full read
.overstack/onboard/intermediate/domain-graph.json
— full read
- If : grep for refs to → 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
Agent: opencode |
模型: opencode/deepseek-v4-flash-free
READ FIRST(在调度前注入 SPEC——除非注入内容,否则 DeepSeek 不会读取文件):
.overstack/graph/ONBOARDING.md
——完整读取
.overstack/onboard/intermediate/domain-graph.json
——完整读取
- 如果 :在 中搜索对 的引用 → 识别过期页面
- ⛔ 不要读取
.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)
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.
```bash
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
**跳过检查:** `RESUME_MODE=true` + `PHASE3_STATUS=done` → 跳至 Phase 4。
```bash
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)
Phase 4 — HTML 文档(skeleton v2 + JSON island)
Agent: assemble JSON = opencode (mechanical) / Claude fallback · fill skeleton = python (no LLM)
Cách hoạt động (KHÁC bản cũ — chống sơ sài + đứt UX): KHÔNG để model sinh HTML thô
(DeepSeek tự chế CSS/JS → mất "gương", ấn không ăn, output 173–816 dòng không ổn định).
Thay vào đó: model CHỈ phát
một object JSON theo schema; UI do
skeleton v2 frozen
(
assets/docs-site-skeleton.html
, đã áp đúng design-system
) render.
Skeleton = nav CỐ ĐỊNH (Overview/What & How/Architecture/Guided Tour/Modules/Docker; What & How ẩn khi JSON thiếu cả
lẫn
) + sidebar
fixed + collapse + scroll-spy + tour master-detail + draggable diagram;
Modules/Docker tự
ẩn khi mono. Nội dung con (layer/tour/module/docker) DATA-DRIVEN từ JSON.
READ FIRST (nguồn GIÀU — inject vào SPEC; DeepSeek không tự đọc file):
.overstack/graph/ONBOARDING.md
— full (overview, hot files, flows, tour narrative)
.overstack/onboard/intermediate/domain-graph.json
— domain→flow→step (tour + lifecycle)
- chỉ + + node entry-point (⛔ KHÔNG full — overflow)
⛔ KHÔNG dùng wiki md mỏng làm nguồn chính (đó là lý do bản cũ sơ sài).
bash
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 chết/treo → Claude main thread tự đọc
+
, viết
theo schema (đây là assemble dữ liệu, OK ở Claude),
rồi chạy STEP B. KHÔNG bao giờ tự viết HTML thô — luôn qua skeleton v2.
STEP C — vẽ vector (wiki vừa sinh ở Phase 3 → giờ CÓ concept để vẽ):
Onboard đẻ wiki nhưng KHÔNG tự vẽ vector quan hệ — vẽ NGAY tại đây để dự án code-only kết thúc
onboard là có luôn vector (đúng nút thắt:
đọc
+ code, không
đọc thẳng code để đẻ concept). Fail-open, không chặn onboard.
Agent: 组装 JSON = opencode(机械操作)/ Claude fallback · 填充 skeleton = python(无 LLM)
工作方式(与旧版不同——防止粗制滥造和 UX 破损): 不让模型直接生成原始 HTML
(DeepSeek 自行编造 CSS/JS → 失去“设计系统”,按钮无法点击,输出 173–816 行且不稳定)。
取而代之,模型只根据 schema 输出
一个 JSON object;UI 由
skeleton v2 frozen
(
assets/docs-site-skeleton.html
,已应用正确的 design-system
)渲染。
Skeleton = 固定导航(Overview/What & How/Architecture/Guided Tour/Modules/Docker;当 JSON 同时缺少
和
时隐藏 What & How)+ 固定 sidebar + 折叠 + scroll-spy + tour 主从视图 + 可拖拽图表;Modules/Docker 在 mono 项目中自动隐藏。子内容(layer/tour/module/docker)均由 JSON 数据驱动。
READ FIRST(信息丰富——注入 SPEC;DeepSeek 不会自行读取文件):
.overstack/graph/ONBOARDING.md
——完整读取(概览、hot 文件、flows、导览叙述)
.overstack/onboard/intermediate/domain-graph.json
——domain→flow→step(导览 + 生命周期)
- ——仅读取 + + entry-point 节点(⛔ 不得完整读取——会溢出)
⛔ 不要使用内容浅薄的 wiki Markdown 作为主要来源(这正是旧版质量不足的原因)。
bash
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 崩溃/挂起 → Claude 主线程自行读取
+
,根据 skeleton schema 编写
(此处属于数据组装,可由 Claude 完成),然后运行 STEP B。绝不能直接编写原始 HTML——始终通过 skeleton v2。
STEP C——绘制向量 (Phase 3 刚生成 wiki,因此现在已有 concept 可供绘制):
代码库上手会生成 wiki,但不会自行绘制关系向量——在此立即绘制,使纯代码项目在完成上手后立即拥有向量(正确顺序:先由
读取
+ 代码,不能直接读取代码来臆造 concept)。Fail-open,不阻止代码库上手。
engine: repo-local → global (cùng thứ tự hook Stop resolve)
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:**
```bash
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"
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
**完成后:**
```bash
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 BEFORE ACT — each phase reads all inputs in block before any action. Never ask user about something already in a file.
- NO full reads after Phase 1 — use instead
- Real file paths only — never fabricate
- Domain graph: only reference real file:line, verify against code
- Wiki: wikilink format
- Tour: 5-15 steps, start with project overview
- Reasoning tasks (domain, architecture): Claude main thread only
- 先读后执行——每个 phase 在执行任何操作前,必须读取 块中的所有输入。绝不能询问用户文件中已经包含的信息。
- Phase 1 之后不得完整读取 ——改用
- 只能使用真实 file path——绝不编造
- 领域图谱:只能引用真实 file:line,并对照代码进行验证
- Wiki:使用 格式的 wikilink
- 导览:5–15 个步骤,并以项目概览开始
- 推理任务(领域、架构):仅在 Claude 主线程中执行
- Phase 1 batch fail (opencode) → retry 1 lần, fail nữa → Claude main thread tự analyze batch đó; ghi PHASE_WARNINGS
- Phase 1 fail (no graph) → kiểm tra batch-*.json có tồn tại không; merge script lỗi → đọc stderr, sửa, chạy lại
- 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
- Phase 1 批次失败(opencode)→ 重试 1 次,再次失败则由 Claude 主线程自行分析该批次;写入 PHASE_WARNINGS
- Phase 1 失败(没有 graph)→ 检查 是否存在;merge 脚本出错 → 读取 stderr,修复并重新运行
- Phase 2 domain 为空 → 未找到 HTTP/CLI/event 入口点;写入空 domains 数组
- Phase 3 失败 → 检查 opencode 模型配置;fallback 到 Claude 主线程
- Phase 4 失败 → fallback:在 Claude 中直接调用 docs-site-macos skill
After all phases complete, write propose draft to wiki.
1. Filename: — 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
---
所有 phase 完成后,将 propose 草稿写入 wiki。
1. 文件名: ——当天日期 + 2–4 个 kebab-case 摘要词
2. 写入 llmwiki/wiki/draft/orca/DDMMYY-<ten>.md
:
---
type: draft
title: DDMMYY-<ten>
status: proposed
tags: [orca-onboard, output-report]
timestamp: YYYY-MM-DD
---
Agent Task Assignment
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 |
| 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 |
<One sentence>
<One sentence>
<Key artefacts>
<Key artefacts>
| File | Action |
|---|
.overstack/graph/knowledge-graph.json
| created |
| created/modified |
llmwiki/html/onboarding-<slug>.html
| created |
| File | Action |
|---|
.overstack/graph/knowledge-graph.json
| created |
| created/modified |
llmwiki/html/onboarding-<slug>.html
| created |
- 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:
```bash
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.
- 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,然后推送:
```bash
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
仅当该 skill 未生成任何产物且未做出任何决策时,才可跳过输出报告。
After all phases complete, write propose draft to wiki.
1. Filename: — 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
---
所有 phase 完成后,将 propose 草稿写入 wiki。
1. 文件名: ——当天日期 + 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
---
Agent Task Assignment
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 |
| 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 |
<One sentence>
<One sentence>
<Key artefacts>
<Key artefacts>
| File | Action |
|---|
.overstack/graph/knowledge-graph.json
| created |
| created/modified |
llmwiki/html/onboarding-<slug>.html
| created |
| File | Action |
|---|
.overstack/graph/knowledge-graph.json
| created |
| created/modified |
llmwiki/html/onboarding-<slug>.html
| created |
- 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:
```bash
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.
- 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,然后推送:
```bash
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
仅当该 skill 未生成任何产物且未做出任何决策时,才可跳过输出报告。
| ID | Kind | Guard | Hành vi | Skip / failure | Rejoin |
|---|
| B01 | user_optional | (RESUME_MODE) | đọc status từng phase từ draft, phase thì skip | draft thiếu → root rỗng → exit 1 | phase đầu tiên chưa |
| B02 | user_optional | + graph có sẵn | chỉ re-analyze file đổi, merge vào graph/domain/wiki cũ | chưa có graph/ → exit 1; rỗng → full rebuild | W03 |
| B03 | user_optional | | xoá , full pipeline | — | W03 |
| B04 | conditional_required | graph có sẵn, không cờ | skip Phase 1, dùng graph cũ | — | W06 |
| B05 | capability_optional | code-graph báo | 1.7 CODE-GRAPH MCP INDEX: mỗi repo code, verify >0, ghi concepts/code-graph-nav.md
| / → skip | W06 |
| B06 | recovery | opencode unavailable/treo ở 1.3, Phase 3, Phase 4 STEP A | Claude main thread tự làm (analyze batch / wiki / assemble JSON) — Phase 4 vẫn qua skeleton | Phase 4 fail hẳn → invoke trực tiếp | bước kế tiếp của phase đó |
| B07 | user_optional | | bỏ Phase 3 | — | W08 |
| B08 | conditional_required | repo mono () | , → skeleton tự ẩn tab Modules/Docker | multi-service → có tab Docker | W08 |
| ID | 类型 | 守卫 | 行为 | 跳过/失败 | 汇合 |
|---|
| B01 | user_optional | (RESUME_MODE) | 从草稿读取各 phase 状态,状态为 的 phase 跳过 | 草稿缺少 → 根目录为空 → 状态码 1 退出 | 第一个尚未 的 phase |
| B02 | user_optional | + 已有 graph | 仅重新分析变更文件,并合并到现有 graph/domain/wiki | 不存在 graph/ → 状态码 1 退出; 为空 → 完整重建 | W03 |
| B03 | user_optional | | 删除 ,运行完整流水线 | — | W03 |
| B04 | conditional_required | 已有 graph,无标志 | 跳过 Phase 1,使用旧 graph | — | W06 |
| B05 | capability_optional | code-graph 的 报告 | 1.7 CODE-GRAPH MCP INDEX:对每个代码 repo 执行 ,验证 >0,并编写 concepts/code-graph-nav.md
| / → 跳过 | W06 |
| B06 | recovery | 1.3、Phase 3、Phase 4 STEP A 中 opencode 不可用/挂起 | 由 Claude 主线程自行完成(分析批次/wiki/组装 JSON)——Phase 4 仍通过 skeleton | Phase 4 完全失败 → 直接调用 | 该 phase 的下一步骤 |
| B07 | user_optional | | 跳过 Phase 3 | — | W08 |
| B08 | conditional_required | mono repo() | 、 → skeleton 自动隐藏 Modules/Docker 标签页 | 多服务项目 → 显示 Docker 标签页 | W08 |
Validation và stopping
验证与停止条件
Kiểm tất định bằng script: gate cuối Phase 1 (2 file bắt buộc), validate graph 1.6 (không duplicate ID, không dangling edge, mỗi file node đúng 1 layer, tour nodeIds tồn tại), assert thay hết
/
ở STEP B,
ở cuối Phase 4. Cần review: layers/tour, domain graph (đối chiếu file:line thật), chất lượng wiki. Dừng khi 4 phase
trong draft; retry batch tối đa 1 lần.
使用脚本进行确定性检查:Phase 1 最终 gate(两个必需文件)、图谱 1.6 验证(不得有重复 ID、不得有悬空边、每个文件节点必须位于一个 layer、tour nodeIds 必须存在)、断言 STEP B 已替换所有
/
、在 Phase 4 末尾执行
。需要人工 review:layers/tour、domain graph(对照真实 file:line)、wiki 质量。当草稿中的 4 个 phase 均为
时停止;批次最多重试 1 次。
- Positive:
/orca-onboard ~/code/zca-bridge
trên repo 180 file, có opencode → draft + dispatch board in terminal → user "ok" → graph 180 node + 7 layer + tour 9 bước → 3 domain → wiki concepts/entities → llmwiki/html/onboarding-zca-bridge.html
+ ; draft 4 phase .
- Boundary/failure: trên repo chưa từng onboard → Phase 0 in "❌ --update requires existing graph. Run without --update first." và exit 1, không tạo draft.
- Boundary: opencode treo ở Phase 4 STEP A → Claude tự viết theo schema skeleton rồi chạy STEP B; không viết HTML thô.
- 正向: 对包含 180 个文件且已安装 opencode 的 repo 执行
/orca-onboard ~/code/zca-bridge
→ 在终端输出草稿 + 调度面板 → 用户回复“ok”→ 生成包含 180 个节点的图谱 + 7 个 layer + 9 步导览 → 包含 3 个 domain → wiki concepts/entities → llmwiki/html/onboarding-zca-bridge.html
+ ;草稿中的 4 个 phase 均为 。
- 边界/失败: 对从未执行过上手流程的 repo 使用 → Phase 0 输出“❌ --update requires existing graph. Run without --update first.”并以状态码 1 退出,不创建草稿。
- 边界: Phase 4 STEP A 中 opencode 挂起 → Claude 自行根据 skeleton schema 编写 ,然后运行 STEP B;不直接编写原始 HTML。