aizuchi 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * ボード差分 (新着インジケータ用) の純関数。
3
+ * SSE で再取得した前後のタスク一覧を比べ、「人間が見ていない間に変わったタスク」を割り出す。
4
+ * AI → 人間の「何が変わったか」を画面内シグナルとして太くするための補助情報で、
5
+ * これ自体は正本性を持たない (既読マーカーは localStorage に置く・origin 分断は許容)。
6
+ *
7
+ * 純粋・副作用なし。server/web の双方が型を共有できるよう新データ源・新依存はゼロ。
8
+ */
9
+ /**
10
+ * 前回スナップショット (prev) と最新 (next) を比べ、変化したタスクの id 集合を返す。
11
+ * - 新規 (prev に無い id) → newIds
12
+ * - updated が進んだ or status が変わった → updatedIds
13
+ * - 削除 (next に無い id) は無視する (消えたカードはハイライト対象にならない)
14
+ *
15
+ * updated は文字列比較ではなく時刻比較で「進んだ」を判定する (ISO 8601 の桁揃えに依存しない)。
16
+ * parse 不能な updated は文字列の不一致をもって変化とみなす (誤検知より取りこぼし回避を優先)。
17
+ */
18
+ export function diffBoards(prev, next) {
19
+ const prevById = new Map();
20
+ for (const task of prev) {
21
+ prevById.set(task.id, task);
22
+ }
23
+ const newIds = [];
24
+ const updatedIds = [];
25
+ for (const task of next) {
26
+ const before = prevById.get(task.id);
27
+ if (before === undefined) {
28
+ newIds.push(task.id);
29
+ continue;
30
+ }
31
+ if (task.status !== before.status || isNewer(task.updated, before.updated)) {
32
+ updatedIds.push(task.id);
33
+ }
34
+ }
35
+ return { newIds, updatedIds, changedIds: new Set([...newIds, ...updatedIds]) };
36
+ }
37
+ /**
38
+ * next の updated が prev の updated より「新しい」かを判定する。
39
+ * 両方 parse できれば時刻で比較。どちらかが parse 不能なら文字列の不一致を変化とみなす。
40
+ */
41
+ function isNewer(nextUpdated, prevUpdated) {
42
+ const nextMs = Date.parse(nextUpdated);
43
+ const prevMs = Date.parse(prevUpdated);
44
+ if (Number.isNaN(nextMs) || Number.isNaN(prevMs)) {
45
+ return nextUpdated !== prevUpdated;
46
+ }
47
+ return nextMs > prevMs;
48
+ }
@@ -3,15 +3,31 @@
3
3
  * PUT 競合 (409) 時にローカル編集とサーバー側内容の差分を提示するために使う。
4
4
  * 依存を追加せず ~50 行で実装する。server / web が共有する。
5
5
  */
6
+ /**
7
+ * LCS の DP 行列サイズ (aLines.length × bLines.length) の上限。これを超えたら DP を回さず
8
+ * フォールバックする (長大な作業ログを持つタスクで行 LCS が O(n×m) で重くなるのを避ける)。
9
+ */
10
+ export const DIFF_MAX_MATRIX = 250000;
6
11
  /**
7
12
  * 2 つのテキストを行単位で比較し、変更箇所を返す。
8
13
  * `equal` = 両方にある行、`remove` = a のみ (削除)、`add` = b のみ (追加)。
14
+ * 行数の積が DIFF_MAX_MATRIX を超える場合は DP を回さず、全体を「a 全削除 + b 全追加」の
15
+ * 1 つの変更ブロックとして返す (行単位の対応付けは諦める)。両 diff 利用箇所が恩恵を受ける。
9
16
  */
10
17
  export function diffLines(a, b) {
11
18
  const aLines = a.split('\n');
12
19
  const bLines = b.split('\n');
13
20
  const n = aLines.length;
14
21
  const m = bLines.length;
22
+ // サイズガード: DP 行列が大きすぎる場合は LCS を回さず粗いフォールバックを返す
23
+ if (n * m > DIFF_MAX_MATRIX) {
24
+ const result = [];
25
+ for (const text of aLines)
26
+ result.push({ op: 'remove', text });
27
+ for (const text of bLines)
28
+ result.push({ op: 'add', text });
29
+ return result;
30
+ }
15
31
  // LCS の長さ表 (動的計画法)。lcs[i][j] = aLines[i..], bLines[j..] の LCS 長
16
32
  const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
17
33
  for (let i = n - 1; i >= 0; i--) {
@@ -10,6 +10,8 @@ export const PRIORITIES = ['high', 'medium', 'low'];
10
10
  export const MEMBER_TYPES = ['human', 'ai'];
11
11
  // マイルストーンの状態 (Phase 2 波 II の新規スキーマ拡張)
12
12
  export const MILESTONE_STATUSES = ['planned', 'active', 'done'];
13
+ // UI 表示言語。web の i18n (LANGS) と config.language が共有する唯一の源
14
+ export const UI_LANGS = ['en', 'ja'];
13
15
  export const DEFAULT_PORT = 5151;
14
16
  /** overview モードの既定ポート (波 VII)。serve の 5151 と衝突しない値・1 箇所集約 */
15
17
  export const DEFAULT_OVERVIEW_PORT = 5152;
@@ -26,12 +28,17 @@ export const taskIdSchema = z
26
28
  // 1 行テキスト (title 等。改行を含むと行ベースの frontmatter 処理が壊れる)
27
29
  const singleLineString = z.string().min(1).regex(/^[^\r\n]+$/, '1 行で書く (改行不可)');
28
30
  export const memberSchema = z.object({
31
+ // スラッグ (タスクファイルの created_by / assignee に書かれる安定 ID)
29
32
  id: z.string().min(1),
33
+ // 表示名 (任意)。未指定は id を表示 (columns label と同じパターン)。表示名の変更は id に影響しない
34
+ label: z.string().min(1).optional(),
30
35
  type: z.enum(MEMBER_TYPES),
31
36
  });
32
37
  export const columnSchema = z.object({
33
38
  id: z.string().min(1),
34
- label: z.string().min(1),
39
+ // 表示名 (任意)。未指定ならビュー層が表示言語に応じた status 訳を出す。
40
+ // 指定した場合はカスタム名としてどの言語でも最優先で表示される (後方互換)
41
+ label: z.string().min(1).optional(),
35
42
  hideWhenEmpty: z.boolean().optional(),
36
43
  wipLimit: z.number().int().positive().optional(),
37
44
  });
@@ -57,6 +64,22 @@ export const taskTemplateSchema = z
57
64
  priority: z.enum(PRIORITIES).optional(),
58
65
  })
59
66
  .strict();
67
+ /**
68
+ * 保存済みビュー定義 (絞り込みプリセット)。よく使うボードの絞り込み (担当 / ラベル / 検索語 /
69
+ * status) を config に名前付きで保存し、ワンクリックで適用する。
70
+ * language と同じく config.json を正とする (localStorage は origin=port 単位で分断され git 同期もされない)。
71
+ * name は chip のラベル (必須)、query/label/assignee/statuses は適用する絞り込み値 (任意)。
72
+ * .strict で未知フィールドを拒否する (config の typo を可視化)。既定は空配列で後方互換。
73
+ */
74
+ export const savedViewSchema = z
75
+ .object({
76
+ name: z.string().min(1),
77
+ query: z.string().optional(),
78
+ label: z.string().optional(),
79
+ assignee: z.string().optional(),
80
+ statuses: z.array(z.enum(TASK_STATUSES)).optional(),
81
+ })
82
+ .strict();
60
83
  export const configSchema = z.object({
61
84
  projectName: z.string().min(1).default('project'),
62
85
  idPrefix: z
@@ -65,25 +88,40 @@ export const configSchema = z.object({
65
88
  .default('TASK'),
66
89
  port: z.number().int().min(1).max(65535).default(DEFAULT_PORT),
67
90
  aiTaskCreation: z.enum(['free', 'proposal']).default('free'),
91
+ // UI 表示言語 (任意)。localStorage は origin (port) 単位で分断されるため、ファイル側を正として言語を運ぶ。
92
+ // 未指定はクライアント既定 (localStorage → en) に任せる = 既存 config と後方互換
93
+ language: z.enum(UI_LANGS).optional(),
68
94
  members: z
69
95
  .array(memberSchema)
70
96
  .min(1)
97
+ // 既定 member はテンプレート (templates/config.json) と同じ汎用名 (公開物に実名を載せない方針)
71
98
  .default([
72
- { id: 'kurata', type: 'human' },
73
- { id: 'fujimaki', type: 'human' },
99
+ { id: 'member1', type: 'human' },
100
+ { id: 'member2', type: 'human' },
74
101
  { id: 'claude', type: 'ai' },
75
102
  { id: 'codex', type: 'ai' },
76
- ]),
103
+ ])
104
+ // id (スラッグ) はタスク参照の照合キーなので一意必須 (リネーム統合や手編集での重複混入を弾く)
105
+ .superRefine((members, ctx) => {
106
+ const seen = new Set();
107
+ for (const member of members) {
108
+ if (seen.has(member.id)) {
109
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: `member id が重複しています: ${member.id}` });
110
+ }
111
+ seen.add(member.id);
112
+ }
113
+ }),
114
+ // 既定カラムは label 無し = UI の表示言語に応じた status 訳で表示する
77
115
  columns: z
78
116
  .array(columnSchema)
79
117
  .min(1)
80
118
  .default([
81
- { id: 'proposed', label: '提案', hideWhenEmpty: true },
82
- { id: 'backlog', label: 'Backlog' },
83
- { id: 'todo', label: 'Todo' },
84
- { id: 'in_progress', label: 'In Progress', wipLimit: 2 },
85
- { id: 'pending', label: 'Pending' },
86
- { id: 'done', label: 'Done' },
119
+ { id: 'proposed', hideWhenEmpty: true },
120
+ { id: 'backlog' },
121
+ { id: 'todo' },
122
+ { id: 'in_progress', wipLimit: 2 },
123
+ { id: 'pending' },
124
+ { id: 'done' },
87
125
  ]),
88
126
  instructionTemplate: z
89
127
  .string()
@@ -99,8 +137,29 @@ export const configSchema = z.object({
99
137
  milestones: z.array(milestoneSchema).default([]),
100
138
  // タスクテンプレート定義 (波 VI)。既定は空 = 既存 config と後方互換 (テンプレート UI は非表示)
101
139
  taskTemplates: z.array(taskTemplateSchema).default([]),
140
+ // 保存済みビュー (絞り込みプリセット)。既定は空 = 既存 config と後方互換 (chip 非表示・N-6)。
141
+ // language と同じくファイル側を正とし、ポート差・案件横断で効き git 同期される (localStorage 不使用)
142
+ savedViews: z.array(savedViewSchema).default([]),
143
+ // ビュー切替タブの表示順 + 表示/非表示。順序付き {id, hidden?}。既定は空 = 既定順で全表示 (後方互換)。
144
+ // id は web 側の既定ビュー集合 (board/critical/...) と突き合わせ、未知 id は無視・未列挙の既定ビューは末尾表示。
145
+ views: z.array(z.object({ id: z.string().min(1), hidden: z.boolean().optional() })).default([]),
102
146
  // 関連資料ディレクトリ (波 VIII)。プロジェクトルートからの相対パス。既定は空 = 機能オフ (UI 非表示)
103
147
  docsDirs: z.array(z.string().min(1)).default([]),
148
+ // ごみ箱 (.kanban/.trash) の同 id あたり退避世代の保持件数。任意・後方互換 (未設定は DEFAULT_TRASH_KEEP)。
149
+ // 破壊的書込の直前に旧版を .trash へコピー退避し、この件数を超えた古い世代を刈り取る (誤上書きの安全網)
150
+ trashKeep: z.number().int().positive().optional(),
151
+ // 停滞アラート閾値 (静かなタスク検知)。status 別に「最後の作業ログから何日で停滞とみなすか」(単位: 日)。
152
+ // 任意・後方互換 (milestones/docsDirs 前例): 未設定でも DEFAULT_STALL_THRESHOLDS で動く (N-6)。
153
+ // partial なので個別 status だけ上書き可。done/archive は対象外なので持たない
154
+ stallThresholds: z
155
+ .object({
156
+ in_progress: z.number().int().positive(),
157
+ todo: z.number().int().positive(),
158
+ pending: z.number().int().positive(),
159
+ })
160
+ .strict()
161
+ .partial()
162
+ .optional(),
104
163
  });
