Kanban worker lanes
worker lane은 kanban dispatcher가 task를 route할 수 있는 process class입니다. 각 lane에는 identity(assignee string), spawn mechanism, 그리고 spawn된 뒤 task를 어떻게 처리해야 하는지에 대한 contract가 있습니다.
이 페이지는 그 contract입니다. 두 독자를 위해 존재합니다.
- Operator - board에 어떤 lane을 연결할지 선택하는 사람. 어떤 profile을 만들고 어떤 assignee를 사용할지 결정합니다.
- Plugin / integration author - 새로운 lane shape를 추가하려는 사람. 예: Codex / Claude Code / OpenCode를 감싼 CLI worker, containerized review worker, API로 task를 pull하는 non-Hermes service.
worker code 자체, 즉 lane 안에서 실행되는 agent를 작성한다면 kanban-worker skill에 더 자세한 절차가 있습니다.
hierarchy
Hermes Kanban = canonical task lifecycle + audit trail
Worker lane = implementation executor for one assigned card
Reviewer = human or human-proxy that gates "done"
GitHub PR = upstreamable artifact (optional, for code lanes)
Hermes Kanban은 lifecycle truth를 소유합니다. ready → running → blocked / done / archived 흐름입니다. worker lane은 작업을 실행하지만 이 truth를 소유하지 않습니다. worker가 하는 모든 일은 kanban_* tool을 통해 kanban kernel로 되돌아갑니다. non-Hermes external worker의 경우 API를 통해 되돌아갑니다. reviewer는 "code change written"에서 "task done"으로 넘어가는 전환을 gate합니다.
lane이 제공해야 하는 것
kanban worker lane이 되려면 integration이 세 가지를 제공해야 합니다.
1. assignee string
dispatcher는 task.assignee를 Hermes profile name(default lane shape) 또는 registered non-spawnable identifier(plugin lane shape - 아래 Adding an external CLI worker lane 참고)와 match합니다. assignee가 resolve되지 않는 task는 skipped_nonspawnable event와 함께 ready에 남습니다. board operator가 고칠 수 있게 하기 위함이며, 조용히 drop되거나 임의 fallback으로 실행되지 않습니다.
2. spawn mechanism
Hermes profile lane의 경우 dispatcher의 _default_spawn은 task의 pinned workspace 안에서 hermes -p <assignee> chat -q <prompt>를 실행합니다. hermes shim이 $PATH에 없으면 동등한 module form을 사용합니다. 다음 env var가 설정됩니다.
| Variable | Carries |
|---|---|
HERMES_KANBAN_TASK | worker가 작업 중인 task id |
HERMES_KANBAN_DB | per-board SQLite file의 absolute path |
HERMES_KANBAN_BOARD | board slug |
HERMES_KANBAN_WORKSPACES_ROOT | board workspace tree의 root |
HERMES_KANBAN_WORKSPACE | 이 task workspace의 absolute path |
HERMES_KANBAN_RUN_ID | 현재 run id(lifecycle gate용) |
HERMES_KANBAN_CLAIM_LOCK | claim lock string(<host>:<pid>:<uuid>) |
HERMES_PROFILE | worker 자신의 profile name(kanban_comment author attribution용) |
HERMES_TENANT | task에 tenant가 있으면 tenant namespace |
plugin으로 등록된 non-Hermes lane의 경우 plugin이 자체 spawn_fn callable을 제공합니다. 이 callable은 task, workspace, board를 받고 crash detection에 사용할 optional pid를 반환합니다.
3. lifecycle terminator
모든 claim은 정확히 다음 중 하나로 끝나야 합니다.
kanban_complete(summary=..., metadata=...)- task 성공. status가done으로 바뀝니다.kanban_block(reason=...)- human input 대기. status가blocked로 바뀝니다.kanban_unblock이 실행되면 dispatcher가 다시 spawn합니다.- worker process가 tool call 없이 종료됨. kernel이 이를 reap하고
crashed(PID died),gave_up(consecutive-failure breaker tripped),timed_out(max_runtime exceeded)를 emit합니다. 이는 failure path입니다. healthy worker는 여기서 끝나지 않습니다.
kanban kernel은 각 run이 정확히 하나의 terminator로 끝나도록 강제합니다. 아무 terminator도 호출하지 않고 정상 종료한 worker는 crashed로 처리됩니다.
output과 review-required convention
대부분의 code-changing task는 worker가 끝났다고 해서 진짜 done이 아닙니다. human reviewer가 필요합니다. kanban kernel은 이 구분을 강제하지 않습니다. "code-changing task"의 경계가 모호하고, 모든 code worker에 block-instead-of-complete를 강제하면 review가 필요 없는 flow를 망가뜨릴 수 있기 때문입니다. 대신 위에 얹는 convention이 있습니다.
- complete 대신 block하고,
reason앞에review-required:를 붙입니다. dashboard /hermes kanban show가 해당 row를 review 대기 상태로 보여 줍니다. kanban_block은 human-readablereason만 담으므로, 먼저kanban_comment에 structured metadata를 남깁니다. comment는 durable annotation channel입니다. audit에 중요한 field(changed_files, tests_run, diff_path 또는 PR url, decision)는 모두 여기에 들어가야 합니다.- reviewer는 approve 후 unblock하여 comment thread를 포함한 follow-up worker를 respawn하거나, 다른 comment로 change request를 남깁니다. 다음 worker run은
kanban_showcontext에서 이를 봅니다.
kanban-worker skill에는 kanban_complete(typo fix, docs change, research writeup처럼 진짜 terminal task)와 review-required block pattern의 worked example이 있습니다.
log와 audit trail
dispatcher는 task별 worker stdout/stderr를 <board-root>/logs/<task_id>.log에 씁니다. log는 kanban metadata에서 audit할 수 있습니다.
task_runsrow에는log_path, exit code(가능한 경우), summary, metadata가 들어갑니다.task_eventsrow에는 모든 state transition(promoted,claimed,heartbeat,completed,blocked,gave_up,crashed,timed_out,reclaimed,claim_extended)이 들어갑니다.kanban_show는 둘 다 반환하므로 reviewer나 follow-up worker는 dashboard access 없이도 전체 history를 읽을 수 있습니다.
dashboard는 run history를 summary, metadata block, exit-status badge와 함께 render합니다. CLI 사용자는 hermes kanban tail <task_id>로 live log를 따라가거나, hermes kanban runs <task_id>로 historical attempt list를 볼 수 있습니다.
기존 lane shape
Hermes profile lane(default)
현재 모든 kanban worker가 취하는 shape입니다. assignee는 profile name이고, dispatcher는 hermes -p <profile>을 spawn합니다. worker는 kanban-worker skill과 KANBAN_GUIDANCE system-prompt block을 자동 load하고, kanban_* tool로 run을 terminate합니다. profile을 정의하는 것 외에는 별도 setup이 필요 없습니다.
fleet용 profile을 만들 때는 orchestrator가 route하길 원하는 role과 맞는 이름을 고르세요. orchestrator가 있다면 hermes profile list로 profile name을 discover합니다. system이 가정하는 fixed roster는 없습니다. orchestrator 쪽 contract는 kanban-orchestrator skill을 참고하세요.
Orchestrator profile lane
profile lane의 specialization입니다. orchestrator는 toolset에 kanban은 포함하지만 implementation용 terminal / file / code / web은 제외한 Hermes profile입니다. orchestrator의 역할은 high-level goal을 kanban_create + kanban_link로 child task로 분해한 뒤 물러나는 것입니다. orchestrator skill은 직접 구현하고 싶은 유혹을 막는 규칙을 encoding합니다.
Adding an external CLI worker lane
non-Hermes CLI tool(Codex CLI, Claude Code CLI, OpenCode CLI, local coding-model runner 등)을 kanban worker lane으로 연결하는 것은 아직 paved path가 아닙니다. dispatcher의 spawn function은 pluggable입니다. spawn_fn은 dispatch_once parameter이며, plugin이 non-Hermes assignee용 자체 spawn_fn을 등록할 수 있습니다. 하지만 그 주변 integration 작업, 즉 CLI exit code를 kanban_complete / kanban_block call로 감싸는 일, CLI workspace/sandbox convention을 dispatcher의 HERMES_KANBAN_WORKSPACE env에 맞추는 일, auth와 CLI별 policy를 처리하는 일은 아직 integration별 설계가 필요합니다.
CLI lane 추가를 고려 중이라면, 어떤 CLI와 어떤 workflow를 활성화하려는지 issue를 열어 설명해 주세요. 위 contract는 그런 lane이 만족해야 할 제약입니다. implementation shape(각 CLI마다 plugin 하나 vs config로 parameterize되는 generic CLI-runner plugin)는 열려 있습니다.
이와 관련된 historical issue는 #19931이며, merge되지 않고 닫힌 Codex-specific PR은 #19924입니다. 두 링크는 원래 architecture proposal을 설명하지만 runner로 merge되지는 않았습니다.
dispatcher가 처리하는 failure mode
lane author가 다시 구현하지 않아도 되는 것들입니다.
- Stale claim TTL - claim한 뒤 heartbeat / complete / block을 전혀 하지 않는 worker는
DEFAULT_CLAIM_TTL_SECONDS(기본 15분) 후 reclaimed됩니다. 단, worker process가 실제로 죽은 경우에만 그렇습니다. 살아 있는 worker(느린 model이 tool-free LLM call 하나에 20분 이상 쓰는 경우)는 죽이는 대신 claim이 extended됩니다. dead PID만 reclaimed됩니다. - Crashed worker - host-local PID가 사라진 worker는
detect_crashed_workers로 감지되어 reap됩니다. task는consecutive_failures를 증가시키며 breaker가 trip되면 auto-block될 수 있습니다. - Run-level retry - task가 retry될 때(post-block, post-crash, post-reclaim), worker는 terminating tool의
expected_run_idparameter를 사용해 자신의 run이 이미 supersede되었으면 fail fast할 수 있습니다. - Per-task max runtime -
task.max_runtime_seconds는 PID liveness와 관계없이 run별 wall-clock time을 hard-cap합니다. live-PID extension 때문에 계속 실행될 수 있는 진짜 deadlock worker를 잡습니다. - Stranded-task detection - ready task의 assignee가
kanban.stranded_threshold_seconds(기본 30분) 안에 claim을 만들지 않으면hermes kanban diagnostics에stranded_in_readywarning으로 나타납니다. threshold의 2배에서 error, 6배에서 critical로 severity가 올라갑니다. 오타가 난 assignee, 삭제된 profile, 내려간 external worker pool을 하나의 signal로 잡습니다. identity-agnostic이며 board별 allowlist를 관리할 필요가 없습니다.
관련 문서
- Kanban overview - user-facing intro
- Kanban tutorial - dashboard를 열어 놓고 따라가는 walkthrough
kanban-worker- worker process가 load하는 skillkanban-orchestrator- orchestrator 쪽 contract