← Về thư mục
📄 / / root / .hermes / skills / operate / kanban-bootstrap / SKILL.md

name: kanban-bootstrap description: Set up, restructure, and maintain Hermes Kanban boards following company IT-BA standards — board naming, task hierarchy, dependency linking, and running the lightweight kanban web viewer. trigger: | Trigger when: - User asks to create a kanban board or restructure existing tasks - User asks to set up task hierarchy or fix broken hierarchies - User asks about dependency linking or parent-child relationships - The kanban web viewer (port 9120) needs to be started, restarted, or debugged - User complains about "board stands alone" or "hierarchy doesn't make sense"


Kanban Bootstrap

Board Naming Convention

Task ID & Hierarchy Convention

Task IDs follow hierarchical dot-notation. The parent is the Project/Phase, children are its sub-tasks:

Correct Wrong
Parent: IT.04 ... Parent: IT.02 ... (wrong number)
Child: IT.04.01 [IT.03] ... Child: IT.03 ... (flat, no hierarchy)
Child: IT.04.02 [IT.09] ... Child: IT.09 ... (flat, no hierarchy)

Key rules: - Hierarchy is expressed in the title string, NOT through hermes kanban link - The [original_ID] in brackets links back to the Lark Task Hub ID for cross-reference - The dot-notation (IT.04 → IT.04.01) makes parent-child visible at a glance in any Kanban view

This is the #1 pitfall in Hermes Kanban. Understand this clearly:

hermes kanban link <predecessor_id> <successor_id> means:

"successor task cannot start until predecessor task is completed (status=done)"

When you link A→B: - B is automatically forced to todo status - B stays todo until A is set to done - When A is marked done, B auto-promotes to ready

The Circular Deadlock Trap

If you link every child to an umbrella parent, ALL children get stuck in todo forever: - Child needs parent → child in todo - Parent has children → parent can't complete until children are done - → Deadlock: nothing can ever complete

Correct usage

✅ GOOD: link only REAL execution dependencies
  IT.04.02 [IT.09] CEO chốt thread ID
    ↓ LINK ──────────────→  IT.04.04 [IT.04] handoff.py MAPPING
    ↓ LINK ──────────────→  IT.04.05 [IT.05] Telegram thread IDs
  IT.04.04 [IT.04] handoff.py MAPPING
    ↓ LINK ──────────────→  IT.04.06 [IT.06] handoff-task skill

✅ ALSO GOOD: independent tasks with NO links
  IT.04.01 [IT.03] Lark options     → stays ready (no blockers)
  IT.04.03 [IT.08] SOP handoff      → stays ready (no blockers)

❌ WRONG: link children to umbrella parent
  IT.04 (umbrella) ──link──→ IT.04.01  ← ALL children stuck in todo!
❌ WRONG: link everything to everything

Umbrella container pattern

For umbrella/project container tasks: 1. Create the task normally 2. Set it to running (not todo/ready) via hermes kanban claim <id> 3. Do NOT link children to it 4. It sits in "In Progress" as a visual grouping header

Hermes Profiles — Department-Level Worker Routing

Each department needs its own Hermes profile so the dispatcher can auto-route tasks to the correct worker. Without profiles, all tasks are unassigned and skipped by the dispatcher.

Profile creation

# 1. Create profile (auto-creates wrapper script ~/.local/bin/<name>)
hermes profile create <dept-name>

# 2. Copy API keys from default profile (or run <profile> setup)
cp ~/.hermes/.env ~/.hermes/profiles/<dept-name>/.env

# 3. Set description — CRITICAL for dispatcher routing
hermes profile describe <dept-name> --text "<department role description>"

Profile descriptions (dispatcher routing signal)

The description is what the dispatcher uses to decide which profile should claim which task. Be specific about what work this profile handles:

hermes profile describe r-and-d --text "R&D — policy research, literature review, data analysis, academic/regulatory research tasks."

Assigning tasks to profiles

# After creating a task, assign it to the right profile:
hermes kanban assign <task_id> <profile_name>

# Dispatch — spawns worker for the assigned profile:
hermes kanban dispatch
# Output: "Spawned: 1 - t_xxxx -> <profile> @ /path/to/workspace"

Profile list for NV-Office company

Profile Purpose Thread
it-ai IT & AI — infra, automation, devops 18
r-and-d R&D — policy, data analysis 12
str-mkt Strategy & Marketing 14
writers Copywriting, translation, content 1591
grill-qa QA, testing, validation 20

Mandatory: --assignee flag on task creation

Tasks created WITHOUT --assignee get null/unassigned — the dispatcher SKIPS them. Every task MUST have an owner profile:

