Skip to content

feat(layout): topological row assignment from task dependencies - #17

Merged
sousuke0422 merged 5 commits into
masterfrom
feat/topological-assign-rows
Jul 14, 2026
Merged

feat(layout): topological row assignment from task dependencies#17
sousuke0422 merged 5 commits into
masterfrom
feat/topological-assign-rows

Conversation

@sousuke0422

Copy link
Copy Markdown
Contributor

概要

SPEC の P2 未実装項目「依存関係を考慮したトポロジカル行割り当て」を Rust core に実装する。

これまで layout::assign_rows はタスク配列の順序をそのまま行番号にしていた(row = i)ため、GanttDep を無視しており、blocker(先行タスク)が blocked(後続)より下に来ることがあった。本 PR で依存トポロジ順(blocker を上、blocked を下)に並べ替える。

変更内容

  • crates/koyori-arc-core/src/layout.rsassign_rows を deps 考慮のトポロジカル順序へ。Kahn 法でソートし、blocker_task_id(先行)を小さい row(上)へ割り当てる。呼び出し側が deps を渡せるようシグネチャを更新。
  • crates/koyori-arc-core/src/display_list/build.rs — 呼び出し元を新シグネチャに追随。

設計上の不変条件

  • 決定性: 同一入力 → byte 完全一致の出力。同一トポロジ階層内の tie-break は元の入力配列順で固定(HashMap 走査順を出力順に混入させない)。SVG が byte 不変である前提(golden fixture / DOM 仮想化)を壊さない。
  • サイクル安全: task_relations は循環しうる。panic / 無限ループを起こさず、循環ノードは Kahn 処理後に入力順で決定的に割り当て、全タスクを必ず 1 行ずつ配置する(欠落・重複なし)。
  • 頑健性: tasks に存在しない id を参照する dep は無視する。

スコープ

本 PR は「1 タスク = 1 行のトポロジ順序」に限定する。時間ベースの行パッキング(時間的に重ならないタスクを同一行に詰める)は SPEC の将来課題として温存する。

テスト

layout.rs に variant 網羅の回帰テストを追加(deps 無し = 入力順維持 / 単純 blocker→blocked / 鎖 A→B→C / ダイヤモンド / 非連結タスクの安定順序 / 循環 = panic せず決定的 / 未知 id dep 無視 / 空入力 / 決定性)。

  • cargo nextest run: 72 passed
  • wasm-pack test --node: 13 passed

※ DRAFT 解除・merge は maintainer 判断。

Assisted-by: multi-agent-shogun-aki-tweak

Replace sequential row=i layout with Kahn topological ordering so
blockers render above blocked tasks. Deterministic tie-break uses input
array order; cycles and unknown dependency IDs are handled safely.

Assisted-by: Cursor <cursor@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Assisted-by: multi-agent-shogun-aki-tweak
@chromatic-com

chromatic-com Bot commented Jul 14, 2026

Copy link
Copy Markdown

Important

Testing in progress…

🟢 UI Tests: 5 tests unchanged
UI Review: Comparing 5 stories…
Storybook icon Storybook Publish: 5 stories published

@chromatic-com

chromatic-com Bot commented Jul 14, 2026

Copy link
Copy Markdown

Tip

All tests passed and all changes approved!

🟢 UI Tests: 5 tests unchanged
🟢 UI Review: 5 stories published -- no changes
Storybook icon Storybook Publish: 5 stories published

sousuke0422 and others added 4 commits July 14, 2026 21:02
assign_rows now returns one entry per input task (fixing bar/arrow zip
mismatch in build.rs) and uses Tarjan SCC condensation so downstream
tasks stay below cycle blockers. Add integration tests for reversed
input and cycle+downstream graphs.

Assisted-by: Cursor <cursor@cursor.com>
Assisted-by: multi-agent-shogun-aki-tweak
Replace SCC-level priority topological sort with DFS clustering so dependents
emit immediately after all blockers (acceptance: [t1,t3,t2]→rows [0,2,1]).

Assisted-by: multi-agent-shogun-aki-tweak
Replace linear Vec::find id resolution with HashMap for O(V+E) edge
construction. Replace recursive try_emit_dependent_sccs with an explicit
stack that preserves byte-identical clustering order. Add regression tests
for 10k chains and 5000_dense timing.

Co-authored-by: Cursor <cursoragent@cursor.com>
Assisted-by: multi-agent-shogun-aki-tweak
Replace O(V²) predecessor scans in drain_dependent_sccs with
remaining_indegree decrements on emit. Add join fixture (2k blockers
→ sink) guarding linear-time fan-in. Output order unchanged.

Co-authored-by: Cursor <cursoragent@cursor.com>
Assisted-by: multi-agent-shogun-aki-tweak
@sousuke0422
sousuke0422 merged commit 17b5221 into master Jul 14, 2026
6 checks passed
@sousuke0422
sousuke0422 deleted the feat/topological-assign-rows branch July 14, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant