@takagaki/cortex-decisions-viewer 0.4.42 → 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 +10 -0
- package/dist/render.js +25 -7
- package/dist/repo.js +46 -0
- package/package.json +1 -1
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;
|
|
@@ -965,10 +972,10 @@ const CLIENT_JS = `
|
|
|
965
972
|
// 顧客も押すボタンなので、内側の運用事情を文面に出さない。
|
|
966
973
|
var AI_COMMON = "";
|
|
967
974
|
// Home(案件の入口)のAI編集。Gold層の4区画と違い規約READMEが無いので、Home自身を読ませて直させる。
|
|
968
|
-
//
|
|
975
|
+
// 「このプロジェクトが目指すもの」はAIが判断の方向を決める材料なので、未記入なら埋めることを促す。
|
|
969
976
|
var HOME_EDIT_PROMPT = [
|
|
970
|
-
"Cortex/Home.md
|
|
971
|
-
"
|
|
977
|
+
"Cortex/Home.md を読んでから、このプロジェクトの入口ページを修正してください。",
|
|
978
|
+
"何を直すかは、まずわたしに質問してください。「このプロジェクトが目指すもの」が未記入なら、そこを埋めるところから始めてください(解きたいこと=誰の何の課題をどう解くか/達成した状態=どうなったら成功か)。",
|
|
972
979
|
"frontmatter(識別カード・engine 設定)は触らないでください。日付・進捗・実績値は書かないでください(変わるものの正本は課題管理ツール等の外部にあります)。",
|
|
973
980
|
"書き込む前に、変更内容を提示して承認を得てください。",
|
|
974
981
|
].join("\\n");
|
|
@@ -1151,17 +1158,24 @@ const CLIENT_JS = `
|
|
|
1151
1158
|
var base = SITE.repoBaseUrl;
|
|
1152
1159
|
var INFO = {
|
|
1153
1160
|
"decisions": {
|
|
1154
|
-
text: "
|
|
1161
|
+
text: "議事録・課題から確定した決定が毎晩自動で追記されます。",
|
|
1155
1162
|
btnLabel: "実行履歴を確認 →",
|
|
1156
|
-
btnUrl: base ? base + "/actions/workflows/update-
|
|
1163
|
+
btnUrl: base ? base + "/actions/workflows/update-gold.yml" : null,
|
|
1157
1164
|
},
|
|
1158
1165
|
"dir:Glossary": {
|
|
1159
|
-
text: "毎晩の自動走査が新しい用語を draft
|
|
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-
|
|
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