105
164
  /** 既定 config を生成する (N-6: 設定ゼロでも既定値で動作する) */
106
165
  export function defaultConfig() {
@@ -318,6 +377,17 @@ export const rejectInputSchema = z
318
377
  reason: singleLineString,
319
378
  })
320
379
  .strict();
380
+ /**
381
+ * POST /api/tasks/:id/revise の入力 (やり直し依頼。done/in_progress/pending から todo へ戻す)。
382
+ * reason は任意・改行可 (差し戻しの説明が複数行になりうるため reject の 1 行制約とは別扱い)。
383
+ * baseMtimeMs があれば PATCH/PUT と同じ mtime 競合検知に乗る (N-3)。
384
+ */
385
+ export const reviseInputSchema = z
386
+ .object({
387
+ reason: z.string().max(2000).optional(),
388
+ baseMtimeMs: z.number().optional(),
389
+ })
390
+ .strict();
321
391
  // ---------------------------------------------------------------------------
322
392
  // AI 設定ファイル管理 (F-4) の境界型
323
393
  // ---------------------------------------------------------------------------
@@ -333,6 +403,8 @@ export const fileSaveInputSchema = z
333
403
  path: z.string().min(1),
334
404
  content: z.string(),
335
405
  baseMtimeMs: z.number(),
406
+ // 'global' = ~/.claude/skills,agents への保存 (省略 = プロジェクトローカル)。グローバルは UI で警告のうえ保存
407
+ scope: z.enum(['local', 'global']).optional(),
336
408
  })
337
409
  .strict();
338
410
  /** カタログ項目 (skill / agent の frontmatter name/description 抽出。F-4-4) */
@@ -361,6 +433,49 @@ export const commentInputSchema = z
361
433
  .strict();
362
434
  /** POST /api/tasks/:id/rename の入力 (重複 ID リネーム支援 F-6-5。空き番号へ採番し直す) */
363
435
  export const renameInputSchema = z.object({}).strict();
436
+ // ---------------------------------------------------------------------------
437
+ // ごみ箱 (.kanban/.trash) の境界型。破壊的書込の直前に旧版をコピー退避した一覧 + 復元
438
+ // ---------------------------------------------------------------------------
439
+ /** GET /api/trash の退避 1 件 (軽量メタ + プレビュー用本文。frontmatter parse 成功時のみ表示用 title) */
440
+ export const trashItemSchema = z.object({
441
+ /** 元タスク ID */
442
+ id: z.string().min(1),
443
+ /** 退避時刻のエポックミリ秒 (世代の識別子。restore の trashedAt に渡す) */
444
+ trashedAt: z.number().int().nonnegative(),
445
+ /** frontmatter が parse できれば title (壊れた退避では null) */
446
+ title: z.string().nullable(),
447
+ /** 退避時の status (frontmatter が zod 検証を通った時のみ。壊れた退避は null) */
448
+ status: z.enum(TASK_STATUSES).nullable(),
449
+ /** 退避内容の本文 (プレビュー用。frontmatter 以降。parse 不能なら全文) */
450
+ body: z.string(),
451
+ });
452
+ /** GET /api/trash の応答 (退避一覧。新しい退避が先頭) */
453
+ export const trashListResponseSchema = z.object({
454
+ items: z.array(trashItemSchema),
455
+ });
456
+ /**
457
+ * POST /api/tasks/:id/restore の入力 (ごみ箱からの復元)。
458
+ * trashedAt 省略時は当該 id の最新世代を復元する。空オブジェクト可 (最新復元)。
459
+ * overwrite が true なら tasks/<id>.md が既存でも上書き復元する (現行は退避してから上書き)。
460
+ * 未指定 / false なら既存時は 409 (上書きしない・unarchive と対称) のまま。
461
+ */
462
+ export const restoreInputSchema = z
463
+ .object({
464
+ trashedAt: z.number().int().nonnegative().optional(),
465
+ overwrite: z.boolean().optional(),
466
+ })
467
+ .strict();
468
+ /**
469
+ * POST /api/members/rename の入力 (member スラッグ変更 / 削除時の移譲)。
470
+ * 全タスクの created_by / assignee の from を to へ付け替える
471
+ */
472
+ export const memberRenameInputSchema = z
473
+ .object({
474
+ from: singleLineString,
475
+ to: singleLineString,
476
+ })
477
+ .strict()
478
+ .refine((v) => v.from !== v.to, { message: 'from と to が同じです' });
364
479
  /**
365
480
  * 新規タスクの本文テンプレート (要件 §5.3 のファイル例のセクション構成)。
366
481
  * HTTP ルート (app.ts) と AI 用 CLI (task-ops.ts) の起票が同じ本文を書くよう、唯一の定義をここに置く。
@@ -9,6 +9,121 @@ import { parseWorkLogLines } from './digest.js';
9
9
  import { TASK_STATUSES } from './schema.js';
10
10
  const MS_PER_DAY = 24 * 60 * 60 * 1000;
11
11
  const DEFAULT_MAX_BOTTLENECKS = 5;
12
+ /** 停滞アラートの対象ステータス (done/archive は対象外。能動的に進める必要がある 3 状態のみ) */
13
+ export const STALL_STATUSES = ['in_progress', 'todo', 'pending'];
14
+ /**
15
+ * 停滞アラートの既定閾値 (単位: 日)。設定ゼロでも動く既定値の唯一の集約点 (N-6・ハードコード回避)。
16
+ * in_progress は能動的に進行中のはずなので短く、todo は着手前で長め、pending は待ち中で中間。
17
+ */
18
+ export const DEFAULT_STALL_THRESHOLDS = {
19
+ in_progress: 2,
20
+ todo: 7,
21
+ pending: 5,
22
+ };
23
+ /**
24
+ * 「人の判断待ち」(status='pending' かつ blocked_type='decision') のタスクを抽出する純関数。
25
+ * AI が blocked_type=decision で pending にしても人間が気づけない問題への read-only 派生表示。
26
+ * ID 昇順 (数値を考慮した自然順) で返す。新データ源・新依存・API 追加はゼロ。
27
+ */
28
+ export function deriveDecisionWaits(tasks) {
29
+ return tasks
30
+ .filter((t) => t.status === 'pending' && t.blocked_type === 'decision')
31
+ .map((t) => ({
32
+ id: t.id,
33
+ title: t.title,
34
+ blocked_reason: t.blocked_reason,
35
+ assignee: t.assignee,
36
+ }))
37
+ .sort((a, b) => a.id.localeCompare(b.id, 'en', { numeric: true }));
38
+ }
39
+ /** status が停滞対象 (in_progress/todo/pending) かを型ガードで判定する */
40
+ function isStallStatus(status) {
41
+ return STALL_STATUSES.includes(status);
42
+ }
43
+ // `## 作業ログ` 見出し行の検出 (level 不問・前後空白許容)。見出し文言は §5.3 / CLAUDE.md テンプレートに準拠。
44
+ const WORKLOG_HEADING_RE = /^\s{0,3}#{1,6}\s+作業ログ\s*$/;
45
+ // 任意の Markdown 見出し行 (セクション境界の検出に使う)。
46
+ const ANY_HEADING_RE = /^\s{0,3}#{1,6}\s+/;
47
+ /**
48
+ * stats 用に「作業ログセクションだけ」を切り出す (digest は全セクションを拾う現挙動を維持し、本関数は使わない)。
49
+ * `## 作業ログ` 見出しがあればその配下〜次の見出し直前までを返す。見出しが無ければ本文全体を返す (後方互換)。
50
+ * 目的: `## やりとり` のコメント行 (`- HH:mm [member]` と同書式) を停滞・完了集計が拾わないようにする (R-review #3)。
51
+ */
52
+ function workLogBody(body) {
53
+ const lines = body.split('\n');
54
+ let start = -1;
55
+ for (let i = 0; i < lines.length; i++) {
56
+ if (WORKLOG_HEADING_RE.test(lines[i])) {
57
+ start = i + 1;
58
+ break;
59
+ }
60
+ }
61
+ if (start === -1)
62
+ return body; // 作業ログ見出しが無ければ全体 (テスト fixture や旧形式との後方互換)
63
+ const out = [];
64
+ for (let i = start; i < lines.length; i++) {
65
+ if (ANY_HEADING_RE.test(lines[i]))
66
+ break; // 次の見出し (## やりとり 等) でセクション終了
67
+ out.push(lines[i]);
68
+ }
69
+ return out.join('\n');
70
+ }
71
+ /**
72
+ * タスクの「最後の活動時刻」を決める (epoch ms と ISO 文字列)。
73
+ * 優先順位: (1) 作業ログセクションの「最も新しい」日時 → 無ければ (2) frontmatter.updated。
74
+ * 出現位置の末尾ではなく時刻最大で選ぶ (手編集での過去日付追記やバックフィルで誤判定しないため、R-review #2)。
75
+ * 作業ログ時刻は offset 無し (ローカル解釈)。updated は offset 付き絶対時刻 (deriveStats と同じ既知近似)。
76
+ * いずれも parse 不能なら null。
77
+ */
78
+ function lastActivity(task) {
79
+ const logs = parseWorkLogLines(workLogBody(task.body));
80
+ let best = null;
81
+ for (const log of logs) {
82
+ const iso = `${log.date}T${log.time}`;
83
+ const ms = Date.parse(iso);
84
+ if (Number.isNaN(ms))
85
+ continue;
86
+ if (best === null || ms > best.ms)
87
+ best = { ms, iso };
88
+ }
89
+ if (best !== null)
90
+ return best;
91
+ const ms = parseIsoMs(task.updated);
92
+ return ms === null ? null : { ms, iso: task.updated };
93
+ }
94
+ /**
95
+ * 「静かなタスク (停滞)」を検知する純関数 (既存ボトルネック = pending 滞留のみ とは直交)。
96
+ * in_progress/todo/pending のうち、最後の作業ログ (無ければ updated) からの経過日数が
97
+ * status 別閾値 (日) を超えたものを idleDays 降順 → ID 昇順で返す。done/archive は対象外。
98
+ *
99
+ * @param tasks 対象タスク (status 不問。内部で対象 status のみ評価する)
100
+ * @param now 現在時刻 (epoch ms)。経過日数の基準 (Date.now ハードコード禁止・テスト再現性)
101
+ * @param thresholds status 別閾値 (日)。未指定の status は DEFAULT_STALL_THRESHOLDS を使う (N-6)
102
+ */
103
+ export function findStalledTasks(tasks, now, thresholds = {}) {
104
+ const result = [];
105
+ for (const task of tasks) {
106
+ if (!isStallStatus(task.status))
107
+ continue; // done/backlog/proposed/archive は対象外
108
+ const activity = lastActivity(task);
109
+ if (activity === null)
110
+ continue; // 日時が parse 不能なら判定不可 (誤検知を避けスキップ)
111
+ const limitDays = thresholds[task.status] ?? DEFAULT_STALL_THRESHOLDS[task.status];
112
+ const idleMs = now - activity.ms;
113
+ // 閾値「超過」のみ停滞とみなす (ちょうど閾値ぴったりは含めない)
114
+ if (idleMs <= limitDays * MS_PER_DAY)
115
+ continue;
116
+ result.push({
117
+ id: task.id,
118
+ title: task.title,
119
+ status: task.status,
120
+ lastActivityIso: activity.iso,
121
+ idleDays: toDays(idleMs),
122
+ });
123
+ }
124
+ // 停滞が深い順 → 同率は ID 昇順 (自然順)
125
+ return result.sort((a, b) => b.idleDays - a.idleDays || a.id.localeCompare(b.id, 'en', { numeric: true }));
126
+ }
12
127
  // 完了記録の偽陽性を避けるための否定文脈ガード (R10-1)。これにヒットする行は完了記録とみなさない。
