@takagaki/cortex-decisions-viewer 0.12.44 → 0.12.46

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/build.js CHANGED
@@ -538,7 +538,11 @@ async function readFleetSources(repoRoot) {
538
538
  .filter((x) => TOOL_KINDS.indexOf(x.kind) >= 0 && TOOL_STATES.indexOf(x.state) >= 0);
539
539
  // **items が 0 件でも器は通す。** 「まだ 1 つも接続が無い」(接続の導線を出す)と
540
540
  // 「この項目を知らない古い生成物」(何も出さない)は別の状態
541
- tools = { version: 1, items: items, paragraph: String(t.paragraph ?? "") };
541
+ //
542
+ // 🔴 **`paragraph` は受け渡さない(#501 で #275 の一部を取り消した)。** engine は
543
+ // 「この案件が使っているツール: …」の段落を載せ続けているが、AI の起動文には
544
+ // 付けないと決めたので、画面データにも運ばない(知らないキーとして落ちる)
545
+ tools = { version: 1, items: items };
542
546
  }
543
547
  }
544
548
  // 能力ごとの導出済みの状態(#125①が載せ、#125②で画面の正本になった)。
@@ -978,48 +982,19 @@ async function walkMd(dirAbs) {
978
982
  * - minute:{定例名}:{YYYYMMDD} → 議事録ファイルのGitHub blobリンク
979
983
  */
980
984
  /**
981
- * マーカーファイルの在り処からディレクトリ名を求める(`cortex-engine/scripts/fleet-status.mjs`
982
- * の `findDirByMarker` と同じ考え方)。
985
+ * 能力ディレクトリの名前(#479)。**固定値。探索しない。**
986
+ *
987
+ * かつては「案件によって置き場が違うかもしれない」前提で、マーカーファイル
988
+ * (`ingest-config.json` など)の在り処からディレクトリ名を求める探索を持っていた。旧構成の案件は
989
+ * 2026-09-07 に全部標準構成へ移り、艦隊 35 リポすべてがこの配置になったので、その分岐は撤去した。
983
990
  *
984
- * **ディレクトリ名をハードコードしない。** `customize-tooling` で改名している案件が実在する
985
- * (ある案件は `課題管理/`→`Backlog/`・`会議/`→`MTG/`・`デザイン/`→`Figma/`)。
986
- * 決め打ちだと、その案件では課題キーもFigmaも**永久に解決できない**。
991
+ * **無い案件では探索版も既定名(=この値)に落ちていた**ので、ここを固定にしても
992
+ * 「置き場が見つからないときの挙動」は変わらない——その先の `walkMd` / `fs.readdir` が
993
+ * 実在しないディレクトリを catch して空を返す(空扱い・警告なし)。
987
994
  */
988
- async function findDirByMarker(repoRoot, marker, fallback) {
989
- try {
990
- for (const d of await node_fs_1.promises.readdir(repoRoot, { withFileTypes: true })) {
991
- if (!d.isDirectory() || d.name === "node_modules" || d.name.startsWith("."))
992
- continue;
993
- try {
994
- await node_fs_1.promises.stat(path.join(repoRoot, d.name, marker));
995
- return d.name;
996
- }
997
- catch {
998
- // 直下に無ければ1階層下も見る(backlog-settings.json は issues/ の下に置かれる)
999
- }
1000
- try {
1001
- for (const sub of await node_fs_1.promises.readdir(path.join(repoRoot, d.name), { withFileTypes: true })) {
1002
- if (!sub.isDirectory())
1003
- continue;
1004
- try {
1005
- await node_fs_1.promises.stat(path.join(repoRoot, d.name, sub.name, marker));
1006
- return d.name;
1007
- }
1008
- catch {
1009
- // 次へ
1010
- }
1011
- }
1012
- }
1013
- catch {
1014
- // 読めないディレクトリは飛ばす
1015
- }
1016
- }
1017
- }
1018
- catch {
1019
- // repoRoot が読めなければ既定名で進む
1020
- }
1021
- return fallback;
1022
- }
995
+ const MEETING_DIR = "会議";
996
+ const DESIGN_DIR = "デザイン";
997
+ const MATERIALS_DIR = "共有資料";
1023
998
  /** 会議の回を入れるディレクトリの名前(`会議/<会議名>/20260120/`) */
1024
999
  const MEETING_DATE_DIR = /^\d{8}$/;
1025
1000
  /**
@@ -1041,8 +1016,7 @@ const MEETING_DATE_DIR = /^\d{8}$/;
1041
1016
  * 同じ日に文字起こしを足しても議事録は作り直されないので、送る前に画面で伝えるために使う。
1042
1017
  */
1043
1018
  async function collectMeetings(repoRoot) {
1044
- const meetingDir = await findDirByMarker(repoRoot, "ingest-config.json", "会議");
1045
- const rootAbs = path.join(repoRoot, meetingDir);
1019
+ const rootAbs = path.join(repoRoot, MEETING_DIR);
1046
1020
  const out = [];
1047
1021
  const hasMinute = async (dirAbs) => {
1048
1022
  try {
@@ -1098,12 +1072,13 @@ const BACKLOG_SECTIONS = ["issues", "documents", "wiki"];
1098
1072
  /**
1099
1073
  * 課題管理の能力ディレクトリ(`<ここ>/issues` に課題ミラーが入る)を探す。
1100
1074
  *
1101
- * **汎用の `findDirByMarker` では足りない。** `backlog-settings.json` は能力ディレクトリの
1102
- * 直下ではなく**区画の中**(`<課題管理>/issues/` 等)にあり、しかも接続先が複数になると
1103
- * さらに1階層落ちる(`<課題管理>/<キー>/{issues,…}/`・#127)。汎用版は最上位の
1104
- * ディレクトリ名しか返さないので、入れ子形の案件では `<課題管理>/issues` という
1105
- * 実在しないパスを見に行き、**課題キー→Backlog URL の表が空になる**
1075
+ * 🔴 **他の能力(会議・デザイン・共有資料)のように固定値にできない(#479 の対象外)。**
1076
+ * `backlog-settings.json` は能力ディレクトリの直下ではなく**区画の中**
1077
+ * (`<課題管理>/issues/` 等)にあり、しかも接続先が複数になるとさらに1階層落ちる
1078
+ * (`<課題管理>/<キー>/{issues,…}/`・#127)。`課題管理` 決め打ちだと、入れ子形の案件では
1079
+ * `課題管理/issues` という実在しないパスを見に行き、**課題キー→Backlog URL の表が空になる**
1106
1080
  * (グラフの課題ノードが全部リポ内パス止まりになり、Backlog へ飛べない)。
1081
+ * 標準構成への移行(#479)で揃ったのは**能力ディレクトリの名前**であって、区画の入れ子ではない。
1107
1082
  *
1108
1083
  * 規則の出どころは cortex-engine の `plugin/scripts/issues-config.mjs`(`findBacklogDir`)。
1109
1084
  * **あちらを変えたらここも変えること**(`viewer/test/backlog-nested-layout.test.mjs` が見張る)。
@@ -1152,9 +1127,9 @@ async function findBacklogDir(repoRoot, fallback) {
1152
1127
  async function buildTargetUrlMap(repoRoot, repoBaseUrl, branch) {
1153
1128
  const map = new Map();
1154
1129
  const issuesDir = await findBacklogDir(repoRoot, "課題管理");
1155
- const designDir = await findDirByMarker(repoRoot, "figma.json", "デザイン");
1156
- const meetingDir = await findDirByMarker(repoRoot, "ingest-config.json", "会議");
1157
- const materialsDir = await findDirByMarker(repoRoot, "materials-config.json", "共有資料");
1130
+ const designDir = DESIGN_DIR;
1131
+ const meetingDir = MEETING_DIR;
1132
+ const materialsDir = MATERIALS_DIR;
1158
1133
  // 課題キー → Backlog URL({課題管理}/issues/ の同期mdの基本情報から抽出)
1159
1134
  for (const file of await walkMd(path.join(repoRoot, issuesDir, "issues"))) {
1160
1135
  try {
@@ -1221,7 +1196,7 @@ async function buildTargetUrlMap(repoRoot, repoBaseUrl, branch) {
1221
1196
  // minute:{定例名}:{YYYYMMDD} → 議事録ファイルのGitHubリンク
1222
1197
  // パス規約: {会議}/{フェーズ}/{定例名}/{YYYYMMDD}/*minutes*.md
1223
1198
  //
1224
- // **以前は存在しない `ミーティング/` を見ていた**(艦隊は全案件 `会議/`。改名案件は `MTG/`)。
1199
+ // **以前は存在しない `ミーティング/` を見ていた**(艦隊は全案件 `会議/`)。
1225
1200
  // そのため minute: の解決は一度も効いていなかった。
1226
1201
  if (repoBaseUrl) {
1227
1202
  for (const file of await walkMd(path.join(repoRoot, meetingDir))) {
package/dist/render.js CHANGED
@@ -409,15 +409,14 @@ function projectRepoSlug(repoBaseUrl) {
409
409
  * 「この案件を Claude Code Web で開く」URL。
410
410
  *
411
411
  * 🔴 **AI 導線はこの1本を呼ぶ(`claudeCodeUrl` の呼び出しを写さない)。** 呼び出し側で
412
- * 組み直すと、引数を1つ落とした側だけが**開発リポジトリを載せない/ツールの段落を
413
- * 付けない**——「同じ先」が静かに割れる。指示文・slug の導出・URL の組み立ての3つを、
412
+ * 組み直すと、引数を1つ落とした側だけが**開発リポジトリを載せない**——「同じ先」が
413
+ * 静かに割れる。指示文・slug の導出・URL の組み立ての3つを、
414
414
  * ここと ASK_PROMPT / projectRepoSlug に閉じておく。
415
415
  *
416
416
  * `?? []` は必須——build.ts は fleet-status.json が無い案件で externalSources を持たない。
417
- * 第4引数は使っているツールの段落(#275・全導線に同じ段落を付ける)。
418
417
  */
419
418
  function askAiUrl(site) {
420
- return claudeCodeUrl(ASK_PROMPT, projectRepoSlug(site.repoBaseUrl), site.externalSources ?? [], site.tools && site.tools.paragraph);
419
+ return claudeCodeUrl(ASK_PROMPT, projectRepoSlug(site.repoBaseUrl), site.externalSources ?? []);
421
420
  }
422
421
  /**
423
422
  * owner/repo の形か(ポータル web/src/features/harness/harness-link.ts の REPOSITORY_SLUG と同じ形)。
@@ -496,18 +495,16 @@ function claudeCodeRepositories(projectRepo, devRefs) {
496
495
  * repositories はカンマ区切りで**素のまま**載せる(公式の例がその形で、スラッシュも
497
496
  * エンコードしない)。指示文だけ encodeURIComponent する。
498
497
  *
499
- * `toolsParagraph`(#275)は「この案件が使っているツール: …」の 1 段落。非空なら
500
- * **指示文の先頭に付ける**。7 導線すべてがこの 1 関数を通るので、ここに置くだけで
501
- * どのボタンから開いても AI が最初に案件の道具立てを知る——**呼び出し側で足さないこと**
502
- * (足すと、足し忘れたボタンだけ文脈の無い起動になる)。
503
- * `data-ai-prompt` には元の指示文を残す(貼り替えもこの関数を通るので段落は保たれる)。
498
+ * 🔴 **指示文には前置きを足さない(#501・#275 の取り消し)。** かつては
499
+ * 「この案件が使っているツール: …」の 1 段落をここで先頭に付けていたが、オーナー判断で
500
+ * やめた。`href` の指示文と貼り替えの目印(`data-ai-prompt`)は**同じ文字列**に保つ
501
+ * ——ここで足すと、貼り替えのたびに前置きが増えるかどうかを両側で気にすることになる。
504
502
  */
505
- function claudeCodeUrl(prompt, projectRepo, externals, toolsParagraph) {
503
+ function claudeCodeUrl(prompt, projectRepo, externals) {
506
504
  var repos = claudeCodeRepositories(projectRepo, devRepositoryRefs(externals));
507
505
  if (!repos.length)
508
506
  return CLAUDE_CODE_HOME;
509
- var text = toolsParagraph ? String(toolsParagraph) + "\n\n" + prompt : prompt;
510
- return "https://claude.ai/code?repositories=" + repos.join(",") + "&prompt=" + encodeURIComponent(text);
507
+ return "https://claude.ai/code?repositories=" + repos.join(",") + "&prompt=" + encodeURIComponent(prompt);
511
508
  }
512
509
  // ---------------------------------------------------------------------------
513
510
  // Home の「使用ツール」(engine #275)— 一覧は engine が登録簿から算出した `SITE.tools`
@@ -4706,10 +4703,8 @@ ${calendarAddUrl.toString()}
4706
4703
  // 🔴 **var MERGE_KEYS の宣言より上に codeUrl を呼ぶトップレベル文を足さないこと。**
4707
4704
  // fleetVal は MERGE_KEYS を読むが、var の初期化は宣言行に達するまで走らない
4708
4705
  // (関数宣言の巻き上げでは undefined を読む)。呼び出しは全て描画(route)以降に置く
4709
- // 第4引数は使っているツールの段落(#275)。**焼き込んだ SITE から取る**——この段落は
4710
- // engine が毎朝 fleet-status.json に載せるもので、ライブ(op=state)は運んでこない
4711
4706
  function codeUrl(prompt) {
4712
- return claudeCodeUrl(prompt, REPO_SLUG, fleetVal("externalSources") || [], SITE.tools && SITE.tools.paragraph);
4707
+ return claudeCodeUrl(prompt, REPO_SLUG, fleetVal("externalSources") || []);
4713
4708
  }
4714
4709
  /**
4715
4710
  * 🔴 **「1件も登録されていない」と「確かめられなかった」を分ける(#409)。**
@@ -8060,6 +8055,13 @@ ${calendarAddUrl.toString()}
8060
8055
  */
8061
8056
  var KEY_POINTING_CHECKS = { backlog_secrets: "課題管理", figma_token: "デザイン" };
8062
8057
 
8058
+ /**
8059
+ * Backlog の固定送信元IP(NAT GatewayのEIP)。IP制限のある顧客スペースは、
8060
+ * この1つの値を許可リストに入れれば固定IP経由で同期できる(艦隊共通1本)。
8061
+ * 出どころ: BacklogSyncFixedIpスタックの出力 FixedEgressIp。値が変わったらそちらを直す。
8062
+ */
8063
+ var BACKLOG_FIXED_EGRESS_IP = "54.238.206.32";
8064
+
8063
8065
  /**
8064
8066
  * 応答に添えられた接続先の一覧を採ったときの件数(Backlog の adoptTargets)。
8065
8067
  *
@@ -10694,6 +10696,16 @@ ${calendarAddUrl.toString()}
10694
10696
  // Webhook を貼りに行く(貼っても届かない)
10695
10697
  var rt = realtimeSyncCard();
10696
10698
  if (rt) box.appendChild(rt);
10699
+ // **モーダルの末尾に固定IP案内を1つだけ足す(#497)。** 固定IP経由の案件
10700
+ // (backlogTargetsEditable()===false)は既に3行上で「この画面からは接続先を
10701
+ // 変更できません」を出して担当者連絡に倒しているので、二重に言わない。
10702
+ if (backlogTargetsEditable()) {
10703
+ box.appendChild(el("p", {
10704
+ class: "sec-how",
10705
+ text: "Backlog に IP 制限がかかっている場合は、固定の送信元 IP(" + BACKLOG_FIXED_EGRESS_IP
10706
+ + ")経由で同期できます。お客様側でこの IP の許可を依頼したうえで、運用担当に連絡してください(切り替えは運用側で行います)。",
10707
+ }));
10708
+ }
10697
10709
  used = true;
10698
10710
  }
10699
10711
 
@@ -10971,7 +10983,7 @@ ${calendarAddUrl.toString()}
10971
10983
  // how / note)。全文をここに移すと二重になり、片方だけ直る形になる
10972
10984
  // ——カードは接続マップとタイルの注記と条件を揃えているので、動かすと壊れやすい。
10973
10985
  hint: [
10974
- "Figma でトークンを発行します(読み取りだけ。スコープ2つ)。手順は「Figma のトークン」の欄にあります(ファイルを追加すると上に出ます)。",
10986
+ "Figma でトークンを発行します(読み取りだけ。スコープ2つ。Dev または Full 席の方が発行)。手順は「Figma のトークン」の欄にあります(ファイルを追加すると上に出ます)。",
10975
10987
  "発行したアカウントを、読み取りたい Figma ファイルに閲覧者として招待します(招待が無いと、トークンが正しくても読めません)。",
10976
10988
  "そのファイルのURLを下の欄に貼って「追加」を押します。",
10977
10989
  "追加したファイルは、画面名と Figma へのリンクが毎晩同期されます(画像は取り込まれません)。",
@@ -12743,7 +12755,8 @@ ${calendarAddUrl.toString()}
12743
12755
  // **スコープが正しくても、招待が無いと読めない。** トークンは「そのアカウントが
12744
12756
  // 見られるファイル」しか読めないので、招待漏れは 404 になる。権限の問題に見えないため
12745
12757
  // 現場で切り分けに時間がかかる(実際に踏んだ)。入力欄の隣に書いておく。
12746
- note: "発行したアカウントを、対象の Figma ファイルに閲覧者として招待しておいてください(招待が無いとトークンが正しくても読めません)。",
12758
+ note: "発行したアカウントを、対象の Figma ファイルに閲覧者として招待しておいてください(招待が無いとトークンが正しくても読めません)。"
12759
+ + "発行するのは、対象ファイルのあるチームで Dev または Full の席を持つ方にしてください。閲覧席(View/Collab)のトークンは取得回数が月 20 回までで、夜間同期が数日で止まります。",
12747
12760
  },
12748
12761
  "backlog": {
12749
12762
  icon: "📋",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takagaki/cortex-decisions-viewer",
3
- "version": "0.12.44",
3
+ "version": "0.12.46",
4
4
  "description": "Cortexの意思決定記録(Decisions/*.md)を静的サイトにビルドして閲覧する。各レコードに「Edit on GitHub」リンクを付与する。",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,