# ✅ CORRECT — dispatcher picks it up
/opt/ai-os/products/ceo/scripts/create_task.sh "Task Name" --assignee <profile_name>

# ❌ WRONG — becomes "unassigned", dispatcher skips
hermes kanban create "Task Name"

Wrapper script at /opt/ai-os/products/ceo/scripts/create_task.sh enforces this by rejecting creates without --assignee. Always use this script.

Profile routing via describe --text (NOT per-profile SOUL.md)

⚠️ KEY CORRECTION (2026-07-12): Hermes only reads ONE global SOUL.md (~/.hermes/SOUL.md). Per-profile SOUL.md files (~/.hermes/profiles/<name>/SOUL.md) are NOT supported — the engine silently ignores them. Do NOT create per-profile SOUL.md files.

Instead, use hermes profile describe <name> --text "<description>" to define each department's focus and style. This description is what the dispatcher reads to route tasks to the right profile:

hermes profile describe it-ai --text "IT & AI: code, devops, automation, kanban pipeline, system maintenance."
hermes profile describe r-and-d --text "R&D / Policy Lab: policy research, macroeconomics, literature review, APA 7th."
hermes profile describe str-mkt --text "Strategy & Marketing: market strategy, campaigns, SEO, competitor analysis, brand."
hermes profile describe writers --text "Writers / Content: copywriting, translation, editorial, SEO-optimized content."
hermes profile describe grill-qa --text "Grill & QA: testing, bug hunting, cross-review, stress-test, quality assurance."

Layered identity architecture (bottom to top, all compose additively): | Layer | Scope | Mechanism | |:------|:------|:----------| | SOUL.md | Whole instance | ~/.hermes/SOUL.md — identity, style, guardrails for ALL profiles | | Profile Description | Per department | hermes profile describe <name> --text "..." — routing/dispatcher signal | | AGENTS.md | Per project repo | ./AGENTS.md — project-specific conventions | | /personality | Per session | /personality pirate — temporary roleplay override |

None of these layers override another — they all compose additively into the system prompt.

Ex vs Sup — không cần 2 profile cho 1 phòng

Cách sai: Tạo it-ai-exit-ai-sup riêng biệt → 10 profile cho 5 phòng. Cách đúng (Story 3): Dùng pipeline link để review qua profile khác:

Task A (it-ai: implement) ──link──→ Task B (grill-qa: review)
                                     Task C (str-mkt: approve)

Profile executor IMPLEMENT → complete. Profile reviewer (grill-qa) REVIEW trước khi thực hiện bàn giao. Pipeline link làm nhiệm vụ phân luồng.

Parallel Multi-Agent Execution (Story 5 & 6)

Khi nhận yêu cầu chạy song song các khối công việc lớn thuộc các chuyên môn khác nhau (ví dụ: IT nâng cấp dashboard và R&D hệ thống hóa tri thức): 1. Phân tách task có cấu trúc: Tạo cây task rõ ràng với sequence ID tương ứng từng phòng ban (IT.KBN.01RD.BRN.01). 2. Gán Assignee chuẩn xác: Bắt buộc truyền tham số assignee khớp với keys trong config/departments.json ngay khi tạo task để tránh task bị bỏ quên (unassigned). 3. Dispatch Subagents song song: Sử dụng công cụ delegate_task để spawn các sub-agents với vai trò riêng biệt (IT Agent và R&D Agent), cung cấp context chuyên biệt chứa các Task ID tương ứng để tránh bị chồng chéo ngữ cảnh. Các sub-agents chạy độc lập trong background và tự cập nhật trạng thái Kanban của mình.

Pipeline & Auto-promotion

When tasks are chained via kanban link, the auto-promotion mechanism makes the workflow fully automatic: - When task A completes with --result, the dispatcher promotes linked task B from todoready. - CRITICAL: For HUMAN-in-the-loop review, do NOT link B directly. Instead, create a separate task for review.

Human-in-the-Loop Review Pipeline (2026-07-12)

If a task output requires CEO approval (e.g., ingest results, master files):

  1. Step 1: Create TASK.01 (Execution) and TASK.01.RV (Review).
  2. Step 2: Link TASK.01.RV -> TASK.02 (Next step).
  3. Step 3: Task TASK.01 completes -> Set status to blocked + kind=needs_input.
  4. Step 4: CEO reviews file, then manually unblocks TASK.01.
  5. Step 5: Dispatcher auto-promotes TASK.01.RV to ready, then proceeds to TASK.02.

NEVER manually create duplicate tasks named 'Review' to replace statuses. Use standard status transitions (blocked -> unblock).

Fixing Status / Column Issues

If a task shows as ready but needs human review: - CLI: hermes kanban block <task_id> --kind needs_input --reason "Review needed at <URL>" - Effect: CLI status becomes blocked and moves to the "Blocked" column automatically. Gateway avoids auto-promoting tasks with block_kind=needs_input.

Process flow

# 1. Link tasks in execution order
hermes kanban link t_IT01_part1 t_IT01_part2    # part1 → part2

# 2. When part1 completes with --result + --metadata
hermes kanban complete t_IT01_part1 \
  --result "Summary of work done" \
  --metadata '{"files": ["/path/to/output"]}'

# 3. Dispatch promotes part2 from todo → ready automatically
hermes kanban dispatch
# Output: Promoted: 1 - t_IT01_part2 (was todo, now ready)

# 4. When worker claims part2 and calls kanban context
hermes kanban context t_IT01_part2
# → Shows parent's summary + metadata in worker_context

Hermes Gateway (Dispatcher nền)

Để hệ thống tự động dispatch và spawn các worker chạy ngầm mà không cần con người chạy CLI thủ công:

# Khởi chạy gateway nền
hermes gateway start

Heartbeat & Real-time Progress

Để dashboard hiển thị tiến độ thời gian thực, trong code worker phải chèn:

# Cập nhật tiến độ giữa chừng (không cần kết thúc task)
kanban_heartbeat(note="Đang chạy bước 2/3: Cấu hình database...")

Metadata Schema chuẩn (Bắt buộc)

Khi gọi kanban_complete, bắt buộc dùng schema metadata để Agent sau kế thừa:

kanban_complete(
    summary="Tóm tắt công việc đã xong",
    metadata={
        "changed_files": ["path/file1", "path/file2"],
        "decisions": ["quyết định 1", "quyết định 2"],
        "duration_seconds": 120,
        "status": "completed"
    }
)

Worker context passing

This is the key mechanism that replaces manual handoff messages:

Retry flow (Story 4)

# When worker needs human input:
hermes kanban block <task_id>
hermes kanban comment <task_id> "BLOCKER: reason"

# Human unblocks:
hermes kanban unblock <task_id>

# Dispatcher re-promotes to ready, new worker spawns
hermes kanban dispatch
# → Second run reads block reason from prior run's events

Setup Steps (full workflow)

Phase A: Reset/Clean board

# Delete old board entirely (if starting fresh)
hermes kanban boards rm <slug> --delete
# Or clear tasks from within the board
python3 -c "import sqlite3; c=sqlite3.connect('/root/.hermes/kanban/boards/<slug>/kanban.db'); c.execute('DELETE FROM tasks'); c.commit()"

Phase B: Create board structure

# 1. Create board (general workspace name)
hermes kanban boards create nv-office --name "NV-Office"

# 2. Switch to it
hermes kanban boards switch nv-office

# 3. Create umbrella (parent) task -- running state
umbrella=$(hermes kanban create 'IT.04 Dự án Tái cấu trúc Vận hành Nova (Phase 1)' \
  --body 'Project Dossier: projects/IT.04.md' \
  --assignee default --priority 0 --json)
