@takagaki/cortex-decisions-viewer 0.4.43 → 0.4.44

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
@@ -42,6 +42,9 @@ const path = __importStar(require("node:path"));
42
42
  const gray_matter_1 = __importDefault(require("gray-matter"));
43
43
  const marked_1 = require("marked");
44
44
  const repo_1 = require("./repo");
45
+ // 直近のGold昇格で追加されたレコードのパス集合。レコード生成の各所から参照するのでモジュールスコープに置く
46
+ // (引数で引き回すと呼び出し側の改修が広範囲になる)。build() の冒頭で1回だけ解決する。
47
+ let LATEST_PATHS = new Set();
45
48
  const render_1 = require("./render");
46
49
  const DEFAULT_EXCLUDE = ["README.md", "template.md"];
47
50
  /** frontmatterのrelationsを安全に正規化する */
@@ -245,6 +248,7 @@ async function parseGeneric(raw, fileName, repoRelDir, repoBaseUrl, branch) {
245
248
  editUrl,
246
249
  rtype: data.type != null ? String(data.type) : "",
247
250
  rstatus: data.status != null ? String(data.status) : "",
251
+ isLatest: LATEST_PATHS.has(filePath),
248
252
  relations: toRelations(data.relations),
249
253
  source: data.source != null ? String(data.source) : "",
250
254
  bodyLinks: extractBodyLinks(content),
@@ -901,6 +905,11 @@ async function build(opts) {
901
905
  branch: opts.branch,
902
906
  cwd: dirAbs,
903
907
  });
908
+ // 直近のGold昇格で追加されたレコードを git から解決する(レコードの date は決定日なので生成時期が分からない)。
909
+ // git が返すのはリポジトリルート相対のパス(`Cortex/...`)なので、判定も**リポジトリルート**で行う
910
+ // (Decisionsディレクトリで実行すると `-- Cortex/` に一致せず常に空になる)。
911
+ // 浅いclone・git無しの環境では空集合が返り、「最新」ラベルが出ないだけで他の表示は壊れない。
912
+ LATEST_PATHS = (0, repo_1.latestGeneratedPaths)(process.cwd());
904
913
  const decisions = [];
