@takagaki/cortex-decisions-viewer 0.4.32 → 0.4.34

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.
Files changed (2) hide show
  1. package/dist/render.js +106 -13
  2. package/package.json +1 -1
package/dist/render.js CHANGED
@@ -184,7 +184,7 @@ function buildTutorialData(site, codeUrl, repoSlug) {
184
184
  {
185
185
  title: "ドメインを可視化する",
186
186
  desc: "案件の概念と関係を図にする",
187
- prompt: "このプロジェクトの主要なドメイン概念(用語集)と、それらの関係性を、HTML アーティファクトで見やすく可視化してください。カードやボックスと線でノードと関係を表す軽量な作りにし、描画に時間のかかる精密な SVG 座標計算は避けてください。配色は リポジトリの デザイン/DESIGN.md のトークンに従い、無ければ薄い青と白を基調に、黄・ピンク・明るい緑をアクセントとして使ってください。",
187
+ prompt: "このプロジェクトの主要なドメイン概念(用語集)と、それらの関係性を、HTML アーティファクトで見やすく可視化してください。カードやボックスと線でノードと関係を表す軽量な作りにし、描画に時間のかかる精密な SVG 座標計算は避けてください。",
188
188
  },
189
189
  {
190
190
  title: "決定の経緯を辿る",
@@ -197,6 +197,14 @@ function buildTutorialData(site, codeUrl, repoSlug) {
197
197
  prompt: "直近2週間の主要な動き・論点・未解決事項を、議事録や決定記録を横断してまとめてください。",
198
198
  },
199
199
  ];
200
+ // メンバーの自分のレコードを update-member スキルで直す体験(Members セクションがある案件のみ出す)
201
+ if ((site.sections ?? []).some((s) => s.name === "Members" || s.name === "メンバー")) {
202
+ specs.push({
203
+ title: "自分の名前を変更してみよう",
204
+ desc: "メンバー一覧の自分のレコードをAIに直してもらう",
205
+ prompt: "update-member スキルを使って、メンバー一覧の中のあなた自身のレコードの表示名を変更してください(Gold層への書き込みを体験します)。",
206
+ });
207
+ }
200
208
  return {
201
209
  slug: repoSlug,
202
210
  challenges: specs.map((s, i) => ({
@@ -491,6 +499,24 @@ a:hover { text-decoration: underline; }
491
499
  box-shadow: var(--shadow); white-space: nowrap;
492
500
  }
493
501
  .edit-btn:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
502
+ /* ---- AI導線ボタン(AIで編集・+AIで登録。claude.ai/code へのディープリンク・AIアクションはオレンジ系で統一) ---- */
503
+ .ai-edit-btn {
504
+ -webkit-backdrop-filter: blur(10px) saturate(150%); backdrop-filter: blur(10px) saturate(150%);
505
+ flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
506
+ padding: 8px 14px; border: 1px solid rgba(217,119,87,0.55); border-radius: var(--radius);
507
+ background: rgba(217,119,87,0.1); color: #b45309; font-size: 13.5px; font-weight: 600;
508
+ box-shadow: var(--shadow); white-space: nowrap;
509
+ }
510
+ .ai-edit-btn:hover { background: rgba(217,119,87,0.18); border-color: rgba(217,119,87,0.85); text-decoration: none; }
511
+ .ai-add-bar { margin-bottom: 16px; }
512
+ .ai-add-btn {
513
+ display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; border-radius: 999px;
514
+ border: 1px solid rgba(255,255,255,0.55); background: rgba(217,119,87,0.82); color: #fff;
515
+ font-size: 13px; font-weight: 600; white-space: nowrap;
516
+ -webkit-backdrop-filter: blur(12px) saturate(160%); backdrop-filter: blur(12px) saturate(160%);
517
+ box-shadow: 0 2px 10px rgba(190,90,60,0.3), inset 0 1px 0 rgba(255,255,255,0.45);
518
+ }
519
+ .ai-add-btn:hover { background: rgba(194,94,63,0.92); text-decoration: none; }
494
520
  .section-label { font-size: 12px; font-weight: 700; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; margin: 24px 0 8px; }
495
521
  /* ---- はじめに(チュートリアル・Homeタブ下部) ---- */
496
522
  .tut-section { margin-top: 34px; padding-top: 22px; border-top: 1px solid var(--border); }
@@ -737,13 +763,19 @@ const CLIENT_JS = `
737
763
  // 本文は bodies/<i>.html に外出しされ詳細表示時に fetch されるため、linkify は loadBody 側で適用する
738
764
  // (ここで inline bodyHtml に適用すると検索テキストにHTMLが混ざるため適用しない)。
739
765
 
766
+ // Gold層ディレクトリ名(英語)→ タブ・フォルダの表示名(日本語)の辞書。
767
+ // 辞書に無いディレクトリはディレクトリ名のまま表示する(案件が独自ディレクトリを足しても壊れない)。
768
+ // 内部の識別子(タブkey・フォルダ状態)は英語ディレクトリ名のまま扱い、表示だけ差し替える。
769
+ var DIR_LABELS = { Decisions: "決定事項", Glossary: "用語集", Members: "メンバー", Rules: "ルール" };
770
+ function dirLabel(name) { return DIR_LABELS[name] || name; }
771
+
740
772
  // タブ: ホーム → Decisions → records/ を持つ各ディレクトリ(自動発見)
741
773
  // オンボーディングのチュートリアル(5チャレンジ)は独立タブを廃止し、Homeタブ下部に統合した
742
774
  var TABS = [];
743
775
  if (SITE.home) TABS.push({ key: "home", label: "Home" });
744
- TABS.push({ key: "decisions", label: "Decisions", items: SITE.decisions });
776
+ TABS.push({ key: "decisions", label: dirLabel("Decisions"), items: SITE.decisions });
745
777
  (SITE.sections || []).forEach(function (sec) {
746
- TABS.push({ key: "dir:" + sec.name, label: sec.name, items: sec.records });
778
+ TABS.push({ key: "dir:" + sec.name, label: dirLabel(sec.name), items: sec.records });
747
779
  });
748
780
  if (SITE.graph && SITE.graph.nodes.length > 0) {
749
781
  TABS.push({ key: "graph", label: "ナレッジグラフ" });
@@ -786,6 +818,56 @@ const CLIENT_JS = `
786
818
  function catBadge(cat) {
787
819
  return el("span", { class: "badge cat-" + cat, text: cat || "未分類" });
788
820
  }
821
+
822
+ // ---------- AI導線(Gold層への人間の書き込み口。claude.ai/code へのディープリンク) ----------
823
+ // ヘッダー「AIに聞く」と同じ方式。repoBaseUrl から slug を導出し、プロンプトを入力済みで Claude Code Web を開く。
824
+ var REPO_SLUG = SITE.repoBaseUrl
825
+ ? SITE.repoBaseUrl.replace(/^https?:\\/\\/github\\.com\\//, "").replace(/\\.git$/, "")
826
+ : "";
827
+ function codeUrl(prompt) {
828
+ return REPO_SLUG
829
+ ? "https://claude.ai/code?repo=" + REPO_SLUG + "&prompt=" + encodeURIComponent(prompt)
830
+ : "https://claude.ai/code/";
831
+ }
832
+ // editUrl(.../edit/<branch>/<path>)からリポジトリ相対のファイルパスを取り出す(プロンプトで対象を指し示すため)
833
+ function repoPathOf(rec) {
834
+ if (!rec || !rec.editUrl) return "";
835
+ var m = rec.editUrl.match(/\\/edit\\/[^/]+\\/(.+)$/);
836
+ return m ? decodeURIComponent(m[1]) : "";
837
+ }
838
+ // Gold型(ディレクトリ名)→ 手動更新スキルの対応。決定事項/用語集/メンバー/ルールの4型のみ。
839
+ // レポート等スキルの無いディレクトリは対象外(ボタンを出さない)。プロンプトは手順を埋め込まずスキル呼び出しの1〜2行にする。
840
+ var GOLD_SKILL = {
841
+ "Decisions": { skill: "update-decision", noun: "決定", add: "これから伝える決定事項を記録してください(決定の変更は既存記録を書き換えず supersedes で新しい記録として残します)", edit: "の変更を扱ってください(決定の変更は既存記録を書き換えず supersedes で新しい記録として残します)" },
842
+ "Glossary": { skill: "update-glossary", noun: "用語", add: "これから伝える用語を登録してください", edit: "を修正してください" },
843
+ "Members": { skill: "update-member", noun: "メンバー", add: "これから伝えるメンバーを登録してください", edit: "を修正してください" },
844
+ "Rules": { skill: "update-rule", noun: "ルール", add: "これから伝えるルールを登録してください", edit: "を修正してください" },
845
+ };
846
+ // ディレクトリ名が日本語の案件(用語集 等)でも同じ4型に解決できるよう、表示名(DIR_LABELS)→英語キーの別名も引く
847
+ var GOLD_ALIAS = { "決定事項": "Decisions", "用語集": "Glossary", "メンバー": "Members", "ルール": "Rules" };
848
+ function goldSkill(sectionName) {
849
+ return GOLD_SKILL[sectionName] || GOLD_SKILL[GOLD_ALIAS[sectionName]] || null;
850
+ }
851
+ // セクション(Gold型)の一覧上部に置く「+AIで登録」ボタン。スキルの無いディレクトリでは null
852
+ function aiAddBar(sectionName) {
853
+ var g = goldSkill(sectionName);
854
+ if (!g) return null;
855
+ var prompt = g.skill + " スキルを使って、" + g.add + "。";
856
+ return el("div", { class: "ai-add-bar" }, [
857
+ el("a", { class: "ai-add-btn", href: codeUrl(prompt), target: "_blank", rel: "noopener", text: "+ AIで登録" }),
858
+ ]);
859
+ }
860
+ // 各Goldレコードの「AIで編集」ボタン(GitHubで編集の隣)。スキルの無い型では null
861
+ function aiEditBtn(rec, sectionName, title) {
862
+ var g = goldSkill(sectionName);
863
+ if (!g) return null;
864
+ var pathRef = repoPathOf(rec);
865
+ var target = pathRef
866
+ ? pathRef + " の" + g.noun + "「" + title + "」"
867
+ : "この" + g.noun + "「" + title + "」(" + rec.id + ")";
868
+ var prompt = g.skill + " スキルを使って、" + target + g.edit + "。";
869
+ return el("a", { class: "ai-edit-btn", href: codeUrl(prompt), target: "_blank", rel: "noopener", text: "🤖 AIで編集" });
870
+ }
789
871
  // 本文HTMLは bodies/<i>.html に外出しされている。詳細表示時にfetchして埋める(キャッシュ・失敗時フォールバック付き)
790
872
  var bodyCache = {};
791
873
  function loadBody(rec, mount) {
@@ -869,11 +951,14 @@ const CLIENT_JS = `
869
951
  btnLabel: "実行履歴を確認 →",
870
952
  btnUrl: base ? base + "/actions/workflows/update-decision-log.yml" : null,
871
953
  },
872
- "dir:用語集": {
954
+ "dir:Glossary": {
873
955
  text: "毎晩の自動走査が新しい用語を draft として直接追加します(update-glossary-auto)。AIが生成した定義は仮のものです。「AI生成・未確認」の用語は必ず内容を確認し、適切な定義に置き換えて status: active にしてください。",
874
956
  btnLabel: "実行履歴を確認 →",
875
957
  btnUrl: base ? base + "/actions/workflows/update-glossary.yml" : null,
876
958
  },
959
+ "dir:Rules": {
960
+ text: "案件で継続的に守る制約・ルールの一覧です。AIはここを読んで、違反する提案を避けます。",
961
+ },
877
962
  "graph": {
878
963
  text: "決定・用語・レポートと、その根拠になった課題・議事録・資料のつながりを自動でつないだ地図です。点をクリックすると、そのページや実際のシステム(Backlog・GitHub等)に移動できます。",
879
964
  },
@@ -881,9 +966,7 @@ const CLIENT_JS = `
881
966
  text: "決定・用語・レポートを起点に、つながり(根拠・出典・リンク)を1列ずつ辿る表示です。行をクリックすると右に次の列が開きます。",
882
967
  },
883
968
  "dir:レポート": {
884
- text: "週次cronが自動生成します(weekly-report)。",
885
- btnLabel: "実行履歴を確認 →",
886
- btnUrl: base ? base + "/actions/workflows/weekly-report.yml" : null,
969
+ text: "レポートの生成は終了し、履歴として凍結されています(レポートはSlack配信に一本化されました)。以下は過去に生成されたレコードです。",
887
970
  },
888
971
  };
889
972
  var infoKey = listState.tab === "graph" ? (knowledgeView === "map" ? "graph" : "explorer") : listState.tab;
@@ -938,8 +1021,8 @@ const CLIENT_JS = `
938
1021
  if (!challenges.length) return; // 最小データ(チュートリアル無し)では出さない
939
1022
 
940
1023
  var sec = el("section", { class: "tut-section" });
941
- sec.appendChild(el("h2", { class: "tut-section-head", text: "はじめに — このプロジェクトを掴む5ステップ" }));
942
- sec.appendChild(el("p", { class: "tut-intro", text: "AIS Viewer と Claude Code を使ってこのプロジェクトを掴むための5ステップです。各ボタンを押すと、質問が入力済みの状態で Claude Code Web が開きます(このリポジトリへのアクセス権が必要です)。" }));
1024
+ sec.appendChild(el("h2", { class: "tut-section-head", text: "はじめに — このプロジェクトを掴む" + challenges.length + "ステップ" }));
1025
+ sec.appendChild(el("p", { class: "tut-intro", text: "AIS Viewer と Claude Code を使ってこのプロジェクトを掴むための" + challenges.length + "ステップです。各ボタンを押すと、質問が入力済みの状態で Claude Code Web が開きます(このリポジトリへのアクセス権が必要です)。" }));
943
1026
 
944
1027
  // 進捗ヘッダ({完了数}/5・バー・全完了で祝福)
945
1028
  var doneCount = challenges.filter(function (c) { return tutIsDone(c.n); }).length;
@@ -1403,6 +1486,9 @@ const CLIENT_JS = `
1403
1486
  filters.appendChild(buildSelect("すべてのカテゴリー", SITE.categories, listState.category, function (v) { listState.category = v; listState.page = 1; drawCards(); }));
1404
1487
  app.appendChild(filters);
1405
1488
 
1489
+ var addBarD = aiAddBar("Decisions");
1490
+ if (addBarD) app.appendChild(addBarD);
1491
+
1406
1492
  var listWrap = el("div", { class: "card-list", id: "card-list" });
1407
1493
  app.appendChild(listWrap);
1408
1494
  drawCards();
@@ -1482,6 +1568,9 @@ const CLIENT_JS = `
1482
1568
  filters.appendChild(search);
1483
1569
  app.appendChild(filters);
1484
1570
 
1571
+ var addBarG = aiAddBar(listState.tab.replace(/^dir:/, ""));
1572
+ if (addBarG) app.appendChild(addBarG);
1573
+
1485
1574
  var listWrap = el("div", { class: "card-list" });
1486
1575
  app.appendChild(listWrap);
1487
1576
 
@@ -1544,6 +1633,8 @@ const CLIENT_JS = `
1544
1633
  if (r.editUrl) {
1545
1634
  head.appendChild(el("a", { class: "edit-btn", href: r.editUrl, target: "_blank", rel: "noopener", text: "✏️ GitHubで編集" }));
1546
1635
  }
1636
+ var aiEditR = aiEditBtn(r, r._section, r.title);
1637
+ if (aiEditR) head.appendChild(aiEditR);
1547
1638
  app.appendChild(head);
1548
1639
 
1549
1640
  app.appendChild(el("div", { class: "detail-meta" }, [
@@ -2199,6 +2290,8 @@ const CLIENT_JS = `
2199
2290
  if (d.editUrl) {
2200
2291
  head.appendChild(el("a", { class: "edit-btn", href: d.editUrl, target: "_blank", rel: "noopener", text: "✏️ GitHubで編集" }));
2201
2292
  }
2293
+ var aiEditD = aiEditBtn(d, "Decisions", d.title);
2294
+ if (aiEditD) head.appendChild(aiEditD);
2202
2295
  app.appendChild(head);
2203
2296
 
2204
2297
  var meta = el("div", { class: "detail-meta" }, [
@@ -2294,7 +2387,7 @@ const CLIENT_JS = `
2294
2387
  // パンくず(フォルダ › レコード › つながり…)
2295
2388
  var crumbs = [];
2296
2389
  if (!q && explorerState.folder) {
2297
- crumbs.push({ label: explorerState.folder, click: function () { explorerState.path = []; renderList(); } });
2390
+ crumbs.push({ label: dirLabel(explorerState.folder), click: function () { explorerState.path = []; renderList(); } });
2298
2391
  }
2299
2392
  explorerState.path.forEach(function (id, i) {
2300
2393
  crumbs.push({
@@ -2392,7 +2485,7 @@ const CLIENT_JS = `
2392
2485
  return nodeById[id] && recordText(byId[id]).indexOf(q2) !== -1;
2393
2486
  });
2394
2487
  if (!hits.length) return;
2395
- itemsBox.appendChild(el("div", { class: "mc-group", text: g.name }));
2488
+ itemsBox.appendChild(el("div", { class: "mc-group", text: dirLabel(g.name) }));
2396
2489
  hits.forEach(function (id) { itemsBox.appendChild(makeRecordRow(id)); });
2397
2490
  });
2398
2491
  if (!itemsBox.children.length) itemsBox.appendChild(el("div", { class: "mc-empty", text: "一致なし" }));
@@ -2400,7 +2493,7 @@ const CLIENT_JS = `
2400
2493
  goldGroups.forEach(function (g) {
2401
2494
  var row = el("div", { class: "mc-item mc-folder" + (explorerState.folder === g.name ? " selected" : "") });
2402
2495
  row.appendChild(el("span", { text: "📁" }));
2403
- row.appendChild(el("span", { class: "mc-label", text: g.name }));
2496
+ row.appendChild(el("span", { class: "mc-label", text: dirLabel(g.name) }));
2404
2497
  row.appendChild(el("span", { class: "mc-count", text: String(g.ids.length) }));
2405
2498
  row.addEventListener("click", function () {
2406
2499
  explorerState.folder = g.name;
@@ -2432,7 +2525,7 @@ const CLIENT_JS = `
2432
2525
  goldGroups.forEach(function (g) { if (g.name === explorerState.folder) g0 = g; });
2433
2526
  if (g0) {
2434
2527
  var colR = el("div", { class: "mc-col" });
2435
- colR.appendChild(el("div", { class: "mc-col-head" }, [el("span", { text: g0.name + "(" + g0.ids.length + ")" })]));
2528
+ colR.appendChild(el("div", { class: "mc-col-head" }, [el("span", { text: dirLabel(g0.name) + "(" + g0.ids.length + ")" })]));
2436
2529
  g0.ids.forEach(function (id) { if (nodeById[id]) colR.appendChild(makeRecordRow(id)); });
2437
2530
  if (!g0.ids.length) colR.appendChild(el("div", { class: "mc-empty", text: "レコードはまだありません" }));
2438
2531
  cols.appendChild(colR);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takagaki/cortex-decisions-viewer",
3
- "version": "0.4.32",
3
+ "version": "0.4.34",
4
4
  "description": "Cortexの意思決定記録(Decisions/*.md)を静的サイトにビルドして閲覧する。各レコードに「Edit on GitHub」リンクを付与する。",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,