umbrella_id=$(echo "$umbrella" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
hermes kanban claim "$umbrella_id"

Phase C: Create child tasks with hierarchical IDs

# Independent (no deps) -- immediately ready
hermes kanban create 'IT.04.01 [IT.03] Cập nhật department options trên Lark Task Hub' --assignee default --priority 1

# Dependent on CEO chốt -- link later
t09=$(hermes kanban create 'IT.04.02 [IT.09] Xác nhận thread ID R&D (cần CEO chốt)' --assignee default --priority 1 --json)
t09_id=$(echo "$t09" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")

# ... create remaining tasks, then link REAL deps only
hermes kanban link "$t09_id" "$t04_id"   # CEO chốt → handoff.py
hermes kanban link "$t09_id" "$t05_id"   # CEO chốt → Telegram

Phase D: Verify

hermes kanban list
# Expected: umbrella=running, independent=ready, dep-blocked=todo/blocked

Kanban Web Viewer & File Browser

A lightweight HTTP server that reads the Hermes SQLite DB directly and serves a Kanban column UI, bypassing the Dashboard's Host Header and Basic Auth issues. It also serves as a file browser and Markdown viewer.

Files

File Purpose
kanban_server.py Python HTTP server, reads kanban.db, serves HTML+JSON, and static files

Nginx Reverse Proxy Architecture

To avoid "Invalid Host header" errors from the official Hermes Dashboard while exposing both it and the custom Kanban OS via Tailscale Funnel: 1. Run Nginx listening on 127.0.0.1:9121. 2. Configure Nginx to rewrite the Host header to 127.0.0.1:9119 before proxying to the official dashboard (proxy_set_header Host 127.0.0.1:9119;). 3. Map /kanban-os/ to proxy to the custom Python server (proxy_pass http://127.0.0.1:9120/;). 4. Map /files/ to proxy to the custom Python server (proxy_pass http://127.0.0.1:9120/files/;). 5. Run Tailscale Funnel pointing ONLY to the Nginx port: tailscale funnel --bg 9121.

This allows a single Tailscale URL to serve: - / -> Official Hermes Dashboard (header bypass applied) - /kanban-os/ -> Custom Kanban web viewer - /files/ -> Custom file browser & Markdown renderer

Note: You may need to inject a navigation bar into the official dashboard using Nginx's sub_filter module so users can switch between them.

Usage

# Kill existing if port is stuck
lsof -ti:9120 | xargs -r kill -9

# Start fresh (background)
python3 /opt/ai-os/products/ceo/kanban_server.py

Configuration

Kỹ thuật triển khai & Troubleshooting Kanban Server

Task Lifecycle

Edit kanban_server.py and update the columns dict in the embedded JavaScript:

const columns = {"ready":"Ready","todo":"To do","running":"In progress","blocked":"Blocked","done":"Done"};

Task Lifecycle

Hermes Status Kanban Column Meaning CLI Command
ready Ready Available for dispatch; no blockers Default on create
todo To do Waiting on dependency (auto-linked) Auto when parent-linked
running In Progress Claimed by a worker hermes kanban claim <id>
blocked Blocked Needs human input hermes kanban block <id> --reason "..."
done Done Completed hermes kanban complete <id> --result "..."

Pitfalls

  1. Circular deadlock: Never link all children to an umbrella parent. Only link REAL execution deps.
  2. Board named after project: Resist naming boards after projects. Use general workspace names.
  3. Flat task IDs: All tasks on the same level with no hierarchy (IT.03, IT.04, IT.09). Always use parent.Child notation.
  4. Address already in use (port 9120): The kanban server dies and the port lingers. Always kill first (lsof -ti:9120 | xargs -r kill -9).
  5. --assignee bắt buộc: Task không có --assignee sẽ bị null — dispatcher skip. Dùng wrapper script /opt/ai-os/products/ceo/scripts/create_task.sh để enforce. Không gọi hermes kanban create trực tiếp.
  6. Swimlanes chỉ hoạt động khi data có assignee: Nếu nhiều task unassigned, swimlane view sẽ khó đọc. Luôn set assignee.
  7. Parent-child deadlock: hermes kanban link tạo HARD dep — child bị khoá cho đến khi parent done. KHÔNG link umbrella với children. Hierarchy chỉ qua dot-notation tên task.
  8. Duplicate/Broken JavaScript functions on Web Server: Khi override hoặc viết thêm tính năng JS render trên Web Server (ví dụ renderCardHtml), tránh định nghĩa trùng lặp hàm làm hàm cũ bị ghi đè không mong muốn và trả về undefined.
  9. Đầu ra HTML rỗng / Cự tuyệt gửi body: Khi viết custom response trong Python HTTP server, luôn đảm bảo thứ tự: send_response -> send_header -> end_headers -> wfile.write. Gọi status code trước khi khai báo header sai cách có thể gây lỗi stream và trả về trang trắng (HTTP 200 rỗng).
  10. Trùng tên biến và Module trong Python: Không đặt tên biến chứa HTML local trùng với module html đã import (ví dụ html = "..."), gây ra lỗi runtime cannot access local variable 'html' where it is not associated with a value khi các module con gọi html.escape. Nên dùng tên riêng biệt như board_html hoặc html_page.
  11. Lỗi Path Traversal Security (Symlinks): Khi map route /files/ tới /root mà dự án lại nằm ở /opt/... (được liên kết bằng Symlink ceo-project), Python os.path.realpath sẽ giải nén symlink ra path vật lý thực tế. Cần cấu hình whitelist bảo mật cho cả thư mục symlink đích (/opt/ai-os/products/ceo) để tránh bị server cự tuyệt trả về lỗi forbidden 403.
  12. Hermes Dashboard caches old data: After changing tasks via CLI, restart Dashboard to refresh its view: kill $(lsof -ti:9119) && hermes dashboard --port 9119 --host 127.0.0.1.
  13. Parent task set ready instead of running: Umbrella tasks should be running (claimed) so they sit in "In Progress" as active containers, not "Ready" where they look like they need dispatch.

Task Lifecycle

Hermes Status Kanban Column Meaning CLI Command
ready Ready Available for dispatch; no blockers Default on create
todo To do Waiting on dependency (auto-linked) Auto when parent-linked
running In Progress Claimed by a worker hermes kanban claim <id>
blocked Blocked Needs human input hermes kanban block <id> --reason "..."
done Done Completed hermes kanban complete <id> --result "..."