[aside] PR #296 で tag 提案に入れた `LIFECYCLE_TAGS = {open,wip,done,closed,low}` の denylist が、lifecycle tag 語彙の single source of truth と切れている。

新規 `web/src/tag-suggest.ts` は「性質タグだけ提案・状態タグは除外」のため `open/wip/done/closed/low` をハードコードした集合で弾く。だがこの語彙は CLAUDE.md § タグライフサイクルの散文にあるだけで、コード側に共有の定数が無い(SPA の `tag-tree.ts` / `App.tsx` の tag 処理も lifecycle を中央管理していない)。

触らない判断: #296 は機能追加が本題で、語彙の SoT 化は別軸(共有 constants に置くか / projection から引くか / CLAUDE.md から生成するか の設計判断を伴う)。

想定インパクト: 将来 lifecycle tag を 1 個増やす(例 `blocked`)と、この denylist が silent に drift し、新状態タグが「性質タグ」として提案に混じる。トリガー = lifecycle tag 語彙を追加 / 変更するとき、または lifecycle を知る箇所が 3 つ目を超えたとき。