905
914
  for (const fileName of mdFiles) {
906
915
  const raw = await node_fs_1.promises.readFile(path.join(dirAbs, fileName), "utf8");
@@ -1035,6 +1044,7 @@ async function parseDecision(raw, fileName, repoRelDir, repoBaseUrl, branch) {
1035
1044
  bodyRef: "",
1036
1045
  searchText: toSearchText(content),
1037
1046
  rstatus: data.status != null ? String(data.status) : "",
1047
+ isLatest: LATEST_PATHS.has(filePath),
1038
1048
  fileName,
1039
1049
  editUrl,
1040
1050
  fm: sanitizeFm(data),
package/dist/render.js CHANGED
@@ -549,6 +549,8 @@ a:hover { text-decoration: underline; }
549
549
  .badge.cat-ビジネス { background: #fde9ef; color: #be185d; }
550
550
  .badge.cat-デザイン { background: #fce7f3; color: #a21caf; }
551
551
  .badge.draft { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
552
+ /* 直近のGold昇格で作られたレコードの印。draft(黄・要対応)と区別できるよう、新着を示す緑系にする */
553
+ .badge.latest { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
552
554
  .badge.error { background: #fee2e2; color: #b91c1c; border: 1px solid #fca5a5; }
553
555
  .draft-note {
554
556
  display: flex; gap: 8px; align-items: flex-start;
@@ -922,6 +924,11 @@ const CLIENT_JS = `
922
924
  function draftBadge(rec) {
923
925
  return rec && rec.rstatus === "draft" ? el("span", { class: "badge draft", text: "AI生成・未確認" }) : null;
924
926
  }
927
+ // 直近のGold昇格で作られたレコードの印。レコードの date は決定日なので、日付順に並べても
928
+ // 「今回の実行で何が増えたか」は分からない。ビルド時に git から判定した結果(isLatest)を出す
929
+ function latestBadge(rec) {
930
+ return rec && rec.isLatest ? el("span", { class: "badge latest", text: "最新の生成" }) : null;
931
+ }
925
932
  // 詳細ページの警告。バッジより強く「そのまま信じないでほしい」と伝える
926
933
  function draftNote(rec) {
927
934
  if (!rec || rec.rstatus !== "draft") return null;
@@ -1151,17 +1158,24 @@ const CLIENT_JS = `
1151
1158
  var base = SITE.repoBaseUrl;
1152
1159
  var INFO = {
1153
1160
  "decisions": {
1154
- text: "議事録・課題から確定した決定が毎晩自動で追記されます(update-decision-log-auto)。",
1161
+ text: "議事録・課題から確定した決定が毎晩自動で追記されます。",
1155
1162
  btnLabel: "実行履歴を確認 →",
1156
- btnUrl: base ? base + "/actions/workflows/update-decision-log.yml" : null,
1163
+ btnUrl: base ? base + "/actions/workflows/update-gold.yml" : null,
1157
1164
  },
1158
1165
  "dir:Glossary": {
1159
- text: "毎晩の自動走査が新しい用語を draft として直接追加します(update-glossary-auto)。AIが生成した定義は仮のものです。「AI生成・未確認」の用語は必ず内容を確認し、適切な定義に置き換えて status: active にしてください。",
1166
+ text: "毎晩の自動走査が新しい用語を draft として直接追加します。AIが生成した定義は仮のものです。「AI生成・未確認」の用語は必ず内容を確認し、適切な定義に置き換えて status: active にしてください。",
1167
+ btnLabel: "実行履歴を確認 →",
1168
+ btnUrl: base ? base + "/actions/workflows/update-gold.yml" : null,
1169
+ },
1170
+ "dir:Members": {
1171
+ text: "プロジェクト関係者の名簿です。人名の表記ゆれを解決する根拠になります。毎晩の自動走査が新しい参加者を draft として追加します。",
1160
1172
  btnLabel: "実行履歴を確認 →",
1161
- btnUrl: base ? base + "/actions/workflows/update-glossary.yml" : null,
1173
+ btnUrl: base ? base + "/actions/workflows/update-gold.yml" : null,
1162
1174
  },
1163
1175
  "dir:Rules": {
1164
1176
  text: "案件で継続的に守る制約・ルールの一覧です。AIはここを読んで、違反する提案を避けます。",
1177
+ btnLabel: "実行履歴を確認 →",
1178
+ btnUrl: base ? base + "/actions/workflows/update-gold.yml" : null,
1165
1179
  },
1166
1180
  "graph": {
1167
1181
  text: "決定・用語・レポートと、その根拠になった課題・議事録・資料のつながりを自動でつないだ地図です。点をクリックすると、そのページや実際のシステム(Backlog・GitHub等)に移動できます。",
@@ -1747,6 +1761,7 @@ const CLIENT_JS = `
1747
1761
  pg.slice.forEach(function (d) {
1748
1762
  var meta = el("div", { class: "card-meta" }, [
1749
1763
  draftBadge(d),
1764
+ latestBadge(d),
1750
1765
  el("span", { class: "mono", text: d.date || "----" }),
1751
1766
  catBadge(d.category),
1752
1767
  el("span", { class: "mono", text: d.id }),
@@ -1814,6 +1829,7 @@ const CLIENT_JS = `
1814
1829
  pg.slice.forEach(function (r) {
1815
1830
  var meta = el("div", { class: "card-meta" }, [
1816
1831
  draftBadge(r),
1832
+ latestBadge(r),
1817
1833
  r.date ? el("span", { class: "mono", text: r.date }) : null,
1818
1834
  el("span", { class: "mono", text: r.id }),
1819
1835
  ]);
@@ -1864,6 +1880,7 @@ const CLIENT_JS = `
1864
1880
 
1865
1881
  app.appendChild(el("div", { class: "detail-meta" }, [
1866
1882
  draftBadge(r),
1883
+ latestBadge(r),
1867
1884
  r.date ? el("span", { class: "mono", text: r.date }) : null,
1868
1885
  el("span", { class: "mono", text: r.id }),
1869
1886
  r.summary ? el("span", { text: r.summary }) : null,
@@ -2521,6 +2538,7 @@ const CLIENT_JS = `
2521
2538
 
2522
2539
  var meta = el("div", { class: "detail-meta" }, [
2523
2540
  draftBadge(d),
2541
+ latestBadge(d),
2524
2542
  el("span", { class: "mono", text: d.date || "----" }),
2525
2543
  catBadge(d.category),
2526
2544
  el("span", { class: "mono", text: d.id }),
package/dist/repo.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveRepo = resolveRepo;
4
+ exports.latestGeneratedPaths = latestGeneratedPaths;
4
5
  exports.normalizeToHttps = normalizeToHttps;
5
6
  const node_child_process_1 = require("node:child_process");
6
7
  /**
@@ -15,6 +16,51 @@ function resolveRepo(opts) {
15
16
  const remote = tryGitRemote(opts.cwd);
16
17
  return { baseUrl: remote ? normalizeToHttps(remote) : null, branch };
17
18
  }
19
+ /**
20
+ * 直近のGold昇格で追加されたレコードのパス集合を返す。
21
+ *
22
+ * 「最新の生成物」をビューアで区別するために使う。レコードの frontmatter の `date` は
23
+ * **決定日**(過去の議事録から起こした決定は古い日付になる)なので、生成のタイミングは
24
+ * git 側からしか分からない。
25
+ *
26
+ * 判定: 夜間パイプラインのコミット(メッセージが「自動追記」を含む)のうち最新の1回を探し、
27
+ * そのコミットで **追加(A)** されたファイルを返す。同じ夜に複数フェーズが別コミットで入るため、
28
+ * 最新コミットと同じ「日」のパイプラインコミットまでをまとめて1回の実行として扱う。
29
+ *
30
+ * clone が浅い(--depth 1 等)・git が無い環境では**空集合を返す**(ラベルが出ないだけで壊れない)。
31
+ */
32
+ function latestGeneratedPaths(cwd) {
33
+ const empty = new Set();
34
+ try {
35
+ // 夜間パイプラインのコミットを新しい順に数件。--grep はコミットメッセージの規約に依存するため、
36
+ // 変わっても「ラベルが出ない」だけで済むように例外は握る。
37
+ const log = (0, node_child_process_1.execSync)('git log -n 20 --grep="自動追記" --pretty=format:"%H %cI" -- Cortex/', { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
38
+ if (!log)
39
+ return empty;
40
+ const rows = log.split("\n").map((l) => {
41
+ const [sha, iso] = l.trim().split(/\s+/);
42
+ return { sha, day: (iso || "").slice(0, 10) };
43
+ });
44
+ const latestDay = rows[0].day;
45
+ if (!latestDay)
46
+ return empty;
47
+ const out = new Set();
48
+ for (const r of rows) {
49
+ if (r.day !== latestDay)
50
+ break; // 直近の実行日ぶんだけ
51
+ const files = (0, node_child_process_1.execSync)(`git show --diff-filter=A --name-only --pretty=format: ${r.sha}`, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
52
+ for (const f of files.split("\n")) {
53
+ const p = f.trim();
54
+ if (p)
55
+ out.add(p);
56
+ }
57
+ }
58
+ return out;
59
+ }
60
+ catch {
61
+ return empty; // 浅いclone・git無し・メッセージ規約の変更 → ラベルなしで続行
62
+ }
63
+ }
18
64
  function tryGitRemote(cwd) {
19
65
  try {
20
66
  return (0, node_child_process_1.execSync)("git config --get remote.origin.url", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takagaki/cortex-decisions-viewer",
3
- "version": "0.4.43",
3
+ "version": "0.4.44",
4
4
  "description": "Cortexの意思決定記録(Decisions/*.md)を静的サイトにビルドして閲覧する。各レコードに「Edit on GitHub」リンクを付与する。",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,