13
128
  // 例: 「未完了の項目」「完了予定を 7/1」「まだ done していない」「isn't finished」
14
129
  const COMPLETION_NEGATIVE_RE = /未完了|未完|完了予定|完了見込|完了せず|undone|not\s+(done|finished|closed)|n['’]t\s+(done|finished|closed)/i;
@@ -46,7 +161,8 @@ function isCompletionRecord(message) {
46
161
  * 非 JST ブラウザではサイクルタイムが offset 差ぶんずれる (JST 運用なら実害小)。
47
162
  */
48
163
  function completionMs(task) {
49
- const logs = parseWorkLogLines(task.body);
164
+ // `## やりとり` のコメント行に完了キーワードがあっても拾わないよう、作業ログセクションに限定する (R-review #3)
165
+ const logs = parseWorkLogLines(workLogBody(task.body));
50
166
  for (let i = logs.length - 1; i >= 0; i--) {
51
167
  if (isCompletionRecord(logs[i].message)) {
52
168
  const ms = Date.parse(`${logs[i].date}T${logs[i].time}`);
@@ -0,0 +1 @@
1
+ :root{--bg: #f7f7f8;--surface: #ffffff;--surface-alt: #f1f1f3;--border: #e6e6e9;--border-strong: #d8d8dd;--text: #1c1d22;--text-muted: #516079;--accent: #4f46e5;--accent-hover: #4338ca;--accent-active: #3730a3;--accent-soft: #eef2ff;--accent-subtle: #e0e7ff;--danger: #de350b;--danger-soft: #ffe9e3;--danger-strong: #ae2a00;--success: #00875a;--success-soft: #e3fcef;--warn-bg: #fffae6;--warn-border: #ffab00;--human: #00875a;--ai: #6554c0;--status-idle: #8e8e96;--priority-high: #de350b;--priority-medium: #ff991f;--priority-low: #6b778c;--blocked-decision: #6554c0;--blocked-external: #ff8b00;--blocked-dependency: #00a3bf;--priority-high-bg: #ffe9e3;--priority-high-fg: #ae2a00;--priority-medium-bg: #fff0d6;--priority-medium-fg: #974f00;--priority-low-bg: #ebecf0;--priority-low-fg: #42526e;--blocked-decision-bg: #e9e6f7;--blocked-decision-fg: #4a3aa3;--blocked-external-bg: #fff0d6;--blocked-external-fg: #974f00;--blocked-dependency-bg: #d6f4f9;--blocked-dependency-fg: #0b6b7d;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 24px;--space-6: 32px;--radius-sm: 4px;--radius-md: 8px;--radius-lg: 10px;--radius-pill: 9999px;--radius: var(--radius-md);--shadow-card: 0 1px 2px rgba(20, 20, 30, .06);--shadow-hover: 0 2px 8px rgba(20, 20, 30, .1), 0 0 0 1px var(--border);--shadow-lg: 0 12px 32px rgba(20, 20, 30, .2);--shadow-panel: -4px 0 16px rgba(20, 20, 30, .14);--overlay: rgba(20, 20, 30, .45);--fs-xs: 11px;--fs-sm: 12px;--fs-base: 14px;--fs-md: 15px;--fs-lg: 17px;--fs-xl: 20px;--fw-semibold: 600;--fw-bold: 700;--ease: cubic-bezier(.2, 0, 0, 1);--dur-fast: .12s;--dur: .16s;--focus-ring: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent);--focus-ring-tight: 0 0 0 2px var(--accent);font-family:-apple-system,BlinkMacSystemFont,Hiragino Kaku Gothic ProN,Noto Sans JP,Segoe UI,Roboto,sans-serif;color:var(--text)}*{box-sizing:border-box}html,body,#root{margin:0;height:100%}body{background:var(--bg);font-size:var(--fs-base);line-height:1.5}button{font-family:inherit;font-size:inherit;cursor:pointer;transition:background var(--dur-fast) var(--ease),box-shadow var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease),transform var(--dur-fast) var(--ease)}input,select,textarea{font-family:inherit;font-size:inherit}a{color:var(--accent)}:focus-visible{outline:none;box-shadow:var(--focus-ring);border-radius:var(--radius-sm)}@media(prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}._overlay_9olz3_1{position:fixed;top:0;right:0;bottom:0;left:0;background:var(--overlay);display:flex;align-items:center;justify-content:center;padding:24px;z-index:100}._dialog_9olz3_12{background:var(--surface);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);width:100%;max-width:460px;max-height:90vh;overflow-y:auto;padding:20px 22px}._dialogWide_9olz3_23{max-width:720px}._title_9olz3_27{margin:0 0 14px;font-size:var(--fs-xl)}._field_9olz3_32{display:flex;flex-direction:column;gap:4px;margin-bottom:14px}._label_9olz3_39{font-size:12px;font-weight:600;color:var(--text-muted)}._input_9olz3_45,._select_9olz3_46,._textarea_9olz3_47{border:1px solid var(--border);border-radius:var(--radius-sm);padding:7px 9px;width:100%}._input_9olz3_45:focus-visible,._select_9olz3_46:focus-visible,._textarea_9olz3_47:focus-visible{outline:none;box-shadow:var(--focus-ring-tight);border-color:var(--accent)}._textarea_9olz3_47{resize:vertical;min-height:90px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px}._actions_9olz3_69{display:flex;justify-content:flex-end;gap:8px;margin-top:16px}._btn_9olz3_76{border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:7px 14px;color:var(--text)}._btn_9olz3_76:hover{background:var(--surface-alt)}._btnPrimary_9olz3_88{background:var(--accent);border-color:var(--accent);color:#fff}._btnPrimary_9olz3_88:hover{background:var(--accent-hover)}._btnPrimary_9olz3_88:active{background:var(--accent-active);transform:translateY(1px)}._btnPrimary_9olz3_88:disabled{opacity:.5;cursor:not-allowed}._btnDanger_9olz3_108{background:var(--danger);border-color:var(--danger);color:#fff}._error_9olz3_114{color:var(--danger);font-size:12px;margin:0 0 12px}._view_13xsq_1{flex:1;display:flex;overflow:hidden}._list_13xsq_8{flex:0 0 clamp(180px,28vw,280px);display:flex;flex-direction:column;overflow:hidden;border-right:1px solid var(--border);background:var(--surface)}._search_13xsq_18{padding:12px 12px 8px;border-bottom:1px solid var(--border)}._searchInput_13xsq_23{width:100%;box-sizing:border-box;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-alt);color:var(--text);font-size:13px;padding:6px 8px}._searchInput_13xsq_23:focus-visible{outline:none;box-shadow:var(--focus-ring)}._listScroll_13xsq_39{flex:1;overflow-y:auto;padding:8px 12px 12px}._monthGroup_13xsq_45{margin-bottom:10px}._monthName_13xsq_49{display:block;font-size:12px;font-weight:700;color:var(--text-muted);padding:4px 6px}._taskList_13xsq_57{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}._taskBtn_13xsq_66{display:block;width:100%;text-align:left;border:none;background:transparent;color:var(--text);font-size:13px;padding:5px 6px;border-radius:var(--radius-sm);cursor:pointer;overflow:hidden;transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease)}._taskBtn_13xsq_66:hover{background:var(--surface-alt)}._taskBtn_13xsq_66:focus-visible{box-shadow:var(--focus-ring)}._taskBtnActive_13xsq_89{background:var(--accent-soft);color:var(--accent);font-weight:600}._taskBtnActive_13xsq_89:hover{background:var(--accent-soft)}._taskId_13xsq_99{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--text-muted)}._taskTitle_13xsq_105{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._detail_13xsq_113{flex:1;overflow-y:auto;padding:14px 18px;max-width:880px}._detailHeader_13xsq_120{display:flex;align-items:flex-start;gap:12px;margin-bottom:12px}._detailHeadText_13xsq_127{flex:1;min-width:0}._detailTitle_13xsq_132{font-size:16px;font-weight:700;margin:0 0 4px;word-break:break-word}._meta_13xsq_139{display:flex;flex-wrap:wrap;gap:6px 10px;font-size:11px;color:var(--text-muted);margin:0}._metaId_13xsq_148{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._labels_13xsq_152{display:inline-flex;flex-wrap:wrap;gap:4px}._label_13xsq_152{background:var(--surface-alt);border-radius:var(--radius-sm);padding:1px 6px}._restoreBtn_13xsq_164{flex:0 0 auto;border:none;background:var(--accent);color:#fff;font-size:13px;font-weight:600;padding:6px 12px;border-radius:var(--radius-sm);cursor:pointer;transition:background var(--dur-fast) var(--ease)}._restoreBtn_13xsq_164:hover:not(:disabled){background:var(--accent-hover)}._restoreBtn_13xsq_164:focus-visible{outline:none;box-shadow:var(--focus-ring)}._restoreBtn_13xsq_164:disabled{opacity:.5;cursor:default}._markdown_13xsq_191{font-size:14px;line-height:1.65;word-break:break-word}._markdown_13xsq_191 pre{background:var(--surface-alt);padding:10px 12px;border-radius:var(--radius);overflow-x:auto;font-size:12px}._markdown_13xsq_191 code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.92em}._muted_13xsq_210{color:var(--text-muted);font-size:13px}._error_13xsq_215{color:var(--danger);font-size:12px;margin:0 0 10px}._wrap_12hxw_1{display:flex;align-items:center;gap:6px}._track_12hxw_7{flex:1;height:6px;background:var(--surface-alt);border-radius:var(--radius-pill);overflow:hidden}._fill_12hxw_15{height:100%;background:var(--accent);border-radius:var(--radius-pill);transition:width var(--dur) var(--ease)}._fillComplete_12hxw_22{background:var(--success)}._label_12hxw_26{font-size:var(--fs-xs);color:var(--text-muted);white-space:nowrap}._card_i0no9_1{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-card);padding:10px 12px;display:flex;flex-direction:column;gap:var(--space-2);cursor:pointer;-webkit-user-select:none;user-select:none;transition:box-shadow var(--dur) var(--ease),border-color var(--dur) var(--ease),transform var(--dur) var(--ease)}._card_i0no9_1:hover{border-color:var(--accent-subtle);box-shadow:var(--shadow-hover);transform:translateY(-1px);cursor:grab}._card_i0no9_1:focus-visible{box-shadow:var(--focus-ring)}._card_i0no9_1._dragging_i0no9_29{opacity:.5;box-shadow:0 8px 20px #14141e3d;transform:rotate(1.5deg) scale(1.02)}._card_i0no9_1._inProgress_i0no9_35{border-left:3px solid var(--accent)}._card_i0no9_1._unread_i0no9_42{border-color:var(--accent-subtle);box-shadow:0 0 0 1px var(--accent-subtle),var(--shadow-card);animation:_unreadFade_i0no9_1 4s var(--ease) forwards}@keyframes _unreadFade_i0no9_1{0%{background:var(--accent-soft)}to{background:var(--surface)}}._card_i0no9_1._selected_i0no9_58{background:var(--accent-soft);border-color:var(--accent-subtle);box-shadow:0 0 0 2px var(--accent-subtle),var(--shadow-card)}._selectBox_i0no9_65{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:16px;height:16px;border:1.5px solid var(--text-muted);border-radius:var(--radius-sm);background:var(--surface);color:#fff;font-size:11px;line-height:1}._selectBox_i0no9_65._selectBoxOn_i0no9_80{border-color:var(--accent);background:var(--accent)}._unreadBadge_i0no9_86{display:inline-flex;align-items:center;gap:4px;font-size:10px;font-weight:700;color:var(--accent);background:var(--accent-soft);border-radius:var(--radius-pill);padding:1px 6px}._unreadDot_i0no9_98{width:6px;height:6px;border-radius:50%;background:var(--accent);flex-shrink:0}._topRow_i0no9_106{display:flex;justify-content:space-between;align-items:center;gap:6px}._id_i0no9_113{font-size:11px;font-weight:500;color:var(--text-muted);letter-spacing:.04em}._stalledBadge_i0no9_121{margin-left:auto;display:inline-flex;align-items:center;gap:4px;font-size:10px;font-weight:700;color:var(--blocked-external-fg);background:var(--blocked-external-bg);border-radius:var(--radius-pill);padding:1px 6px}._stalledDot_i0no9_134{width:6px;height:6px;border-radius:50%;background:var(--blocked-external-fg);flex-shrink:0}._priority_i0no9_142{font-size:10px;font-weight:700;text-transform:uppercase;padding:1px 6px;border-radius:var(--radius-pill)}._priorityhigh_i0no9_150{background:var(--priority-high-bg);color:var(--priority-high-fg)}._prioritymedium_i0no9_155{background:var(--priority-medium-bg);color:var(--priority-medium-fg)}._prioritylow_i0no9_160{background:var(--priority-low-bg);color:var(--priority-low-fg)}._title_i0no9_165{font-weight:var(--fw-bold);line-height:1.35;color:var(--text);word-break:break-word}._metaRow_i0no9_172{display:flex;flex-wrap:wrap;align-items:center;gap:6px}._assignee_i0no9_179{display:inline-flex;align-items:center;gap:4px;font-size:11px;color:var(--text-muted)}._memberDot_i0no9_187{width:8px;height:8px;border-radius:50%;flex-shrink:0}._memberhuman_i0no9_194{background:var(--human)}._memberai_i0no9_198{background:var(--ai)}._memberunknown_i0no9_202{background:var(--text-muted)}._labels_i0no9_206{display:flex;flex-wrap:wrap;gap:4px}._label_i0no9_206{font-size:var(--fs-xs);background:var(--surface-alt);color:var(--priority-low-fg);border-radius:var(--radius-sm);padding:0 5px}._elapsed_i0no9_220{font-size:11px;color:var(--text-muted);margin-left:auto}._elapsedStrong_i0no9_226{color:var(--accent);font-weight:600}._blocked_i0no9_231{display:flex;flex-direction:column;gap:3px;border-top:1px dashed var(--border);padding-top:5px}._blockedBadge_i0no9_239{align-self:flex-start;font-size:10px;font-weight:700;border-radius:var(--radius-sm);padding:1px 6px}._blockeddecision_i0no9_247{background:var(--blocked-decision-bg);color:var(--blocked-decision-fg)}._blockedexternal_i0no9_252{background:var(--blocked-external-bg);color:var(--blocked-external-fg)}._blockeddependency_i0no9_257{background:var(--blocked-dependency-bg);color:var(--blocked-dependency-fg)}._blockedReason_i0no9_262{font-size:11px;color:var(--text-muted);word-break:break-word}._proposalActions_i0no9_268{display:flex;gap:6px;justify-content:flex-end;border-top:1px dashed var(--border);padding-top:6px;cursor:default}._actionBtn_i0no9_277{font-size:11px;font-weight:600;border-radius:var(--radius-sm);padding:6px 12px;min-height:30px;border:1px solid var(--border);background:var(--surface);transition:transform var(--dur-fast) var(--ease)}._actionBtn_i0no9_277:active{transform:scale(.96)}._actionBtn_i0no9_277:focus-visible{box-shadow:var(--focus-ring)}._approveBtn_i0no9_296{background:var(--human);border-color:var(--human);color:#fff}._rejectBtn_i0no9_302{color:var(--danger);border-color:var(--danger);background:var(--surface)}._column_d1l7j_1{display:flex;flex-direction:column;min-width:248px;max-width:288px;flex:1 0 248px;background:var(--surface-alt);border:1px solid var(--border-strong);border-radius:var(--radius-md);max-height:calc(100vh - 200px)}._header_d1l7j_13{display:flex;align-items:center;justify-content:space-between;padding:12px 12px 8px;gap:var(--space-1)}._columnOver_d1l7j_22{outline:2px solid var(--danger);outline-offset:-2px}._headerOver_d1l7j_27 ._label_d1l7j_27{color:var(--danger)}._label_d1l7j_27{font-weight:var(--fw-semibold);font-size:var(--fs-sm);letter-spacing:.02em}._count_d1l7j_37{font-size:var(--fs-sm);color:var(--text-muted);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-pill);padding:0 8px}._countOver_d1l7j_46{color:#fff;background:var(--danger)}._list_d1l7j_51{display:flex;flex-direction:column;gap:8px;padding:4px 8px 12px;overflow-y:auto;min-height:24px}._over_d1l7j_60{background:var(--accent-soft);outline:2px dashed var(--accent);outline-offset:-2px;border-radius:var(--radius)}._empty_d1l7j_67{color:var(--text-muted);font-size:var(--fs-sm);text-align:center;display:flex;align-items:center;justify-content:center;min-height:var(--space-6);padding:var(--space-5) var(--space-2)}._filterBar_xll91_1{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-2);padding:var(--space-2) var(--space-4);border-bottom:1px solid var(--border);background:var(--surface)}._search_xll91_12{flex:0 1 280px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:6px 9px}._filterBar_xll91_1 select{border:1px solid var(--border);border-radius:var(--radius-sm);padding:6px var(--space-2);background:var(--surface)}._filterSpacer_xll91_26{flex:1}._archiveAllBtn_xll91_30{border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:6px var(--space-3)}._archiveAllBtn_xll91_30:hover{background:var(--surface-alt)}._selectModeBtn_xll91_42{border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:6px var(--space-3)}._selectModeBtn_xll91_42:hover{background:var(--surface-alt)}._selectModeBtn_xll91_42._selectModeBtnOn_xll91_53{background:var(--accent-soft);border-color:var(--accent-subtle);color:var(--accent-active);font-weight:var(--fw-semibold)}._selectBar_xll91_61{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-2);padding:var(--space-2) var(--space-4);border-bottom:1px solid var(--border);background:var(--accent-soft)}._selectCount_xll91_71{font-size:var(--fs-sm);font-weight:var(--fw-semibold);color:var(--accent-active)}._bulkCopyBtn_xll91_77{border:1px solid var(--accent);background:var(--accent);color:#fff;border-radius:var(--radius-sm);padding:var(--space-1) var(--space-3);font-size:var(--fs-sm)}._bulkCopyBtn_xll91_77:hover:not(:disabled){background:var(--accent-active)}._bulkCopyBtn_xll91_77:disabled{cursor:default;opacity:.5}._selectClearBtn_xll91_95{border:1px solid var(--border-strong);background:var(--surface);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-3);font-size:var(--fs-sm)}._selectClearBtn_xll91_95:hover:not(:disabled){background:var(--surface-alt)}._selectClearBtn_xll91_95:disabled{cursor:default;opacity:.5}._selectHint_xll91_112{font-size:var(--fs-sm);color:var(--text-muted)}._viewsBar_xll91_118{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-2);padding:var(--space-2) var(--space-4);border-bottom:1px solid var(--border);background:var(--surface)}._chip_xll91_128{display:inline-flex;align-items:center;border:1px solid var(--border-strong);border-radius:var(--radius-pill);background:var(--surface);overflow:hidden}._chipApply_xll91_137{border:none;background:transparent;padding:var(--space-1) var(--space-3);color:var(--text);font-size:var(--fs-sm)}._chipApply_xll91_137:hover{background:var(--surface-alt)}._chipActive_xll91_150{background:var(--accent-soft);color:var(--accent-active);font-weight:var(--fw-semibold)}._chipActive_xll91_150:hover{background:var(--accent-subtle)}._chipDelete_xll91_160{border:none;border-left:1px solid var(--border);background:transparent;padding:var(--space-1) var(--space-2);color:var(--text-muted);line-height:1}._chipDelete_xll91_160:hover:not(:disabled){background:var(--danger-soft);color:var(--danger-strong)}._chipDelete_xll91_160:disabled{cursor:default;opacity:.5}._saveViewBtn_xll91_179{border:1px dashed var(--border-strong);background:var(--surface);border-radius:var(--radius-pill);padding:var(--space-1) var(--space-3);color:var(--text-muted);font-size:var(--fs-sm)}._saveViewBtn_xll91_179:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}._saveViewBtn_xll91_179:disabled{cursor:default;opacity:.5}._saveViewForm_xll91_198{display:inline-flex;align-items:center;gap:var(--space-2)}._saveViewInput_xll91_204{border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-2);font-size:var(--fs-sm)}._saveViewConfirm_xll91_211,._saveViewCancel_xll91_212{border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-3);font-size:var(--fs-sm)}._saveViewConfirm_xll91_211:hover:not(:disabled),._saveViewCancel_xll91_212:hover{background:var(--surface-alt)}._saveViewConfirm_xll91_211:disabled{cursor:default;opacity:.5}._emptyBoard_xll91_231{display:flex;flex:1;align-items:flex-start;justify-content:center;padding:var(--space-6) var(--space-4);overflow-y:auto}._emptyCard_xll91_240{max-width:560px;width:100%;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface);padding:var(--space-5);box-shadow:var(--shadow-sm)}._emptyTitle_xll91_250{margin:0 0 var(--space-2);font-size:var(--fs-lg);font-weight:var(--fw-semibold)}._emptyLead_xll91_256{margin:0 0 var(--space-4);color:var(--text-muted);line-height:1.6}._emptyAddBtn_xll91_262{border:1px solid var(--accent);background:var(--accent);color:#fff;border-radius:var(--radius-sm);padding:var(--space-2) var(--space-4);font-size:var(--fs-sm);font-weight:var(--fw-semibold)}._emptyAddBtn_xll91_262:hover{background:var(--accent-active)}._emptyAi_xll91_276{margin-top:var(--space-5);padding-top:var(--space-4);border-top:1px solid var(--border)}._emptyAiNote_xll91_282{margin:0 0 var(--space-3);color:var(--text-muted);font-size:var(--fs-sm);line-height:1.6}._emptyCopyBtn_xll91_289{border:1px solid var(--border-strong);background:var(--surface);border-radius:var(--radius-sm);padding:var(--space-2) var(--space-3);font-size:var(--fs-sm)}._emptyCopyBtn_xll91_289:hover{background:var(--surface-alt)}._board_xll91_301{display:flex;gap:var(--space-3);padding:var(--space-2) var(--space-4) var(--space-4);overflow-x:auto;flex:1;align-items:stretch;cursor:grab}._board_xll91_301:after{content:"";flex:0 0 var(--space-4)}._overlay_dbkt0_1{position:fixed;top:0;right:0;bottom:0;left:0;background:var(--overlay);display:flex;align-items:flex-start;justify-content:center;padding:12vh 24px 24px;z-index:120}._palette_dbkt0_12{background:var(--surface);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);width:100%;max-width:560px;max-height:70vh;display:flex;flex-direction:column;overflow:hidden}._input_dbkt0_24{border:none;border-bottom:1px solid var(--border);padding:14px 16px;font-size:15px;width:100%;background:transparent;color:var(--text)}._input_dbkt0_24:focus-visible{border-bottom-color:var(--accent);box-shadow:inset 0 0 0 2px var(--accent)}._list_dbkt0_39{list-style:none;margin:0;padding:6px;overflow-y:auto}._option_dbkt0_46{padding:9px 12px;border-radius:6px;font-size:14px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._optionActive_dbkt0_56{background:var(--accent-soft);border-radius:var(--radius-sm)}._empty_dbkt0_61{color:var(--text-muted);padding:18px 16px;font-size:13px;margin:0}._view_ubr9h_2{flex:1;display:flex;flex-direction:column;overflow:hidden;min-height:0;padding:12px 16px 0}._toolbar_ubr9h_12{display:flex;align-items:center;gap:10px;margin-bottom:12px;flex:none}._cycleWarn_ubr9h_20{background:var(--warn-bg);border:1px solid var(--warn-border);border-radius:var(--radius);padding:8px 12px;margin-bottom:12px;font-size:13px;flex:none}._levels_ubr9h_2{display:flex;gap:var(--space-3);align-items:stretch;flex:1;overflow-x:auto;padding-bottom:var(--space-4);min-height:0}._level_ubr9h_2{display:flex;flex-direction:column;flex:0 0 248px;min-width:248px;max-width:288px;background:var(--surface-alt);border:1px solid var(--border-strong);border-radius:var(--radius-md);min-height:0}._levelCycle_ubr9h_55{border-color:var(--warn-border)}._levelHeader_ubr9h_60{display:flex;align-items:center;justify-content:space-between;gap:var(--space-1);padding:12px 12px 8px;flex:none}._levelLabel_ubr9h_69{font-weight:var(--fw-semibold);font-size:var(--fs-sm);letter-spacing:.02em}._levelCount_ubr9h_75{font-size:var(--fs-sm);color:var(--text-muted);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-pill);padding:0 8px}._levelList_ubr9h_85{display:flex;flex-direction:column;gap:8px;padding:4px 8px 12px;overflow-y:auto;flex:1;min-height:24px}._node_ubr9h_95{background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-card);padding:8px 10px;cursor:pointer;display:flex;flex-direction:column;gap:4px;transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}._node_ubr9h_95:hover{border-color:var(--accent-subtle);box-shadow:var(--shadow-hover)}._nodeCp_ubr9h_116{border-left-color:var(--accent);background:var(--accent-soft)}._nodeCycle_ubr9h_121{border-left-color:var(--danger);background:var(--warn-bg)}._statusproposed_ubr9h_127,._statusbacklog_ubr9h_130{border-left-color:var(--status-idle)}._statustodo_ubr9h_133{border-left-color:var(--text-muted)}._statusin_progress_ubr9h_136{border-left-color:var(--accent)}._statuspending_ubr9h_139{border-left-color:var(--priority-medium)}._nodeTop_ubr9h_143{display:flex;justify-content:space-between;gap:6px}._nodeId_ubr9h_149{font-size:11px;font-weight:700;color:var(--text-muted)}._cpTag_ubr9h_155{font-size:10px;font-weight:700;color:var(--accent)}._nodeTitle_ubr9h_161{font-weight:600;word-break:break-word}._deps_ubr9h_166{display:flex;flex-wrap:wrap;gap:4px;align-items:center}._depsLabel_ubr9h_173{font-size:10px;color:var(--text-muted)}._depChip_ubr9h_178{font-size:10px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:var(--surface-alt);border-radius:var(--radius-sm);padding:0 5px}._pendingBadge_ubr9h_186{align-self:flex-start;font-size:10px;font-weight:700;color:var(--priority-medium-fg);background:var(--priority-medium-bg);border-radius:var(--radius-sm);padding:1px 6px}._empty_ubr9h_196{color:var(--text-muted);padding:var(--space-6) var(--space-5);text-align:center;flex:1;display:flex;align-items:center;justify-content:center;min-height:var(--space-6)}._copyBtn_ubr9h_208{border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:var(--space-2) var(--space-3);color:var(--accent)}._copyBtn_ubr9h_208:hover{background:var(--accent-soft)}._copyBtn_ubr9h_208:focus-visible{box-shadow:var(--focus-ring)}._root_y75j1_1{position:relative;display:inline-flex}._badge_y75j1_6{display:inline-flex;align-items:center;gap:6px;border-radius:var(--radius-pill);padding:5px 12px;min-height:28px;box-sizing:border-box;font-size:12px;font-weight:var(--fw-semibold);border:1px solid var(--border);background:var(--surface);color:var(--text-muted);cursor:pointer;transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)}._badgeActive_y75j1_28{background:var(--accent-soft);color:var(--accent-active);border-color:var(--accent-subtle)}._badgeActive_y75j1_28:hover{border-color:var(--accent)}._badgeMuted_y75j1_39{opacity:.7}._badgeMuted_y75j1_39:hover{opacity:1}._badge_y75j1_6:focus-visible{box-shadow:var(--focus-ring-tight)}._badgeDot_y75j1_51{width:7px;height:7px;border-radius:50%;background:currentColor}._badgeMuted_y75j1_39 ._badgeDot_y75j1_51{background:var(--text-muted)}._popover_y75j1_62{position:absolute;top:calc(100% + 8px);right:0;z-index:50;width:min(360px,90vw);max-height:60vh;overflow-y:auto;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);padding:var(--space-3)}._popoverTitle_y75j1_77{margin:0 0 var(--space-2);font-size:13px;font-weight:var(--fw-bold);color:var(--text)}._empty_y75j1_84{margin:0;font-size:13px;color:var(--text-muted)}._list_y75j1_90{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--space-1)}._item_y75j1_99{display:flex;flex-direction:column;gap:3px;width:100%;text-align:left;border:1px solid transparent;border-radius:var(--radius-sm);background:transparent;padding:8px 10px;cursor:pointer;transition:background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)}._item_y75j1_99:hover{background:var(--surface-alt);border-color:var(--border)}._item_y75j1_99:focus-visible{box-shadow:var(--focus-ring-tight)}._itemHead_y75j1_124{display:flex;align-items:baseline;gap:6px}._itemId_y75j1_130{font-size:11px;font-weight:var(--fw-semibold);color:var(--accent-active);white-space:nowrap}._itemTitle_y75j1_137{font-size:13px;font-weight:var(--fw-semibold);color:var(--text)}._itemReason_y75j1_143{font-size:12px;color:var(--text)}._itemReasonMuted_y75j1_148{font-size:12px;color:var(--text-muted);font-style:italic}._itemAssignee_y75j1_154{font-size:11px;color:var(--text-muted)}._view_5mig8_1{flex:1;display:flex;overflow:hidden}._viewEmpty_5mig8_7{flex:1;overflow:auto;display:flex;align-items:center;justify-content:center;min-height:var(--space-6);padding:var(--space-5) var(--space-4) var(--space-6)}._sidebar_5mig8_19{flex:0 0 clamp(180px,28vw,280px);overflow-y:auto;border-right:1px solid var(--border);background:var(--surface);padding:12px}._sidebarTitle_5mig8_28{font-size:13px;font-weight:700;margin:0 0 8px}._navList_5mig8_34{list-style:none;margin:0;padding:0}._navBtn_5mig8_40{display:flex;justify-content:space-between;align-items:baseline;gap:8px;width:100%;text-align:left;border:none;background:transparent;color:var(--text);font-size:13px;padding:4px 6px;border-radius:var(--radius-sm);cursor:pointer;transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease);font-variant-numeric:tabular-nums}._navBtn_5mig8_40:hover{background:var(--surface-alt)}._navBtn_5mig8_40:focus-visible{outline:none;box-shadow:var(--focus-ring)}._navBtnActive_5mig8_67{background:var(--accent-soft);color:var(--accent);font-weight:600}._navCount_5mig8_73{font-size:11px;color:var(--text-muted)}._navBtnActive_5mig8_67 ._navCount_5mig8_73{color:inherit}._detail_5mig8_83{flex:1;overflow-y:auto;padding:14px 18px}._day_5mig8_89{margin-bottom:20px}._dayHeader_5mig8_93{display:flex;align-items:baseline;gap:10px;border-bottom:2px solid var(--border);padding-bottom:4px;margin-bottom:8px}._date_5mig8_102{font-size:15px;font-weight:700}._count_5mig8_107{font-size:12px;color:var(--text-muted)}._entry_5mig8_112{display:flex;gap:10px;align-items:baseline;padding:3px 0;font-size:13px}._time_5mig8_120{flex:0 0 auto;color:var(--text-muted);font-variant-numeric:tabular-nums;font-size:12px}._taskId_5mig8_127{flex:0 0 auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--text-muted)}._member_5mig8_134{flex:0 0 auto;display:inline-flex;align-items:center;gap:4px;font-weight:600}._memberDot_5mig8_142{width:7px;height:7px;border-radius:50%}._memberhuman_5mig8_148{background:var(--human)}._memberai_5mig8_152{background:var(--ai)}._memberunknown_5mig8_156{background:var(--text-muted)}._message_5mig8_160{word-break:break-word}._empty_5mig8_164{color:var(--text-muted);padding:var(--space-5);font-size:var(--fs-sm);text-align:center}._view_1746t_1{flex:1;display:flex;overflow:hidden}._tree_1746t_8{flex:0 0 clamp(180px,28vw,280px);overflow-y:auto;border-right:1px solid var(--border);background:var(--surface);padding:12px}._treeTitle_1746t_17{font-size:13px;font-weight:700;margin:0 0 8px}._treeRoot_1746t_23,._treeChildren_1746t_24{list-style:none;margin:0;padding:0}._treeChildren_1746t_24{padding-left:14px}._dirName_1746t_34{display:block;font-size:12px;font-weight:600;color:var(--text-muted);padding:4px 6px}._fileBtn_1746t_42{display:block;width:100%;text-align:left;border:none;background:transparent;color:var(--text);font-size:13px;padding:4px 6px;border-radius:var(--radius-sm);cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease)}._fileBtn_1746t_42:hover{background:var(--surface-alt)}._fileBtn_1746t_42:focus-visible{box-shadow:var(--focus-ring)}._fileBtnActive_1746t_67{background:var(--accent-soft);color:var(--accent);font-weight:600}._fileBtnActive_1746t_67:hover{background:var(--accent-soft)}._detail_1746t_78{flex:1;overflow-y:auto;padding:14px 18px;max-width:880px}._docPath_1746t_85{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--text-muted);margin:0 0 10px}._refs_1746t_92{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:10px 12px;margin-bottom:14px}._refsTitle_1746t_100{font-size:12px;font-weight:700;margin:0 0 6px}._refsList_1746t_106{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}._refBtn_1746t_115{width:100%;text-align:left;border:none;background:transparent;color:var(--text);font-size:13px;padding:4px 6px;border-radius:var(--radius-sm);cursor:pointer;display:flex;align-items:baseline;gap:6px;transition:background var(--dur-fast) var(--ease)}._refBtn_1746t_115:hover{background:var(--accent-soft)}._refBtn_1746t_115:focus-visible{box-shadow:var(--focus-ring)}._refId_1746t_139{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--text-muted);flex:0 0 auto}._refStatus_1746t_146{margin-left:auto;font-size:11px;color:var(--text-muted);flex:0 0 auto}._markdown_1746t_153{font-size:14px;line-height:1.65;word-break:break-word}._markdown_1746t_153 pre{background:var(--surface-alt);padding:10px 12px;border-radius:var(--radius);overflow-x:auto;font-size:12px}._markdown_1746t_153 code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.92em}._muted_1746t_172{color:var(--text-muted);font-size:13px}._broken_1746t_177{color:var(--danger);font-size:13px}._error_1746t_182{color:var(--danger);font-size:12px;margin:0 0 10px}._diff_1xtfr_1{border:1px solid var(--border);border-radius:var(--radius-sm);max-height:46vh;overflow:auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5;background:var(--surface)}._line_1xtfr_12{display:flex;white-space:pre-wrap;word-break:break-word;padding:0 8px}._sign_1xtfr_19{flex:0 0 16px;color:var(--text-muted);-webkit-user-select:none;user-select:none}._equal_1xtfr_25{color:var(--text)}._add_1xtfr_29{background:var(--success-soft);color:var(--success)}._remove_1xtfr_34{background:var(--danger-soft);color:var(--danger-strong)}._view_7aej0_1{flex:1;display:flex;min-height:0}._sidebar_7aej0_7{flex:0 0 clamp(180px,28vw,280px);border-right:1px solid var(--border);overflow-y:auto;padding:12px}._sectionTitle_7aej0_15{font-size:11px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.04em;margin:12px 0 4px}._fileItem_7aej0_24{display:block;width:100%;text-align:left;border:none;background:transparent;padding:4px 6px;border-radius:var(--radius-sm);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--text);cursor:pointer;transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease)}._fileItem_7aej0_24:hover{background:var(--accent-soft)}._fileItem_7aej0_24:focus-visible{box-shadow:var(--focus-ring)}._fileItemActive_7aej0_47,._fileItemActive_7aej0_47:hover{background:var(--accent-soft);color:var(--accent)}._tree_7aej0_53{font-size:12px}._treeDir_7aej0_57{font-weight:600;padding:3px 0;color:var(--text-muted)}._catalogItem_7aej0_63{padding:4px 0;font-size:12px}._catalogName_7aej0_68{font-weight:700}._catalogDesc_7aej0_72{color:var(--text-muted)}._catalogGroup_7aej0_77{font-size:12px}._catalogGroupSummary_7aej0_81{cursor:pointer;padding:4px 6px;font-weight:700;border-radius:var(--radius-sm);list-style-position:inside;-webkit-user-select:none;user-select:none}._catalogGroupSummary_7aej0_81:hover{background:var(--surface-alt)}._catalogGroupSummary_7aej0_81:focus-visible{box-shadow:var(--focus-ring)}._catalogCount_7aej0_98{color:var(--text-muted);font-weight:400;font-size:var(--fs-xs)}._catalogGroup_7aej0_77 ._fileItem_7aej0_24{padding-left:16px}._main_7aej0_109{flex:1;display:flex;flex-direction:column;min-width:0;padding:12px 16px}._mainHeader_7aej0_117{display:flex;align-items:center;gap:10px;margin-bottom:8px}._mainPath_7aej0_124{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:700;flex:1;word-break:break-all}._editor_7aej0_131{flex:1;min-height:320px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;line-height:1.6;resize:none}._notice_7aej0_143{background:var(--warn-bg);border:1px solid var(--warn-border);border-radius:var(--radius-sm);padding:6px 10px;font-size:12px;margin-top:8px}._confirmIntro_7aej0_153{color:var(--text-muted);font-size:13px;margin:0 0 12px}._globalBadge_7aej0_160{font-size:11px;font-weight:700;color:var(--blocked-external-fg);background:var(--blocked-external-bg);border-radius:var(--radius-sm);padding:1px 8px;margin-right:8px;white-space:nowrap}._globalWarn_7aej0_172{background:var(--warn-bg);border:1px solid var(--warn-border);border-radius:var(--radius-sm);padding:8px 12px;margin:0 0 12px;font-size:13px;font-weight:600}._footer_7aej0_182{display:flex;align-items:center;gap:10px;margin-top:8px}._error_7aej0_189{color:var(--danger);font-size:12px}._loadError_7aej0_195{color:var(--danger);font-size:12px;padding:4px 6px;margin-bottom:4px}._saved_7aej0_202{color:var(--human);font-size:12px}._btn_7aej0_207{border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:7px 14px;cursor:pointer;transition:background var(--dur-fast) var(--ease),border-color var(--dur-fast) var(--ease)}._btn_7aej0_207:hover{background:var(--accent-soft)}._btn_7aej0_207:focus-visible{box-shadow:var(--focus-ring)}._btnPrimary_7aej0_224{background:var(--accent);border-color:var(--accent);color:#fff}._btnPrimary_7aej0_224:hover{background:var(--accent-hover);border-color:var(--accent-hover)}._btnPrimary_7aej0_224:active{background:var(--accent-active);border-color:var(--accent-active)}._btnPrimary_7aej0_224:disabled{opacity:.5;cursor:not-allowed}._empty_7aej0_245{color:var(--text-muted);margin:auto}._view_xktx5_1{flex:1;display:flex;overflow:hidden}._viewEmpty_xktx5_7{flex:1;overflow:auto;display:flex;align-items:center;justify-content:center;min-height:var(--space-6);padding:var(--space-5) var(--space-4) var(--space-6)}._sidebar_xktx5_19{flex:0 0 clamp(180px,28vw,280px);overflow-y:auto;border-right:1px solid var(--border);background:var(--surface);padding:12px}._sidebarTitle_xktx5_28{font-size:13px;font-weight:700;margin:0 0 8px}._sidebarTitle_xktx5_28+._sidebarTitle_xktx5_28,._navList_xktx5_35+._sidebarTitle_xktx5_28,._sideEmpty_xktx5_36+._sidebarTitle_xktx5_28{margin-top:16px}._sideEmpty_xktx5_36{font-size:12px;color:var(--text-muted);margin:0}._navList_xktx5_35{list-style:none;margin:0;padding:0}._navBtn_xktx5_52{display:flex;justify-content:space-between;align-items:baseline;gap:8px;width:100%;text-align:left;border:none;background:transparent;color:var(--text);font-size:13px;padding:4px 6px;border-radius:var(--radius-sm);cursor:pointer}._navBtn_xktx5_52:hover{background:var(--surface-alt)}._navBtn_xktx5_52:focus-visible{box-shadow:var(--focus-ring)}._navBtnActive_xktx5_76{background:var(--accent-soft);color:var(--accent);font-weight:600}._navLabel_xktx5_82{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._navCount_xktx5_88{flex:0 0 auto;font-size:11px;color:var(--text-muted);font-variant-numeric:tabular-nums}._navBtnActive_xktx5_76 ._navCount_xktx5_88{color:inherit}._detail_xktx5_100{flex:1;overflow-y:auto;padding:14px 18px}._sectionTitle_xktx5_106{font-size:13px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.04em;margin:16px 0 8px}._histStatus_xktx5_115{margin-left:auto;flex:0 0 auto;font-size:11px;color:var(--text-muted)}._milestone_xktx5_122{display:flex;align-items:center;gap:12px;padding:10px 12px;border-left:3px solid var(--border);background:var(--surface)}._milestoneactive_xktx5_131{border-left-color:var(--accent)}._milestonedone_xktx5_135{border-left-color:var(--human)}._milestoneplanned_xktx5_139{border-left-color:var(--text-muted)}._msInfo_xktx5_143{flex:1;min-width:0}._msTitle_xktx5_148{font-weight:700}._msStatus_xktx5_152{font-size:11px;color:var(--text-muted)}._msProgress_xktx5_157{flex:0 0 180px}._month_xktx5_161{margin-bottom:16px}._monthHeader_xktx5_165{font-size:var(--fs-xl);font-weight:700;border-bottom:1px solid var(--border);padding-bottom:4px;margin-bottom:6px}._histEntry_xktx5_173{display:flex;gap:10px;padding:3px 0;font-size:13px;cursor:pointer}._histEntry_xktx5_173:hover{color:var(--accent)}._histId_xktx5_185{flex:0 0 auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--text-muted)}._histTitle_xktx5_192{font-weight:600;flex:0 0 auto}._histSummary_xktx5_197{color:var(--text-muted);word-break:break-word}._empty_xktx5_202{color:var(--text-muted);padding:var(--space-5);text-align:center}._section_1brv5_1{margin-bottom:18px}._sectionTitle_1brv5_5{font-size:12px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.04em;margin:0 0 8px}._modeBox_1brv5_14{background:var(--accent-soft);border:1px solid var(--accent);border-radius:var(--radius);padding:12px;margin-bottom:18px}._memberRow_1brv5_22{display:flex;gap:8px;align-items:center;margin-bottom:6px}._memberRow_1brv5_22 input,._memberRow_1brv5_22 select{border:1px solid var(--border);border-radius:var(--radius-sm);padding:5px 8px}._memberRow_1brv5_22 input:focus-visible,._memberRow_1brv5_22 select:focus-visible{box-shadow:var(--focus-ring)}._memberId_1brv5_41{flex:1}._removeBtn_1brv5_45{border:1px solid var(--border);background:var(--surface);color:var(--danger);border-radius:var(--radius-sm);padding:4px 10px}._removeBtn_1brv5_45:focus-visible{box-shadow:var(--focus-ring)}._addBtn_1brv5_57{border:1px dashed var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:5px 12px;color:var(--accent);margin-top:4px}._addBtn_1brv5_57:focus-visible{box-shadow:var(--focus-ring)}._colRow_1brv5_71{display:flex;gap:8px;align-items:center;margin-bottom:6px}._colRow_1brv5_71 input[type=text],._colRow_1brv5_71 input[type=number]{border:1px solid var(--border);border-radius:var(--radius-sm);padding:5px 8px}._colRow_1brv5_71 input:focus-visible{box-shadow:var(--focus-ring)}._colId_1brv5_89{flex:1;min-width:0}._viewName_1brv5_95{flex:1;min-width:0;font-size:var(--fs-sm)}._colWip_1brv5_101{flex:0 0 64px}._colCheck_1brv5_105{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--text-muted);white-space:nowrap}._moveBtn_1brv5_114{border:1px solid var(--border);background:var(--surface);color:var(--text-muted);border-radius:var(--radius-sm);padding:4px 8px;line-height:1}._moveBtn_1brv5_114:disabled{opacity:.4;cursor:default}._moveBtn_1brv5_114:focus-visible{box-shadow:var(--focus-ring)}._advanced_1brv5_132 summary{cursor:pointer;font-size:12px;font-weight:600;color:var(--text-muted);margin-bottom:8px}._jsonEditor_1brv5_140{width:100%;min-height:160px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:8px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;resize:vertical}._jsonEditor_1brv5_140:focus-visible{box-shadow:var(--focus-ring)}._saved_1brv5_155{color:var(--human);font-size:12px}._reloadBtn_1brv5_161{margin-left:6px;padding:2px 8px;font-size:12px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-alt);color:var(--text);cursor:pointer}._reloadBtn_1brv5_161:focus-visible{box-shadow:var(--focus-ring)}._migrateBox_1brv5_177{border:1px solid var(--border);border-left:3px solid var(--accent);border-radius:var(--radius);background:var(--surface-alt);padding:10px 12px;margin:12px 0}._migrateTitle_1brv5_186{font-size:13px;font-weight:700;margin:0 0 6px}._migrateItem_1brv5_192{font-size:13px;margin:4px 0;display:flex;align-items:center;gap:6px;flex-wrap:wrap}._migrateItem_1brv5_192 select{border:1px solid var(--border);border-radius:var(--radius-sm);padding:3px 6px;background:var(--surface)}._migrateItem_1brv5_192 select:focus-visible{box-shadow:var(--focus-ring)}._migrateActions_1brv5_212{display:flex;justify-content:flex-end;gap:8px;margin-top:8px}._view_1dkqw_1{flex:1;overflow:auto;padding:12px 16px 16px;display:grid;grid-template-columns:1fr 1fr;gap:var(--space-3);align-content:start}@media(max-width:1200px){._view_1dkqw_1{grid-template-columns:1fr}}._card_1dkqw_18{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-card);padding:12px 14px}._cardHead_1dkqw_26{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}._cardTitle_1dkqw_34{font-size:14px;font-weight:700;margin:0 0 10px}._cardHead_1dkqw_26 ._cardTitle_1dkqw_34{margin-bottom:0}._note_1dkqw_44{font-size:12px;color:var(--text-muted);margin:4px 0 10px;line-height:1.5}._metrics_1dkqw_52{display:flex;gap:var(--space-4);flex-wrap:wrap;align-items:flex-end}._metric_1dkqw_52{display:flex;flex-direction:column;gap:2px}._metricValue_1dkqw_65{font-size:26px;font-weight:700;font-variant-numeric:tabular-nums;line-height:1.1}._metricLabel_1dkqw_72,._metricSub_1dkqw_77{font-size:12px;color:var(--text-muted)}._toggle_1dkqw_83{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}._toggleBtn_1dkqw_90{border:none;background:var(--surface-alt);color:var(--text);font-size:12px;padding:4px 10px;cursor:pointer}._toggleBtn_1dkqw_90+._toggleBtn_1dkqw_90{border-left:1px solid var(--border)}._toggleActive_1dkqw_103{background:var(--accent);color:#fff}._chartWrap_1dkqw_109{margin-top:10px;overflow-x:auto}._chart_1dkqw_109{display:block;width:100%;max-height:160px;height:auto}._bar_1dkqw_121{fill:var(--accent)}._barCount_1dkqw_125{fill:var(--text-muted);font-size:10px;font-variant-numeric:tabular-nums}._barLabel_1dkqw_131{fill:var(--text-muted);font-size:9px;font-variant-numeric:tabular-nums}._table_1dkqw_138{width:100%;border-collapse:collapse;font-size:13px}._table_1dkqw_138 caption{text-align:left}._table_1dkqw_138 th,._table_1dkqw_138 td{text-align:left;padding:6px 8px;border-bottom:1px solid var(--border);vertical-align:top}._table_1dkqw_138 th{font-size:11px;color:var(--text-muted);font-weight:600}._table_1dkqw_138 td{font-variant-numeric:tabular-nums}._bId_1dkqw_166{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--text-muted)}._empty_1dkqw_172{color:var(--text-muted);padding:var(--space-6) var(--space-5);text-align:center;grid-column:1 / -1;display:flex;align-items:center;justify-content:center;min-height:var(--space-6)}._srOnly_1dkqw_186{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}._intro_u1sm3_1{color:var(--text-muted);margin:0 0 12px}._legend_u1sm3_8{display:flex;gap:14px;font-size:11px;color:var(--text-muted);margin:8px 0 0}._overlay_1tz57_1{position:fixed;top:0;right:0;bottom:0;left:0;background:var(--overlay);display:flex;justify-content:flex-end;z-index:90}._panel_1tz57_10{background:var(--surface);width:100%;max-width:640px;height:100%;display:flex;flex-direction:column;box-shadow:var(--shadow-panel)}._header_1tz57_20{display:flex;align-items:center;gap:10px;padding:14px 18px;border-bottom:1px solid var(--border)}._id_1tz57_28{font-size:12px;font-weight:700;color:var(--text-muted)}._title_1tz57_34{font-size:var(--fs-xl);font-weight:700;flex:1;word-break:break-word}._copyBtn_1tz57_41{border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:5px 10px;font-size:12px;color:var(--accent);white-space:nowrap}._copyBtn_1tz57_41:hover{background:var(--accent-soft)}._copyBtn_1tz57_41:focus-visible{box-shadow:var(--focus-ring)}._close_1tz57_59{border:none;background:transparent;font-size:20px;color:var(--text-muted);line-height:1;padding:4px 8px}._close_1tz57_59:hover{color:var(--text)}._tabs_1tz57_72{display:flex;gap:2px;padding:8px 18px 0;border-bottom:1px solid var(--border)}._tab_1tz57_72{border:none;background:transparent;padding:8px 14px;color:var(--text-muted);border-bottom:2px solid transparent;font-weight:600}._tab_1tz57_72:hover{color:var(--text)}._tab_1tz57_72:focus-visible{box-shadow:var(--focus-ring-tight)}._tabActive_1tz57_96{color:var(--accent);border-bottom-color:var(--accent)}._body_1tz57_101{flex:1;overflow-y:auto;padding:18px}._markdown_1tz57_107{line-height:1.7;word-break:break-word}._markdown_1tz57_107 h1,._markdown_1tz57_107 h2,._markdown_1tz57_107 h3{margin-top:1.2em}._markdown_1tz57_107 code{background:var(--surface-alt);border-radius:3px;padding:1px 4px;font-size:.9em}._markdown_1tz57_107 pre{background:var(--surface-alt);border-radius:var(--radius-sm);padding:10px;overflow-x:auto}._markdown_1tz57_107 table{border-collapse:collapse}._markdown_1tz57_107 th,._markdown_1tz57_107 td{border:1px solid var(--border);padding:4px 8px}._editor_1tz57_142{width:100%;min-height:360px;height:100%;border:1px solid var(--border);border-radius:var(--radius-sm);padding:10px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;line-height:1.6;resize:vertical}._timeline_1tz57_155{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}._entry_1tz57_164{display:flex;gap:10px;border-left:2px solid var(--border);padding-left:12px;position:relative}._entry_1tz57_164:before{content:"";position:absolute;left:-5px;top:4px;width:8px;height:8px;border-radius:50%;background:var(--accent)}._entryMeta_1tz57_183{flex:0 0 auto;font-size:11px;color:var(--text-muted);min-width:120px}._entryMember_1tz57_190{font-weight:700;color:var(--text)}._entryMessage_1tz57_195{word-break:break-word}._emptyTimeline_1tz57_199{color:var(--text-muted);font-size:13px}._footer_1tz57_204{display:flex;align-items:center;gap:10px;padding:12px 18px;border-top:1px solid var(--border)}._dirty_1tz57_212{color:var(--priority-medium-fg);font-size:12px}._error_1tz57_217{color:var(--danger);font-size:12px;flex:1}._spacer_1tz57_223{flex:1}._btn_1tz57_227{border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:7px 14px}._btn_1tz57_227:hover{background:var(--surface-alt)}._btn_1tz57_227:focus-visible{box-shadow:var(--focus-ring)}._btnPrimary_1tz57_242{background:var(--accent);border-color:var(--accent);color:#fff}._btnPrimary_1tz57_242:disabled{opacity:.5;cursor:not-allowed}._commentInput_1tz57_253{display:flex;gap:8px;align-items:center;margin-top:12px;border-top:1px solid var(--border);padding-top:12px}._commentInput_1tz57_253 select{border:1px solid var(--border);border-radius:var(--radius-sm);padding:6px 8px}._commentField_1tz57_268{flex:1;border:1px solid var(--border);border-radius:var(--radius-sm);padding:6px 9px}._docsHint_1tz57_276{font-size:12px;color:var(--text-muted);background:var(--warn-bg);border:1px solid var(--warn-border);border-radius:var(--radius-sm);padding:6px 10px;margin:0 0 10px}._docsList_1tz57_286{list-style:none;margin:0 0 10px;padding:0;display:flex;flex-direction:column;gap:2px}._docRow_1tz57_295{display:flex;align-items:center;gap:8px}._docLink_1tz57_301{flex:1;text-align:left;border:none;background:transparent;color:var(--accent);padding:5px 6px;border-radius:var(--radius-sm);font-size:13px;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._docLink_1tz57_301:hover{background:var(--surface-alt)}._docLink_1tz57_301:focus-visible{box-shadow:var(--focus-ring)}._docLinkActive_1tz57_324{background:var(--accent-soft)}._docBroken_1tz57_328{font-size:11px;color:var(--danger);border:1px solid var(--danger);border-radius:var(--radius-sm);padding:1px 6px;flex:0 0 auto}._docRemove_1tz57_337{border:1px solid var(--border);background:var(--surface);border-radius:var(--radius-sm);padding:2px 8px;color:var(--text-muted);cursor:pointer;flex:0 0 auto}._docRemove_1tz57_337:focus-visible{box-shadow:var(--focus-ring)}._docRemove_1tz57_337:disabled{opacity:.4;cursor:not-allowed}._docsActions_1tz57_356{margin:4px 0 10px}._docsPicker_1tz57_360{border:1px solid var(--border);border-radius:var(--radius);padding:8px 10px;margin-bottom:12px;max-height:200px;overflow-y:auto;background:var(--surface-alt)}._docsPreview_1tz57_370{border-top:2px solid var(--border);padding-top:10px}._docsPreviewPath_1tz57_375{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--text-muted);margin:0 0 8px}._view_ctpdr_1{flex:1;display:flex;overflow:hidden}._list_ctpdr_8{flex:0 0 clamp(180px,28vw,280px);display:flex;flex-direction:column;overflow:hidden;border-right:1px solid var(--border);background:var(--surface)}._search_ctpdr_18{padding:12px 12px 8px;border-bottom:1px solid var(--border)}._searchInput_ctpdr_23{width:100%;box-sizing:border-box;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-alt);color:var(--text);font-size:13px;padding:6px 8px}._searchInput_ctpdr_23:focus-visible{outline:none;box-shadow:var(--focus-ring)}._listScroll_ctpdr_39{flex:1;overflow-y:auto;padding:8px 12px 12px}._taskList_ctpdr_45{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}._taskBtn_ctpdr_54{display:block;width:100%;text-align:left;border:none;background:transparent;color:var(--text);font-size:13px;padding:5px 6px;border-radius:var(--radius-sm);cursor:pointer;overflow:hidden;transition:background var(--dur-fast) var(--ease),color var(--dur-fast) var(--ease)}._taskBtn_ctpdr_54:hover{background:var(--surface-alt)}._taskBtn_ctpdr_54:focus-visible{box-shadow:var(--focus-ring)}._taskBtnActive_ctpdr_77{background:var(--accent-soft);color:var(--accent);font-weight:600}._taskBtnActive_ctpdr_77:hover{background:var(--accent-soft)}._taskId_ctpdr_87{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--text-muted)}._taskTitle_ctpdr_93{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._taskTime_ctpdr_100{display:block;font-size:10px;color:var(--text-muted)}._detail_ctpdr_107{flex:1;overflow-y:auto;padding:14px 18px;max-width:880px}._detailHeader_ctpdr_114{display:flex;align-items:flex-start;gap:12px;margin-bottom:12px}._detailHeadText_ctpdr_121{flex:1;min-width:0}._detailTitle_ctpdr_126{font-size:16px;font-weight:700;margin:0 0 4px;word-break:break-word}._meta_ctpdr_133{display:flex;flex-wrap:wrap;gap:6px 10px;font-size:11px;color:var(--text-muted);margin:0}._metaId_ctpdr_142{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._restoreBtn_ctpdr_146{flex:0 0 auto;border:none;background:var(--accent);color:#fff;font-size:13px;font-weight:600;padding:6px 12px;border-radius:var(--radius-sm);cursor:pointer;transition:background var(--dur-fast) var(--ease)}._restoreBtn_ctpdr_146:hover:not(:disabled){background:var(--accent-hover)}._restoreBtn_ctpdr_146:focus-visible{outline:none;box-shadow:var(--focus-ring)}._restoreBtn_ctpdr_146:disabled{opacity:.5;cursor:default}._diffWrap_ctpdr_174{margin-bottom:14px}._diffTitle_ctpdr_178,._previewTitle_ctpdr_179{font-size:12px;font-weight:700;margin:0 0 6px}._previewTitle_ctpdr_179{margin-top:14px}._diff_ctpdr_174{border:1px solid var(--border);border-radius:var(--radius-sm);max-height:40vh;overflow:auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.5;background:var(--surface)}._line_ctpdr_200{display:flex;white-space:pre-wrap;word-break:break-word;padding:0 8px}._sign_ctpdr_207{flex:0 0 16px;color:var(--text-muted);-webkit-user-select:none;user-select:none}._equal_ctpdr_213{color:var(--text)}._add_ctpdr_217{background:var(--success-soft);color:var(--success)}._remove_ctpdr_222{background:var(--danger-soft);color:var(--danger-strong)}._legend_ctpdr_227{display:flex;gap:14px;font-size:11px;color:var(--text-muted);margin:8px 0 0}._markdown_ctpdr_235{font-size:14px;line-height:1.65;word-break:break-word}._markdown_ctpdr_235 pre{background:var(--surface-alt);padding:10px 12px;border-radius:var(--radius);overflow-x:auto;font-size:12px}._markdown_ctpdr_235 code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.92em}._muted_ctpdr_254{color:var(--text-muted);font-size:13px}._error_ctpdr_259{color:var(--danger);font-size:12px;margin:0 0 10px}._banner_1uu1k_1{background:var(--warn-bg);border:1px solid var(--warn-border);border-radius:var(--radius);margin:0 16px 12px;padding:8px 12px}._summary_1uu1k_9{display:flex;align-items:center;gap:8px;cursor:pointer;font-weight:600;list-style:none}._summary_1uu1k_9::-webkit-details-marker{display:none}._icon_1uu1k_22{font-size:15px}._list_1uu1k_26{margin:8px 0 0;padding-left:20px;display:flex;flex-direction:column;gap:4px;font-size:13px}._item_1uu1k_35{color:var(--text)}._kind_1uu1k_39{display:inline-block;font-size:10px;font-weight:700;text-transform:uppercase;border-radius:var(--radius-sm);padding:0 5px;margin-right:6px;background:var(--warn-border);color:#fff}._path_1uu1k_51{color:var(--text-muted);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px}._renameBtn_1uu1k_57{margin-left:8px;border:1px solid var(--accent);background:var(--surface);color:var(--accent);border-radius:var(--radius-sm);padding:1px 8px;font-size:11px;cursor:pointer;transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease)}._renameBtn_1uu1k_57:hover{background:var(--accent-soft)}._renameBtn_1uu1k_57:active{background:var(--accent-subtle)}._renameBtn_1uu1k_57:focus-visible{box-shadow:var(--focus-ring)}._app_1d9ko_1{display:flex;flex-direction:column;height:100%}._main_1d9ko_8{flex:1;display:flex;flex-direction:column;min-height:0}._header_1d9ko_15{display:flex;align-items:center;flex-wrap:wrap;gap:var(--space-2);padding:8px 16px;background:var(--surface);border-bottom:1px solid var(--border)}._brand_1d9ko_26{font-size:18px;font-weight:var(--fw-bold);letter-spacing:.02em}._tabs_1d9ko_32{display:flex;gap:2px;padding:0 16px;background:var(--surface);border-bottom:1px solid var(--border);overflow-x:auto;scrollbar-width:thin}._tab_1d9ko_32{flex:0 0 auto;white-space:nowrap;border:none;background:transparent;padding:8px 14px;color:var(--text-muted);border-bottom:2px solid transparent;font-weight:600;transition:color var(--dur) var(--ease)}._tab_1d9ko_32:hover{color:var(--text)}._tab_1d9ko_32:focus-visible{box-shadow:var(--focus-ring-tight)}._tabActive_1d9ko_64{color:var(--accent);border-bottom-color:var(--accent)}._project_1d9ko_69{color:var(--text-muted);font-size:13px}._spacer_1d9ko_74{flex:1}._status_1d9ko_78{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--text-muted)}._dot_1d9ko_86{width:8px;height:8px;border-radius:50%}._dotOn_1d9ko_92{background:var(--human);animation:_dotPulse_1d9ko_1 1.8s var(--ease) infinite}._dotOff_1d9ko_97{background:transparent;border:1.5px solid var(--text-muted)}@keyframes _dotPulse_1d9ko_1{0%,to{opacity:1}50%{opacity:.45}}._markAllReadBtn_1d9ko_113{display:inline-flex;align-items:center;gap:4px;font-size:12px;font-weight:600;color:var(--accent);background:var(--accent-soft);border:1px solid var(--accent-subtle);border-radius:var(--radius-pill);padding:3px 10px;min-height:28px}._markAllReadBtn_1d9ko_113:hover{background:var(--accent-subtle)}._langSelect_1d9ko_132{border:1px solid var(--border);border-radius:var(--radius-sm);padding:7px 10px;min-height:32px;background:var(--surface);color:var(--text)}._settingsBtn_1d9ko_141{display:inline-flex;align-items:center;min-height:32px;border:1px solid var(--border);background:var(--surface);color:var(--text);border-radius:var(--radius-sm);padding:8px 14px}._settingsBtn_1d9ko_141:hover{background:var(--surface-alt)}._addBtn_1d9ko_156{display:inline-flex;align-items:center;min-height:32px;background:var(--accent);color:#fff;border:none;border-radius:var(--radius-sm);padding:8px 16px;font-weight:600}._addBtn_1d9ko_156:hover{background:var(--accent-hover)}._addBtn_1d9ko_156:active{transform:translateY(1px)}._banner_1d9ko_176{background:var(--danger);color:#fff;padding:8px 16px;font-size:13px;display:flex;align-items:center;gap:10px}._bannerClose_1d9ko_186{margin-left:auto;background:transparent;border:1px solid rgba(255,255,255,.6);color:#fff;border-radius:3px;padding:1px 8px}._center_1d9ko_195{display:flex;align-items:center;justify-content:center;flex:1;color:var(--text-muted)}._app_156sn_1{display:flex;flex-direction:column;height:100%}._header_156sn_7{display:flex;align-items:center;gap:12px;padding:12px 16px;background:var(--surface);border-bottom:1px solid var(--border)}._brand_156sn_16{font-size:18px;font-weight:800;letter-spacing:.02em}._mode_156sn_22{color:var(--text-muted);font-size:13px}._spacer_156sn_27{flex:1}._status_156sn_31{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--text-muted)}._dot_156sn_39{width:8px;height:8px;border-radius:50%}._dotOn_156sn_45{background:var(--human)}._dotOff_156sn_49{background:var(--priority-low)}._langSelect_156sn_53{border:1px solid var(--border);border-radius:var(--radius-sm);padding:4px 6px;font-size:12px;background:var(--surface);color:var(--text);transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease)}._langSelect_156sn_53:focus-visible{box-shadow:var(--focus-ring)}._banner_156sn_69{background:var(--danger);color:#fff;padding:8px 16px;font-size:13px}._center_156sn_77{flex:1;display:flex;align-items:center;justify-content:center;color:var(--text-muted)}._main_156sn_85{flex:1;overflow:auto;padding:16px;display:flex;flex-direction:column;gap:24px;max-width:980px}._sectionTitle_156sn_95{font-size:15px;font-weight:700;margin:0 0 10px}._cards_156sn_102{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}._card_156sn_102{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow-card);padding:12px 14px;transition:box-shadow var(--dur) var(--ease)}._card_156sn_102:hover{box-shadow:var(--shadow-hover)}._cardName_156sn_121{font-size:14px;font-weight:700;margin:0}._cardDir_156sn_127{color:var(--text-muted);font-size:11px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;margin:2px 0 10px}._counts_156sn_134{display:flex;flex-wrap:wrap;gap:8px 14px;margin:0}._count_156sn_134{display:flex;align-items:baseline;gap:4px}._count_156sn_134 dt{font-size:11px;color:var(--text-muted)}._count_156sn_134 dd{margin:0;font-size:13px;font-weight:700;font-variant-numeric:tabular-nums}._badges_156sn_159{display:flex;gap:6px;margin-top:10px;flex-wrap:wrap}._badgeWip_156sn_166{background:var(--danger);color:#fff;font-size:11px;border-radius:var(--radius-sm);padding:2px 8px}._badgeWarn_156sn_174{background:var(--warn-bg);border:1px solid var(--warn-border);font-size:11px;border-radius:var(--radius-sm);padding:2px 8px}._tableWrap_156sn_183{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}._table_156sn_183{width:100%;border-collapse:collapse;font-size:13px}._table_156sn_183 th,._table_156sn_183 td{text-align:left;padding:7px 10px;border-bottom:1px solid var(--border);vertical-align:top}._table_156sn_183 th{font-size:11px;color:var(--text-muted);font-weight:600}._taskId_156sn_211{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--text-muted)}._empty_156sn_217{color:var(--text-muted);font-size:13px;padding:12px 0}