@takagaki/cortex-decisions-viewer 0.12.34 → 0.12.35
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.
- package/dist/render.js +188 -23
- package/package.json +1 -1
package/dist/render.js
CHANGED
|
@@ -11,6 +11,7 @@ exports.claudeCodeRepositories = claudeCodeRepositories;
|
|
|
11
11
|
exports.claudeCodeUrl = claudeCodeUrl;
|
|
12
12
|
exports.toolStateLabel = toolStateLabel;
|
|
13
13
|
exports.toolStateWithLive = toolStateWithLive;
|
|
14
|
+
exports.toolsFoldSummary = toolsFoldSummary;
|
|
14
15
|
exports.isAlreadyRegistered = isAlreadyRegistered;
|
|
15
16
|
exports.sanitizeRegisteredNow = sanitizeRegisteredNow;
|
|
16
17
|
exports.sanitizeStateNow = sanitizeStateNow;
|
|
@@ -554,6 +555,41 @@ function toolStateWithLive(item, rows) {
|
|
|
554
555
|
// failed / skipped / not_in_channel / missing_scope / no_token … は全部「人の操作待ち」
|
|
555
556
|
return "waiting";
|
|
556
557
|
}
|
|
558
|
+
/**
|
|
559
|
+
* 畳んだ種別の 1 行に出す、状態の要約(#424)。
|
|
560
|
+
*
|
|
561
|
+
* **全部同じなら、その 1 語だけ**(「GitHub 7 件 ● 読み取り中」)。畳んだ 1 行に
|
|
562
|
+
* 「読み取り中 7」と件数を書いても、左に出ている 7 件と同じ数を 2 回言うだけになる。
|
|
563
|
+
*
|
|
564
|
+
* **混ざっていれば件数で**(「読み取り中 5・承認待ち 2」)。ここで「一部が承認待ち」の
|
|
565
|
+
* ような曖昧な言い方にすると、開くまで何件手を入れるのか分からない。
|
|
566
|
+
*
|
|
567
|
+
* 色は `toolStateLabel` の `ds-gate-*` をそのまま使う。混ざっているときは
|
|
568
|
+
* **承認待ちが 1 件でもあれば橙**——畳んだ 1 行が「人の操作待ちを含む」ことを、
|
|
569
|
+
* 開かずに見つけられる必要がある(畳んだせいで気づかれなくなる、が一番痛い)。
|
|
570
|
+
*
|
|
571
|
+
* **クロージャを持たない純関数に保つこと**(`.toString()` でクライアントへ渡す)。
|
|
572
|
+
*/
|
|
573
|
+
function toolsFoldSummary(states) {
|
|
574
|
+
// 表示の順は状態の 4 語と同じ(読み取り中→承認待ち→停止中→未確認)
|
|
575
|
+
var order = ["reading", "waiting", "stopped", "unknown"];
|
|
576
|
+
var count = { reading: 0, waiting: 0, stopped: 0, unknown: 0 };
|
|
577
|
+
(states || []).forEach(function (s) {
|
|
578
|
+
// ⚠ 4 語のどれかに当たるかは **order で見る**(素のオブジェクトの添字だと
|
|
579
|
+
// "constructor" のような語が継承プロパティに当たって、知らない語が素通りする)
|
|
580
|
+
var k = String(s == null ? "" : s);
|
|
581
|
+
count[order.indexOf(k) < 0 ? "unknown" : k] += 1;
|
|
582
|
+
});
|
|
583
|
+
var used = order.filter(function (k) { return count[k] > 0; });
|
|
584
|
+
if (used.length <= 1) {
|
|
585
|
+
var lab = toolStateLabel(used[0] || "unknown");
|
|
586
|
+
return { text: lab.text, cls: lab.cls, state: used[0] || "unknown" };
|
|
587
|
+
}
|
|
588
|
+
var text = used
|
|
589
|
+
.map(function (k) { return toolStateLabel(k).text + " " + count[k]; })
|
|
590
|
+
.join("・");
|
|
591
|
+
return { text: text, cls: count.waiting > 0 ? "ds-gate-warn" : "ds-gate-muted", state: "mixed" };
|
|
592
|
+
}
|
|
557
593
|
/**
|
|
558
594
|
* 外部ソースの行が「この能力・このアダプタのタイル」に属するか。
|
|
559
595
|
*
|
|
@@ -2812,6 +2848,34 @@ button.site-icon[aria-busy="true"] .site-icon-plus { opacity: 0; }
|
|
|
2812
2848
|
.home-tools-name { flex: 1 1 220px; min-width: 0; word-break: break-all; }
|
|
2813
2849
|
.home-tools-state { flex: 0 0 auto; }
|
|
2814
2850
|
.home-tools-empty, .home-tools-note { font-size: 12.5px; color: var(--muted); line-height: 1.7; margin: 8px 0 0; }
|
|
2851
|
+
/* 種別ごとの折りたたみ(3件以上・#424)。**畳んだ1行は、行と同じ高さ・同じ字の大きさ**
|
|
2852
|
+
——一覧の途中に「見出し」が生えたように見せない。既定は畳む(open を付けない) */
|
|
2853
|
+
.home-tools-fold { margin: 8px 0 0; }
|
|
2854
|
+
.home-tools-fold > summary {
|
|
2855
|
+
display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: center;
|
|
2856
|
+
padding: 7px 0; border-bottom: 1px solid var(--border); font-size: 13.5px;
|
|
2857
|
+
cursor: pointer; list-style: none;
|
|
2858
|
+
}
|
|
2859
|
+
.home-tools-fold > summary::-webkit-details-marker { display: none; }
|
|
2860
|
+
/* アイコンは別の span(読み上げから外すため)。畳まない行の種別と同じ字面にそろえる */
|
|
2861
|
+
.home-tools-fold-icon { flex: 0 0 auto; }
|
|
2862
|
+
.home-tools-fold-label { flex: 0 0 auto; font-weight: 600; color: var(--muted); }
|
|
2863
|
+
/* 状態は行と同じく右端へ寄せる。**縦にそろっていないと一覧に見えない**
|
|
2864
|
+
(畳んだ1行だけ状態が真ん中にあると、同じ列の情報だと分からない) */
|
|
2865
|
+
.home-tools-fold-state { flex: 0 0 auto; margin-left: auto; }
|
|
2866
|
+
/* 開閉の印は CSS の content で出す(.ds-group と同じ形)。**要素にしない**——
|
|
2867
|
+
読み上げ名を「GitHub 7 件」だけにしたいので、文字として DOM に置かない */
|
|
2868
|
+
.home-tools-fold > summary::after { content: "▸"; margin-left: 8px; color: var(--muted); font-size: 12px; }
|
|
2869
|
+
.home-tools-fold[open] > summary::after { content: "▾"; }
|
|
2870
|
+
/* 開いた中身は少し寄せて、畳んだ1行との親子が見えるようにする */
|
|
2871
|
+
.home-tools-fold > .home-tools-list { margin: 0 0 0 12px; padding-left: 10px; border-left: 2px solid var(--border); }
|
|
2872
|
+
/* 畳んだ1行が後ろに続くとき・開いた中身の後ろに行が続くときは、その手前の行にも
|
|
2873
|
+
区切り線を引く。.home-tools-item:last-child で線を落としたままだと、**境目だけ
|
|
2874
|
+
線が抜けて** 2行が1行に見える(畳みが無い案件の見た目は変えない)。
|
|
2875
|
+
:has が効かない環境では、その境目の線が1本消えるだけ(並びも文言も無事) */
|
|
2876
|
+
.home-tools-list:has(+ .home-tools-fold) > .home-tools-item:last-child,
|
|
2877
|
+
.home-tools-fold:has(+ .home-tools-list) > .home-tools-list > .home-tools-item:last-child,
|
|
2878
|
+
.home-tools-fold:has(+ .home-tools-fold) > .home-tools-list > .home-tools-item:last-child { border-bottom: 1px solid var(--border); }
|
|
2815
2879
|
/* ---- レコード詳細の「AIによる最近の変更」(リポジトリの git 履歴 由来)----
|
|
2816
2880
|
カードは詳細ページの提案(.proposals)と同系色にする——どちらも
|
|
2817
2881
|
「AIがやったこと・言っていることを読む」もので種類が同じ。
|
|
@@ -3805,6 +3869,12 @@ ${overlayStateOnFleet.toString()}
|
|
|
3805
3869
|
var TOOL_KIND_ICONS = ${JSON.stringify(TOOL_KIND_ICONS)};
|
|
3806
3870
|
${toolStateLabel.toString()}
|
|
3807
3871
|
${toolStateWithLive.toString()}
|
|
3872
|
+
// 畳んだ種別の 1 行に出す状態の要約(#424)。**同じ 4 語を使う**——ここで別の言い方を
|
|
3873
|
+
// 作ると、畳んだ 1 行と開いた行が違う語で同じ状態を指す
|
|
3874
|
+
${toolsFoldSummary.toString()}
|
|
3875
|
+
// 🔴 **同じ種別が何件あったら畳むか。** 1 にすると 1 件の種別まで畳まれて、
|
|
3876
|
+
// Backlog・Drive・Meet が「1 件 ▸」の行に化ける(#424 で明示的に避けた形)
|
|
3877
|
+
var TOOLS_FOLD_MIN = 3;
|
|
3808
3878
|
${nextStateDelay.toString()}
|
|
3809
3879
|
// 工程1.5: 正本を直接読む(secretsNow / capabilitiesNow / githubOwners)。
|
|
3810
3880
|
// **判定の実体はビルド時の定義**——画面側に書き写すと許可リストが2枚になる
|
|
@@ -5256,30 +5326,34 @@ ${deriveCapTile.toString()}
|
|
|
5256
5326
|
box.appendChild(el("p", { class: "home-tools-empty", text: "まだツールを接続していません。操作タブから接続できます。" }));
|
|
5257
5327
|
return box;
|
|
5258
5328
|
}
|
|
5259
|
-
|
|
5329
|
+
// **種別ごとにまとめる(#424)。**
|
|
5330
|
+
//
|
|
5331
|
+
// 🔴 **隣り合う同じ種別だけをまとめる**(前から順に見て、種別が変わったら切る)。
|
|
5332
|
+
// 種別ごとに拾い集める形にすると、engine が種別を飛び飛びに出した日に
|
|
5333
|
+
// **並び順が変わる**——「並び順は変えない」は仕様なので、engine の出力の性質
|
|
5334
|
+
// (いまは種別ごとに連続している)に寄りかからず、構造として変わらない形にする
|
|
5335
|
+
var groups = [];
|
|
5260
5336
|
items.forEach(function (it) {
|
|
5261
|
-
var
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
if (
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
ul.appendChild(li);
|
|
5337
|
+
var k = String(it && it.kind != null ? it.kind : "");
|
|
5338
|
+
var last = groups[groups.length - 1];
|
|
5339
|
+
if (last && last.kind === k) last.items.push(it);
|
|
5340
|
+
else groups.push({ kind: k, items: [it] });
|
|
5341
|
+
});
|
|
5342
|
+
// 畳まない種別は 1 つの <ul> に続けて入れる(1〜2 件の種別のあいだに区切り線が
|
|
5343
|
+
// 入らない、いまの見た目のまま)。畳みを挟んだら次の種別から新しい <ul> にする
|
|
5344
|
+
var ul = null;
|
|
5345
|
+
var foldSeq = 0;
|
|
5346
|
+
groups.forEach(function (g) {
|
|
5347
|
+
if (g.items.length >= TOOLS_FOLD_MIN) {
|
|
5348
|
+
ul = null;
|
|
5349
|
+
// 連番を渡す。**同じ種別が離れて 2 度出ると、種別だけでは名前がぶつかる**
|
|
5350
|
+
// (id が重複し、開閉の復元も両方に効く)
|
|
5351
|
+
box.appendChild(homeToolsFold(g.items, foldSeq++));
|
|
5352
|
+
return;
|
|
5353
|
+
}
|
|
5354
|
+
if (!ul) { ul = el("ul", { class: "home-tools-list" }); box.appendChild(ul); }
|
|
5355
|
+
g.items.forEach(function (it) { ul.appendChild(homeToolRow(it)); });
|
|
5281
5356
|
});
|
|
5282
|
-
box.appendChild(ul);
|
|
5283
5357
|
// **どこで直せるか・いつの情報かを 1 行で言う。** 操作タブで繋いだ直後は
|
|
5284
5358
|
// この一覧に出ない(engine が毎朝作り直すまで)ので、黙っていると「効いていない」と読まれる
|
|
5285
5359
|
box.appendChild(el("p", {
|
|
@@ -5289,6 +5363,83 @@ ${deriveCapTile.toString()}
|
|
|
5289
5363
|
return box;
|
|
5290
5364
|
}
|
|
5291
5365
|
|
|
5366
|
+
/**
|
|
5367
|
+
* 使用ツールの 1 行。**畳んだ種別の中でも同じ形**(開いたときに見えるのは今までの行)。
|
|
5368
|
+
*/
|
|
5369
|
+
function homeToolRow(it) {
|
|
5370
|
+
var li = el("li", { class: "home-tools-item" });
|
|
5371
|
+
// 種別は**ツール名**(能力名でも単位語でもない)。DS_TYPE の行の約束と同じ
|
|
5372
|
+
li.appendChild(el("span", {
|
|
5373
|
+
class: "home-tools-kind",
|
|
5374
|
+
text: (TOOL_KIND_ICONS[it.kind] || "🔗") + " " + (it.label || it.kind),
|
|
5375
|
+
}));
|
|
5376
|
+
var name = it.name || it.ref || "";
|
|
5377
|
+
// **開ける先が無い行(Google Meet)はリンクにしない。** 押せないリンクを出すより
|
|
5378
|
+
// 素のテキストのほうが正直(url は engine が null で「無い」と言い切っている)
|
|
5379
|
+
// href に載せる前に isHttp を通す(build 側の許可リストと二重の守り。el() の注意書きのとおり)
|
|
5380
|
+
if (it.url && isHttp(it.url)) li.appendChild(el("a", { class: "home-tools-name", href: it.url, target: "_blank", rel: "noopener", text: name }));
|
|
5381
|
+
else li.appendChild(el("span", { class: "home-tools-name", text: name }));
|
|
5382
|
+
// ライブの実測が届いていれば重ねる(stopped は上書きしない・toolStateWithLive)
|
|
5383
|
+
var st = toolStateWithLive(it, LIVE_STATE);
|
|
5384
|
+
var lab = toolStateLabel(st);
|
|
5385
|
+
var chip = el("span", { class: "home-tools-state ds-gate " + lab.cls, text: lab.text });
|
|
5386
|
+
// 状態そのものを属性に残す(表示語を読み替えずに検査・スタイルできるように)
|
|
5387
|
+
chip.setAttribute("data-state", st);
|
|
5388
|
+
li.appendChild(chip);
|
|
5389
|
+
return li;
|
|
5390
|
+
}
|
|
5391
|
+
|
|
5392
|
+
/**
|
|
5393
|
+
* 同じ種別が 3 件以上あるときの、畳んだ 1 行(#424)。
|
|
5394
|
+
*
|
|
5395
|
+
* 🔴 **既定は畳む(open 属性を付けない)。** GitHub 7 件・Slack 11 件が縦に並ぶと、
|
|
5396
|
+
* その下の本文が画面の外へ押し出される。件数と状態の要約は畳んだまま読めるので、
|
|
5397
|
+
* 「何件つながっていて、手を入れる先があるか」は開かなくても分かる。
|
|
5398
|
+
* 開閉は**保存しない**(開き直すと畳んだ状態に戻る・portal #77 と同じ)
|
|
5399
|
+
*
|
|
5400
|
+
* 🔴 **行は畳んでも DOM に残す**(details の中に置くだけ)。描き直し(syncHomeTools)で
|
|
5401
|
+
* 開閉を戻せるのも、検査が行数を数えられるのも、行がそこにあるからで、
|
|
5402
|
+
* **作り直す形にすると開いている最中に中身が消える**
|
|
5403
|
+
*/
|
|
5404
|
+
function homeToolsFold(group, seq) {
|
|
5405
|
+
var first = group[0] || {};
|
|
5406
|
+
var kind = String(first.kind == null ? "" : first.kind);
|
|
5407
|
+
// 畳み 1 つを指す鍵。**種別だけにしない**——同じ種別が離れて 2 度出たときに
|
|
5408
|
+
// id が重複し、開閉の復元も両方に効いてしまう
|
|
5409
|
+
var key = (kind || "other") + "-" + seq;
|
|
5410
|
+
// 状態は 1 行ずつ求めてから畳む(行と要約が別の判定を持たない)
|
|
5411
|
+
var sum = toolsFoldSummary(group.map(function (it) { return toolStateWithLive(it, LIVE_STATE); }));
|
|
5412
|
+
var chip = el("span", { class: "home-tools-fold-state ds-gate " + sum.cls, text: sum.text });
|
|
5413
|
+
chip.setAttribute("data-state", sum.state);
|
|
5414
|
+
// 説明として読ませるので id が要る
|
|
5415
|
+
var chipId = "home-tools-fold-state-" + key;
|
|
5416
|
+
chip.setAttribute("id", chipId);
|
|
5417
|
+
// 件数まで含めて 1 つのテキストノードにする(分けると読み上げが途切れ、
|
|
5418
|
+
// 文言の完全一致で拾えなくなる。portal #77 と同じ約束)。
|
|
5419
|
+
// ⚠ **ツール名はまとまりの中から拾う**(先頭だけ見ると、engine が先頭の 1 件の
|
|
5420
|
+
// label を落とした日に「github 3 件」と内部名が出る)
|
|
5421
|
+
var named = null;
|
|
5422
|
+
group.forEach(function (it) { if (!named && it && it.label) named = it; });
|
|
5423
|
+
var label = ((named || first).label || first.kind || "その他") + " " + group.length + " 件";
|
|
5424
|
+
var sums = el("summary", { class: "home-tools-fold-summary" }, [
|
|
5425
|
+
// アイコンは読み上げから外す(「たこ」と読まれても種別は分からない)
|
|
5426
|
+
el("span", { class: "home-tools-fold-icon", "aria-hidden": "true", text: TOOL_KIND_ICONS[first.kind] || "🔗" }),
|
|
5427
|
+
el("span", { class: "home-tools-fold-label", text: label }),
|
|
5428
|
+
chip,
|
|
5429
|
+
]);
|
|
5430
|
+
// ⚠ **読み上げ名は「GitHub 7 件」**(aria-label で言い切る)。状態の要約は
|
|
5431
|
+
// aria-describedby で**説明として**読ませる——チップを aria-hidden にすると、
|
|
5432
|
+
// 畳んでいるあいだ(中身は支援技術からも見えない)「承認待ちが 2 件ある」ことが
|
|
5433
|
+
// 目で見える人にしか伝わらない。それは畳みを橙にした理由と正面から矛盾する
|
|
5434
|
+
sums.setAttribute("aria-label", label);
|
|
5435
|
+
sums.setAttribute("aria-describedby", chipId);
|
|
5436
|
+
var ul = el("ul", { class: "home-tools-list" });
|
|
5437
|
+
group.forEach(function (it) { ul.appendChild(homeToolRow(it)); });
|
|
5438
|
+
// data-fold-key は「描き直しても開いたままにする」ための目印(syncHomeTools が見る)。
|
|
5439
|
+
// data-kind は種別そのもの(畳んだ 1 行がどのツールのものか、を素直に読めるように)
|
|
5440
|
+
return el("details", { class: "home-tools-fold", "data-kind": kind, "data-fold-key": key }, [sums, ul]);
|
|
5441
|
+
}
|
|
5442
|
+
|
|
5292
5443
|
/**
|
|
5293
5444
|
* 接続状況(op=state)が届いたときに「使用ツール」を描き直す(#275)。
|
|
5294
5445
|
*
|
|
@@ -5300,7 +5451,21 @@ ${deriveCapTile.toString()}
|
|
|
5300
5451
|
var old = app.ownerDocument.querySelector(".home-tools");
|
|
5301
5452
|
if (!old || !old.parentNode) return;
|
|
5302
5453
|
var next = homeToolsSection();
|
|
5303
|
-
if (next)
|
|
5454
|
+
if (!next) return;
|
|
5455
|
+
// 🔴 **人が開いた折りたたみは、描き直しても開いたままにする(#424)。**
|
|
5456
|
+
// 実測は開いた直後に届くことがあり、そこで畳み直すと「押したのに閉じた」になる
|
|
5457
|
+
// (portal #77 で踏んだのと同じ罠)。**保存はしない**——開き直せば畳んだ状態に戻る
|
|
5458
|
+
var opened = {};
|
|
5459
|
+
var before = old.querySelectorAll(".home-tools-fold");
|
|
5460
|
+
for (var i = 0; i < before.length; i++) {
|
|
5461
|
+
// 素のオブジェクトの添字にしない("constructor" のような鍵が継承側に当たる)
|
|
5462
|
+
if (before[i].open) opened["k:" + (before[i].getAttribute("data-fold-key") || "")] = true;
|
|
5463
|
+
}
|
|
5464
|
+
var after = next.querySelectorAll(".home-tools-fold");
|
|
5465
|
+
for (var j = 0; j < after.length; j++) {
|
|
5466
|
+
if (opened["k:" + (after[j].getAttribute("data-fold-key") || "")]) after[j].open = true;
|
|
5467
|
+
}
|
|
5468
|
+
old.parentNode.replaceChild(next, old);
|
|
5304
5469
|
}
|
|
5305
5470
|
|
|
5306
5471
|
/**
|
package/package.json
CHANGED