@takagaki/cortex-decisions-viewer 0.4.33 → 0.4.36
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 +1 -0
- package/dist/render.js +392 -33
- package/package.json +1 -1
package/dist/build.js
CHANGED
|
@@ -1022,6 +1022,7 @@ async function parseDecision(raw, fileName, repoRelDir, repoBaseUrl, branch) {
|
|
|
1022
1022
|
bodyHtml,
|
|
1023
1023
|
bodyRef: "",
|
|
1024
1024
|
searchText: toSearchText(content),
|
|
1025
|
+
rstatus: data.status != null ? String(data.status) : "",
|
|
1025
1026
|
fileName,
|
|
1026
1027
|
editUrl,
|
|
1027
1028
|
fm: sanitizeFm(data),
|
package/dist/render.js
CHANGED
|
@@ -197,6 +197,47 @@ function buildTutorialData(site, codeUrl, repoSlug) {
|
|
|
197
197
|
prompt: "直近2週間の主要な動き・論点・未解決事項を、議事録や決定記録を横断してまとめてください。",
|
|
198
198
|
},
|
|
199
199
|
];
|
|
200
|
+
// ここから先は「書き込み・外部連携」の体験。案件の構成に無い能力のチャレンジは出さない(表示条件つき)
|
|
201
|
+
const tools = site.tools ?? {};
|
|
202
|
+
const internals = site.internalSources ?? [];
|
|
203
|
+
const externals = site.externalSources ?? [];
|
|
204
|
+
// メンバーの自分のレコードを直す体験(Members セクションがある案件のみ出す)
|
|
205
|
+
if ((site.sections ?? []).some((s) => s.name === "Members" || s.name === "メンバー")) {
|
|
206
|
+
specs.push({
|
|
207
|
+
title: "自分の名前を変更してみよう",
|
|
208
|
+
desc: "メンバー一覧の自分のレコードをAIに直してもらう",
|
|
209
|
+
prompt: TUT_MEMBER_PROMPT,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
// Backlogに記票する体験(課題管理にBacklogを使う案件のみ出す)
|
|
213
|
+
const usesBacklog = tools["課題管理"] === "backlog" ||
|
|
214
|
+
internals.some((s) => s.kind === "課題管理" && s.tool === "backlog" && s.enabled !== false);
|
|
215
|
+
if (usesBacklog) {
|
|
216
|
+
specs.push({
|
|
217
|
+
title: "Backlogに記票してみよう",
|
|
218
|
+
desc: "AIから自分の名義で課題にコメントする",
|
|
219
|
+
prompt: TUT_BACKLOG_PROMPT,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
// 画面インベントリを読む体験(デザインを同期している案件のみ出す)
|
|
223
|
+
const usesDesign = (tools["デザイン"] != null && tools["デザイン"] !== "none") ||
|
|
224
|
+
internals.some((s) => s.kind === "デザイン" && s.enabled !== false);
|
|
225
|
+
if (usesDesign) {
|
|
226
|
+
specs.push({
|
|
227
|
+
title: "デザインを読んでみよう",
|
|
228
|
+
desc: "画面インベントリから1画面を選んで理解する",
|
|
229
|
+
prompt: TUT_DESIGN_PROMPT,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
// 完了をSlackに知らせる体験(チャットにSlackを宣言している案件のみ出す。最終チャレンジ)
|
|
233
|
+
const usesSlack = tools["チャット"] === "slack" || externals.some((s) => s.type === "slack");
|
|
234
|
+
if (usesSlack) {
|
|
235
|
+
specs.push({
|
|
236
|
+
title: "Slackに完了を知らせよう",
|
|
237
|
+
desc: "チュートリアルの完了を案件のチャンネルに投稿する",
|
|
238
|
+
prompt: TUT_SLACK_PROMPT,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
200
241
|
return {
|
|
201
242
|
slug: repoSlug,
|
|
202
243
|
challenges: specs.map((s, i) => ({
|
|
@@ -226,6 +267,92 @@ function tutorialChallenge4Prompt(decisions) {
|
|
|
226
267
|
return (`このプロジェクトの決定「${picked.title}」(${picked.id})について、なぜこの結論に至ったのか、` +
|
|
227
268
|
"根拠になった会議や課題まで遡って経緯を説明してください。関連する未解決の論点があれば併せて教えてください。");
|
|
228
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* 書き込み・外部連携をともなうチャレンジのプロンプト。
|
|
272
|
+
* リンク先はクラウド実行のセッションでエンジンのスキルがロードされないため、規約・手順を埋め込んで自己完結させる
|
|
273
|
+
* (AI導線ボタンのプロンプトと同じ方針)。スキルが使える環境ではそちらを優先させる旨を冒頭に添える。
|
|
274
|
+
*/
|
|
275
|
+
const TUT_MEMBER_PROMPT = [
|
|
276
|
+
"(update-member スキルが使える環境なら、そのスキルの手順を優先してください。使えない場合は以下に従ってください。)",
|
|
277
|
+
"",
|
|
278
|
+
"Cortex/Members/records/ にある、わたし自身のメンバーレコードの表示名(title)を変更してください。Gold層へ書き込む練習です。名簿にわたしのレコードが無ければ、新規登録として1ファイル作ってかまいません。",
|
|
279
|
+
"",
|
|
280
|
+
"前提:",
|
|
281
|
+
"- 名簿は更新型です。氏名・所属・役割が変わったら frontmatter・本文を直接更新してかまいません(変更履歴は git が持ちます)",
|
|
282
|
+
"- 新しい表記揺れ(文字起こしの誤変換・呼称)は新規ファイルを作らず aliases に追記します",
|
|
283
|
+
"- 本人やPMに確認が取れたら status: draft を active に上げます。確証が無い項目は推測で埋めず空のままにします",
|
|
284
|
+
"- 離任しても削除せず status: inactive にします(過去の議事録・決定の人名正規化の根拠として残すため)",
|
|
285
|
+
"",
|
|
286
|
+
"手順:",
|
|
287
|
+
"1. Cortex/Members/README.md(スキーマ)と、対象になるレコードを読む",
|
|
288
|
+
"2. わたしのレコードが無ければ、ファイル名 records/{氏名(スペース無し)}.md・id member:{氏名(スペース無し)} で新規に作る",
|
|
289
|
+
"3. frontmatter の必須は type: member / id(member:{氏名(スペース無し)}) / title / description / status。任意は yomi・aliases・org・side(cm | client | vendor)・role・email。README 定義以外のフィールドは追加しない",
|
|
290
|
+
"4. 名簿に書くのは氏名・所属・役割・表記揺れだけ。人の評価・人事・単価・工数は書かない",
|
|
291
|
+
"",
|
|
292
|
+
"共通ルール:",
|
|
293
|
+
"- 書き込む前に、作成・更新する内容を提示して承認を得てください",
|
|
294
|
+
"- 同じ人に複数ファイルを作らないよう、既存レコードとの重複を必ず確認してください",
|
|
295
|
+
"- relations の target にファイルパスは書かず、安定ID(member:{氏名} / 決定ID YYYYMMDD-NNN / 課題キー 等)で張ってください",
|
|
296
|
+
"- 売上・単価・工数・人事評価などの内部限定情報は書かないでください(このリポジトリは顧客も閲覧します)",
|
|
297
|
+
].join("\n");
|
|
298
|
+
const TUT_BACKLOG_PROMPT = [
|
|
299
|
+
"(backlog-push スキルが使える環境なら、そのスキルの手順を優先してください。使えない場合は以下に従ってください。)",
|
|
300
|
+
"",
|
|
301
|
+
"Backlogの課題に、わたしの名義でコメントを1件投稿してください。Backlogの画面を開かずにAIから記票する練習です。",
|
|
302
|
+
"",
|
|
303
|
+
"Backlogのつなぎ方(本人名義で投稿するには Backlog MCP の接続が必要です):",
|
|
304
|
+
"- 手元の Claude Code(CLI・デスクトップ)なら /mcp コマンドから backlog を選んで認証する",
|
|
305
|
+
"- クラウドのセッション(claude.ai/code)なら、セッションのコネクタ設定で Backlog を有効にする",
|
|
306
|
+
"",
|
|
307
|
+
"手順:",
|
|
308
|
+
"1. どの経路で書き込むかを次の優先順で判定し、判定結果とBacklog上の名義を最初に伝える",
|
|
309
|
+
" - mcp__backlog__ で始まるツールが使えるなら、それを使う(あなた本人の名義。手元にAPIキーは不要)",
|
|
310
|
+
" - 使えない場合、環境変数 DOMAIN / PROJECT_KEY / BACKLOG_API_KEY が参照できるなら Backlog REST API を直接呼ぶ(キーの持ち主の名義)",
|
|
311
|
+
" - どちらも無ければ 課題管理/backlog-proxy.json(url / projectKey / token)を読み、その中央プロキシ経由で投稿する(共有bot名義になるため、本文の冒頭に自分の名前を記名する)",
|
|
312
|
+
" - 3つとも無ければ、上記のつなぎ方を案内して止まる",
|
|
313
|
+
"2. 課題管理/issues/ からコメントする課題を1件選ぶ(候補を挙げて確認する)。課題キーは各ファイルの「基本情報 > 課題キー」にある",
|
|
314
|
+
"3. 投稿する課題キー・本文・使う経路・Backlog上の名義を提示して、承認を得る",
|
|
315
|
+
"4. 承認後に投稿し、投稿先のURLを報告する",
|
|
316
|
+
"",
|
|
317
|
+
"注意:",
|
|
318
|
+
"- 今回はコメントの追加だけです。課題の削除・クローズ・属性変更はしないでください",
|
|
319
|
+
"- 売上・単価・工数・人事評価などの内部限定情報は書かないでください(顧客も閲覧します)",
|
|
320
|
+
].join("\n");
|
|
321
|
+
const TUT_DESIGN_PROMPT = [
|
|
322
|
+
"デザイン/inventory/ の画面インベントリから画面を1つ選び、それがどんな画面なのかを説明してください。",
|
|
323
|
+
"",
|
|
324
|
+
"手順:",
|
|
325
|
+
"1. デザイン/inventory/ を一覧し、主要そうな画面を1つ選ぶ(1画面1ファイル。frontmatter に安定ID design:{fileKey}:{nodeId} とFigmaへのディープリンクがあります)",
|
|
326
|
+
"2. その画面のファイルを読み、画面の役割・主な要素・前後の画面とのつながりを、読み取れる範囲で説明する",
|
|
327
|
+
"3. 関連する決定(Cortex/Decisions/)・用語(Cortex/Glossary/)・課題(課題管理/issues/)があれば、安定IDをたどって補足する",
|
|
328
|
+
"4. 最後に、Figmaで実物を開くリンクを提示する",
|
|
329
|
+
"",
|
|
330
|
+
"注意:",
|
|
331
|
+
"- 読むだけです。ファイルの作成・更新はしないでください",
|
|
332
|
+
"- インベントリはFigmaからの同期で上書きされる生成物です。手で編集しないでください",
|
|
333
|
+
].join("\n");
|
|
334
|
+
const TUT_SLACK_PROMPT = [
|
|
335
|
+
"Cortex のチュートリアルを完了したことを、この案件の Slack チャンネルに投稿してください。最後のステップです。",
|
|
336
|
+
"",
|
|
337
|
+
"Slackのつなぎ方:",
|
|
338
|
+
"- 手元の Claude Code(CLI・デスクトップ)なら /mcp コマンドから slack を選んで認可する",
|
|
339
|
+
"- クラウドのセッション(claude.ai/code)なら、セッションのコネクタ設定で Slack を有効にする",
|
|
340
|
+
"- どちらもできない場合は、その旨とつなぎ方を案内して止まってください",
|
|
341
|
+
"",
|
|
342
|
+
"手順:",
|
|
343
|
+
"1. チャット/channels.json を読み、登録されているチャンネル(name / url / description)から投稿先を選ぶ。複数あれば description を見て判断し、迷ったら確認する",
|
|
344
|
+
"2. 次の雛形で本文を作る({名前} は Cortex/Members/records/ にあるわたしのレコードの表記に合わせる)",
|
|
345
|
+
"",
|
|
346
|
+
"🎉 {名前} さんが Cortex のチュートリアルを完了しました",
|
|
347
|
+
"できるようになったこと: Gold層から案件を把握する・自分の情報を更新する・Backlogに記票する・資料を投入する",
|
|
348
|
+
"使い方の質問はこのチャンネルへどうぞ",
|
|
349
|
+
"",
|
|
350
|
+
"3. 投稿先のチャンネルと本文をプレビューして、承認を得る",
|
|
351
|
+
"4. 承認後に投稿し、投稿したメッセージのリンクを報告する",
|
|
352
|
+
"",
|
|
353
|
+
"注意:",
|
|
354
|
+
"- 売上・単価・工数・人事評価などの内部限定情報は書かないでください",
|
|
355
|
+
].join("\n");
|
|
229
356
|
const CSS = `
|
|
230
357
|
:root {
|
|
231
358
|
--bg: #f6f7f9;
|
|
@@ -457,13 +584,9 @@ a:hover { text-decoration: underline; }
|
|
|
457
584
|
.badge.cat-インフラ { background: #efe9fb; color: #6d28d9; }
|
|
458
585
|
.badge.cat-ビジネス { background: #fde9ef; color: #be185d; }
|
|
459
586
|
.badge.cat-デザイン { background: #fce7f3; color: #a21caf; }
|
|
460
|
-
.badge.draft { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
|
|
461
587
|
.badge.error { background: #fee2e2; color: #b91c1c; border: 1px solid #fca5a5; }
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
background: #fffbeb; border: 1px solid #fcd34d; border-radius: 8px;
|
|
465
|
-
padding: 10px 14px; margin: 12px 0 4px; font-size: 13.5px; color: #92400e; line-height: 1.7;
|
|
466
|
-
}
|
|
588
|
+
/* 未確認(status: draft = AI生成・人間未確認)の印。ほとんどのレコードが該当しうるため色もアイコンも使わない */
|
|
589
|
+
.unverified { margin-left: 8px; font-size: 11.5px; font-weight: 400; color: var(--muted); white-space: nowrap; }
|
|
467
590
|
.adoption-note {
|
|
468
591
|
display: flex; gap: 8px; align-items: flex-start;
|
|
469
592
|
background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 8px;
|
|
@@ -491,6 +614,24 @@ a:hover { text-decoration: underline; }
|
|
|
491
614
|
box-shadow: var(--shadow); white-space: nowrap;
|
|
492
615
|
}
|
|
493
616
|
.edit-btn:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
|
|
617
|
+
/* ---- AI導線ボタン(AIで編集・+AIで登録。claude.ai/code へのディープリンク・AIアクションはオレンジ系で統一) ---- */
|
|
618
|
+
.ai-edit-btn {
|
|
619
|
+
-webkit-backdrop-filter: blur(10px) saturate(150%); backdrop-filter: blur(10px) saturate(150%);
|
|
620
|
+
flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
|
|
621
|
+
padding: 8px 14px; border: 1px solid rgba(217,119,87,0.55); border-radius: var(--radius);
|
|
622
|
+
background: rgba(217,119,87,0.1); color: #b45309; font-size: 13.5px; font-weight: 600;
|
|
623
|
+
box-shadow: var(--shadow); white-space: nowrap;
|
|
624
|
+
}
|
|
625
|
+
.ai-edit-btn:hover { background: rgba(217,119,87,0.18); border-color: rgba(217,119,87,0.85); text-decoration: none; }
|
|
626
|
+
.ai-add-bar { margin-bottom: 16px; }
|
|
627
|
+
.ai-add-btn {
|
|
628
|
+
display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; border-radius: 999px;
|
|
629
|
+
border: 1px solid rgba(255,255,255,0.55); background: rgba(217,119,87,0.82); color: #fff;
|
|
630
|
+
font-size: 13px; font-weight: 600; white-space: nowrap;
|
|
631
|
+
-webkit-backdrop-filter: blur(12px) saturate(160%); backdrop-filter: blur(12px) saturate(160%);
|
|
632
|
+
box-shadow: 0 2px 10px rgba(190,90,60,0.3), inset 0 1px 0 rgba(255,255,255,0.45);
|
|
633
|
+
}
|
|
634
|
+
.ai-add-btn:hover { background: rgba(194,94,63,0.92); text-decoration: none; }
|
|
494
635
|
.section-label { font-size: 12px; font-weight: 700; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; margin: 24px 0 8px; }
|
|
495
636
|
/* ---- はじめに(チュートリアル・Homeタブ下部) ---- */
|
|
496
637
|
.tut-section { margin-top: 34px; padding-top: 22px; border-top: 1px solid var(--border); }
|
|
@@ -737,13 +878,19 @@ const CLIENT_JS = `
|
|
|
737
878
|
// 本文は bodies/<i>.html に外出しされ詳細表示時に fetch されるため、linkify は loadBody 側で適用する
|
|
738
879
|
// (ここで inline bodyHtml に適用すると検索テキストにHTMLが混ざるため適用しない)。
|
|
739
880
|
|
|
881
|
+
// Gold層ディレクトリ名(英語)→ タブ・フォルダの表示名(日本語)の辞書。
|
|
882
|
+
// 辞書に無いディレクトリはディレクトリ名のまま表示する(案件が独自ディレクトリを足しても壊れない)。
|
|
883
|
+
// 内部の識別子(タブkey・フォルダ状態)は英語ディレクトリ名のまま扱い、表示だけ差し替える。
|
|
884
|
+
var DIR_LABELS = { Decisions: "決定事項", Glossary: "用語集", Members: "メンバー", Rules: "ルール" };
|
|
885
|
+
function dirLabel(name) { return DIR_LABELS[name] || name; }
|
|
886
|
+
|
|
740
887
|
// タブ: ホーム → Decisions → records/ を持つ各ディレクトリ(自動発見)
|
|
741
888
|
// オンボーディングのチュートリアル(5チャレンジ)は独立タブを廃止し、Homeタブ下部に統合した
|
|
742
889
|
var TABS = [];
|
|
743
890
|
if (SITE.home) TABS.push({ key: "home", label: "Home" });
|
|
744
|
-
TABS.push({ key: "decisions", label: "Decisions", items: SITE.decisions });
|
|
891
|
+
TABS.push({ key: "decisions", label: dirLabel("Decisions"), items: SITE.decisions });
|
|
745
892
|
(SITE.sections || []).forEach(function (sec) {
|
|
746
|
-
TABS.push({ key: "dir:" + sec.name, label: sec.name, items: sec.records });
|
|
893
|
+
TABS.push({ key: "dir:" + sec.name, label: dirLabel(sec.name), items: sec.records });
|
|
747
894
|
});
|
|
748
895
|
if (SITE.graph && SITE.graph.nodes.length > 0) {
|
|
749
896
|
TABS.push({ key: "graph", label: "ナレッジグラフ" });
|
|
@@ -786,6 +933,208 @@ const CLIENT_JS = `
|
|
|
786
933
|
function catBadge(cat) {
|
|
787
934
|
return el("span", { class: "badge cat-" + cat, text: cat || "未分類" });
|
|
788
935
|
}
|
|
936
|
+
// 未確認(status: draft = AI生成・人間未確認)の印。タイトル脇に小さく添えるだけで、active・status無しには何も出さない
|
|
937
|
+
function unverifiedMark(rec) {
|
|
938
|
+
return rec && rec.rstatus === "draft" ? el("span", { class: "unverified", text: "未確認" }) : null;
|
|
939
|
+
}
|
|
940
|
+
// 未確認の絞り込み(フィルタのセレクトの選択肢は draft の1つだけ)
|
|
941
|
+
function statusLabel(v) { return v === "draft" ? "未確認のみ" : v; }
|
|
942
|
+
// 未確認が1件も無い一覧では絞り込みを出さない
|
|
943
|
+
function hasUnverified(items) {
|
|
944
|
+
return (items || []).some(function (r) { return r.rstatus === "draft"; });
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
// ---------- AI導線(Gold層への人間の書き込み口。claude.ai/code へのディープリンク) ----------
|
|
948
|
+
// ヘッダー「AIに聞く」と同じ方式。repoBaseUrl から slug を導出し、プロンプトを入力済みで Claude Code Web を開く。
|
|
949
|
+
var REPO_SLUG = SITE.repoBaseUrl
|
|
950
|
+
? SITE.repoBaseUrl.replace(/^https?:\\/\\/github\\.com\\//, "").replace(/\\.git$/, "")
|
|
951
|
+
: "";
|
|
952
|
+
function codeUrl(prompt) {
|
|
953
|
+
return REPO_SLUG
|
|
954
|
+
? "https://claude.ai/code?repo=" + REPO_SLUG + "&prompt=" + encodeURIComponent(prompt)
|
|
955
|
+
: "https://claude.ai/code/";
|
|
956
|
+
}
|
|
957
|
+
// editUrl(.../edit/<branch>/<path>)からリポジトリ相対のファイルパスを取り出す(プロンプトで対象を指し示すため)
|
|
958
|
+
function repoPathOf(rec) {
|
|
959
|
+
if (!rec || !rec.editUrl) return "";
|
|
960
|
+
var m = rec.editUrl.match(/\\/edit\\/[^/]+\\/(.+)$/);
|
|
961
|
+
return m ? decodeURIComponent(m[1]) : "";
|
|
962
|
+
}
|
|
963
|
+
// Gold型(ディレクトリ名)→ 書き込みプロンプトの対応。決定事項/用語集/メンバー/ルールの4型のみ。
|
|
964
|
+
// レポート等スキルの無いディレクトリは対象外(ボタンを出さない)。
|
|
965
|
+
// リンク先はクラウド実行のセッションでエンジンのスキルがロードされないため、プロンプトには規約を埋め込んで自己完結させる。
|
|
966
|
+
// スキルが使える環境(手元のCLI・デスクトップ等)ではそちらを優先させる旨を冒頭に添える。
|
|
967
|
+
function aiHead(skill) {
|
|
968
|
+
return "(" + skill + " スキルが使える環境なら、そのスキルの手順を優先してください。使えない場合は以下に従ってください。)\\n\\n";
|
|
969
|
+
}
|
|
970
|
+
// 4型すべてに付ける共通の規律(承認・重複・安定ID・公開範囲)
|
|
971
|
+
var AI_COMMON = [
|
|
972
|
+
"",
|
|
973
|
+
"",
|
|
974
|
+
"共通ルール:",
|
|
975
|
+
"- 書き込む前に、作成・更新する内容を提示して承認を得てください",
|
|
976
|
+
"- 同じ対象に複数ファイルを作らないよう、既存レコードとの重複を必ず確認してください",
|
|
977
|
+
"- relations の target にファイルパスは書かず、安定ID(決定ID YYYYMMDD-NNN / term:{代表表記} / rule:{slug} / member:{氏名} / 課題キー / minute:{定例名}:{YYYYMMDD})で張ってください",
|
|
978
|
+
"- 売上・単価・工数・人事評価などの内部限定情報は書かないでください(このリポジトリは顧客も閲覧します)",
|
|
979
|
+
].join("\\n");
|
|
980
|
+
var GOLD_SKILL = {
|
|
981
|
+
"Decisions": {
|
|
982
|
+
skill: "update-decision",
|
|
983
|
+
noun: "決定",
|
|
984
|
+
add: [
|
|
985
|
+
"これから伝える決定事項を Cortex/Decisions/records/ に1決定1ファイルで記録してください。",
|
|
986
|
+
"",
|
|
987
|
+
"手順:",
|
|
988
|
+
"1. Cortex/Decisions/README.md(フィールド定義・カテゴリー一覧)と Cortex/Decisions/template.md を読む",
|
|
989
|
+
"2. 既存の records/ を一覧し、同じ決定が記録済みでないかと、決定日の連番の続きを確認する",
|
|
990
|
+
"3. ファイル名は YYYYMMDD-NNN-決定内容の要約.md(YYYYMMDD=決定日、NNN=同日内の連番)",
|
|
991
|
+
"4. frontmatter の必須は type: decision / id(YYYYMMDD-NNN) / title / date / sprint(スプリント運用が無ければフェーズ名) / category(ビジネス・技術選定・設計方針・運用ルール・インフラ・デザインから選ぶ) / deciders(Cortex/Members/records/ の正式表記に揃える。名簿に無い人名は「(要確認)」を付ける) / description(1文要約) / references(出典への人間向けリンク)。README 定義以外のフィールドは追加しない",
|
|
992
|
+
"5. 根拠がある場合は relations に rel: based_on で安定IDを張る(議事録は minute:{定例名}:{YYYYMMDD}、課題は課題キー)",
|
|
993
|
+
"6. 本文は「# タイトル」「## 背景」(なぜ必要になったか)「## 理由」(なぜその選択をしたか・他案との比較)",
|
|
994
|
+
"7. 過去の決定を変える内容なら、その記録は書き換えず新しい記録を作り、relations に rel: supersedes で元の決定IDを張る",
|
|
995
|
+
"8. 確定した決定だけを記録する(検討中・未確定の議論は記録しない)",
|
|
996
|
+
].join("\\n"),
|
|
997
|
+
edit: function (target) {
|
|
998
|
+
return [
|
|
999
|
+
target + "について、これから伝える変更を反映してください。",
|
|
1000
|
+
"",
|
|
1001
|
+
"重要: 決定の内容そのものが変わる場合、この記録は書き換えません。Cortex/Decisions/records/ に新しいファイル(YYYYMMDD-NNN-決定内容の要約.md。YYYYMMDD=新しい決定日、NNN=同日内の連番)を作り、frontmatter の relations に rel: supersedes / target: 元の決定ID を張って、背景・理由に変更の経緯を書いてください。誤字・リンク切れなど決定の中身が変わらない訂正だけ、その場で直してかまいません。",
|
|
1002
|
+
"",
|
|
1003
|
+
"手順:",
|
|
1004
|
+
"1. Cortex/Decisions/README.md(フィールド定義・カテゴリー一覧)と対象ファイルを読む",
|
|
1005
|
+
"2. 新しい記録を作る場合は、既存の records/ で連番の続きと重複を確認する",
|
|
1006
|
+
"3. frontmatter の必須は type: decision / id / title / date / sprint / category / deciders(Cortex/Members/records/ の正式表記に揃える) / description / references。README 定義以外のフィールドは追加しない",
|
|
1007
|
+
"4. 本文は「# タイトル」「## 背景」「## 理由」の構成を保つ",
|
|
1008
|
+
"5. あなた(人間)が内容を確認して編集したので、status が draft(AI生成・人間未確認)なら active に上げる。内容を確認せず表記・形式だけ直した場合は draft のままにする",
|
|
1009
|
+
].join("\\n");
|
|
1010
|
+
},
|
|
1011
|
+
},
|
|
1012
|
+
"Glossary": {
|
|
1013
|
+
skill: "update-glossary",
|
|
1014
|
+
noun: "用語",
|
|
1015
|
+
add: [
|
|
1016
|
+
"これから伝える用語を Cortex/Glossary/records/ に1用語1ファイルで登録してください。",
|
|
1017
|
+
"",
|
|
1018
|
+
"手順:",
|
|
1019
|
+
"1. Cortex/Glossary/README.md(スキーマ・除外用語リスト)と Cortex/Glossary/template.md を読む",
|
|
1020
|
+
"2. 既存 records/ の title と synonyms を確認する。既存用語の表記揺れなら新規ファイルを作らず、その用語の synonyms に追記する。除外用語リストに載っている語は登録しない",
|
|
1021
|
+
"3. ファイル名は records/{代表表記}.md、id は term:{代表表記}",
|
|
1022
|
+
"4. frontmatter の必須は type: term / id / title / description(1文要約) / scope(project=案件固有 | organization=全社共通) / status / date(登録日)。任意は synonyms(表記揺れ)・source(この案件での出典)・references。README 定義以外のフィールドは追加しない",
|
|
1023
|
+
"5. 案件固有語は社内の情報源(議事録・課題・資料)の記述だけを根拠に定義する(Web検索せず references も付けない)。Figma・OIDC のような一般公開のサービス・技術・規格は、Web で公式ドキュメント等の一次情報を確認してから定義し、そのURLを references に入れる。推測で書かない",
|
|
1024
|
+
"6. 定義を人間と確認できた場合のみ status: active。確証が持てなければ status: draft(AI生成・人間未確認の印)にする",
|
|
1025
|
+
"7. 本文にはこの案件における意味を1〜数段落で具体的に書く(一般的な意味に加え、この案件で特殊な使われ方があれば補足する)",
|
|
1026
|
+
].join("\\n"),
|
|
1027
|
+
edit: function (target) {
|
|
1028
|
+
return [
|
|
1029
|
+
target + "について、これから伝える修正を反映してください。",
|
|
1030
|
+
"",
|
|
1031
|
+
"前提:",
|
|
1032
|
+
"- 用語集は更新型です。定義が変わったら本文・frontmatter を直接更新してかまいません(変更履歴は git が持ちます)",
|
|
1033
|
+
"- 新しい表記揺れは新規ファイルを作らず synonyms に追記します",
|
|
1034
|
+
"- 定義を人間と確認できたら status: draft を active に上げます",
|
|
1035
|
+
"- 使われなくなった用語は削除せず status: superseded にします",
|
|
1036
|
+
"",
|
|
1037
|
+
"手順:",
|
|
1038
|
+
"1. Cortex/Glossary/README.md(スキーマ)と対象ファイルを読む",
|
|
1039
|
+
"2. frontmatter の必須は type: term / id(term:{代表表記}) / title / description / scope / status / date。README 定義以外のフィールドは追加しない",
|
|
1040
|
+
"3. 一般公開のサービス・技術・規格は Web で公式ドキュメント等の一次情報を確認してから定義を直し、references にそのURLを入れる。案件固有語は社内の情報源だけを根拠にし、推測で書かない",
|
|
1041
|
+
"4. あなた(人間)が内容を確認して編集したので、status が draft(AI生成・人間未確認)なら active に上げる。内容を確認せず表記・形式だけ直した場合は draft のままにする",
|
|
1042
|
+
].join("\\n");
|
|
1043
|
+
},
|
|
1044
|
+
},
|
|
1045
|
+
"Members": {
|
|
1046
|
+
skill: "update-member",
|
|
1047
|
+
noun: "メンバー",
|
|
1048
|
+
add: [
|
|
1049
|
+
"これから伝えるメンバーを Cortex/Members/records/ に1人1ファイルで登録してください。",
|
|
1050
|
+
"",
|
|
1051
|
+
"手順:",
|
|
1052
|
+
"1. Cortex/Members/README.md(スキーマ)と Cortex/Members/template.md を読む",
|
|
1053
|
+
"2. 既存 records/ の title・aliases・side を確認する。既存メンバーの表記揺れなら新規ファイルを作らず、その人の aliases に追記する(同一人物に複数ファイルを作らない)",
|
|
1054
|
+
"3. ファイル名は records/{氏名(スペース無し)}.md、id は member:{氏名(スペース無し)}",
|
|
1055
|
+
"4. frontmatter の必須は type: member / id / title(氏名の正式表記。スペースを含んでよい) / description(何者かの1文) / status(active=在籍 | inactive=離任 | draft=AI生成・人間未確認)。任意は yomi・aliases・org・side(cm=開発側 | client=顧客 | vendor=ベンダー)・role・email。README 定義以外のフィールドは追加しない",
|
|
1056
|
+
"5. 氏名・所属・side を推測で確定させない。確証が無い項目は空にし、確認が取れていないレコードは status: draft のままにする",
|
|
1057
|
+
"6. 本文にも何者かを1〜2文書く(Viewer の個別ページに表示されるため空にしない)",
|
|
1058
|
+
"7. 名簿に書くのは氏名・所属・役割・表記揺れだけ。人の評価・人事・単価・工数は書かない",
|
|
1059
|
+
].join("\\n"),
|
|
1060
|
+
edit: function (target) {
|
|
1061
|
+
return [
|
|
1062
|
+
target + "について、これから伝える修正を反映してください。",
|
|
1063
|
+
"",
|
|
1064
|
+
"前提:",
|
|
1065
|
+
"- 名簿は更新型です。氏名・所属・役割が変わったら frontmatter・本文を直接更新してかまいません(変更履歴は git が持ちます)",
|
|
1066
|
+
"- 新しい表記揺れ(文字起こしの誤変換・呼称)は新規ファイルを作らず aliases に追記します",
|
|
1067
|
+
"- 本人やPMに確認が取れたら status: draft を active に上げます。確証が無い項目は推測で埋めず空のままにします",
|
|
1068
|
+
"- 離任しても削除せず status: inactive にします(過去の議事録・決定の人名正規化の根拠として残すため)",
|
|
1069
|
+
"",
|
|
1070
|
+
"手順:",
|
|
1071
|
+
"1. Cortex/Members/README.md(スキーマ)と対象ファイルを読む",
|
|
1072
|
+
"2. frontmatter の必須は type: member / id(member:{氏名(スペース無し)}) / title / description / status。任意は yomi・aliases・org・side(cm | client | vendor)・role・email。README 定義以外のフィールドは追加しない",
|
|
1073
|
+
"3. 名簿に書くのは氏名・所属・役割・表記揺れだけ。人の評価・人事・単価・工数は書かない",
|
|
1074
|
+
"4. あなた(人間)が内容を確認して編集したので、status が draft(AI生成・人間未確認)なら active に上げる。内容を確認せず表記・形式だけ直した場合は draft のままにする",
|
|
1075
|
+
].join("\\n");
|
|
1076
|
+
},
|
|
1077
|
+
},
|
|
1078
|
+
"Rules": {
|
|
1079
|
+
skill: "update-rule",
|
|
1080
|
+
noun: "ルール",
|
|
1081
|
+
add: [
|
|
1082
|
+
"これから伝えるルール(案件で継続的に守る制約)を Cortex/Rules/records/ に1ルール1ファイルで登録してください。",
|
|
1083
|
+
"",
|
|
1084
|
+
"手順:",
|
|
1085
|
+
"1. Cortex/Rules/README.md(スキーマ・除外ルールリスト)と Cortex/Rules/template.md を読む",
|
|
1086
|
+
"2. Rule と Decision を判別する。Rule は「本番リリースは金曜禁止」のように今も効き続ける約束事だけ。一回きりの決定・単発のTODO・期限付きの依頼は Rule にしない(それは Cortex/Decisions/ の担当)",
|
|
1087
|
+
"3. 既存 records/ の title を確認して重複を避ける。README の除外ルールに載っている制約は起票しない(除外リストは読むだけで編集しない)",
|
|
1088
|
+
"4. ファイル名は records/{slug}.md、id は rule:{slug}(例: rule:本番リリース-金曜禁止)",
|
|
1089
|
+
"5. frontmatter の必須は type: rule / id / title(制約の1行表現) / description(1文要約) / status(draft=AI生成・人間未確認 | active=確認済み)。README 定義以外のフィールドは追加しない",
|
|
1090
|
+
"6. status は原則 draft。対話でユーザー本人が制約の内容に合意している場合だけ active にしてよい",
|
|
1091
|
+
"7. 元になった決定があれば relations に rel: derived_from / target: 決定ID(YYYYMMDD-NNN)を、議事録・課題が根拠なら rel: based_on で安定IDを張る",
|
|
1092
|
+
"8. 本文は「## 制約」「## 適用範囲」「## 違反するとどうなるか」「## 出典」で構成する",
|
|
1093
|
+
].join("\\n"),
|
|
1094
|
+
edit: function (target) {
|
|
1095
|
+
return [
|
|
1096
|
+
target + "について、これから伝える修正を反映してください。",
|
|
1097
|
+
"",
|
|
1098
|
+
"前提:",
|
|
1099
|
+
"- ルールは更新型です。制約の表現・適用範囲が変わったら frontmatter・本文を直接更新してかまいません(変更履歴は git が持ちます)",
|
|
1100
|
+
"- 内容を人間と確認できたら status: draft を active に上げます(本人の合意が無いものを勝手に active にしない)",
|
|
1101
|
+
"- 効かなくなったルールは削除せず、本文に失効を追記して元の決定から履歴をたどれるようにします",
|
|
1102
|
+
"- 継続的な制約でなくなる内容(一回きりの決定)は Rule ではなく Cortex/Decisions/ の担当です",
|
|
1103
|
+
"",
|
|
1104
|
+
"手順:",
|
|
1105
|
+
"1. Cortex/Rules/README.md(スキーマ・除外ルール)と対象ファイルを読む",
|
|
1106
|
+
"2. frontmatter の必須は type: rule / id(rule:{slug}) / title / description / status。README 定義以外のフィールドは追加しない",
|
|
1107
|
+
"3. 本文は「## 制約」「## 適用範囲」「## 違反するとどうなるか」「## 出典」の構成を保つ",
|
|
1108
|
+
"4. あなた(人間)が内容を確認して編集したので、status が draft(AI生成・人間未確認)なら active に上げる。内容を確認せず表記・形式だけ直した場合は draft のままにする",
|
|
1109
|
+
].join("\\n");
|
|
1110
|
+
},
|
|
1111
|
+
},
|
|
1112
|
+
};
|
|
1113
|
+
// ディレクトリ名が日本語の案件(用語集 等)でも同じ4型に解決できるよう、表示名(DIR_LABELS)→英語キーの別名も引く
|
|
1114
|
+
var GOLD_ALIAS = { "決定事項": "Decisions", "用語集": "Glossary", "メンバー": "Members", "ルール": "Rules" };
|
|
1115
|
+
function goldSkill(sectionName) {
|
|
1116
|
+
return GOLD_SKILL[sectionName] || GOLD_SKILL[GOLD_ALIAS[sectionName]] || null;
|
|
1117
|
+
}
|
|
1118
|
+
// セクション(Gold型)の一覧上部に置く「+AIで登録」ボタン。スキルの無いディレクトリでは null
|
|
1119
|
+
function aiAddBar(sectionName) {
|
|
1120
|
+
var g = goldSkill(sectionName);
|
|
1121
|
+
if (!g) return null;
|
|
1122
|
+
var prompt = aiHead(g.skill) + g.add + AI_COMMON;
|
|
1123
|
+
return el("div", { class: "ai-add-bar" }, [
|
|
1124
|
+
el("a", { class: "ai-add-btn", href: codeUrl(prompt), target: "_blank", rel: "noopener", text: "+ AIで登録" }),
|
|
1125
|
+
]);
|
|
1126
|
+
}
|
|
1127
|
+
// 各Goldレコードの「AIで編集」ボタン(GitHubで編集の隣)。スキルの無い型では null
|
|
1128
|
+
function aiEditBtn(rec, sectionName, title) {
|
|
1129
|
+
var g = goldSkill(sectionName);
|
|
1130
|
+
if (!g) return null;
|
|
1131
|
+
var pathRef = repoPathOf(rec);
|
|
1132
|
+
var target = pathRef
|
|
1133
|
+
? pathRef + " の" + g.noun + "「" + title + "」"
|
|
1134
|
+
: "この" + g.noun + "「" + title + "」(" + rec.id + ")";
|
|
1135
|
+
var prompt = aiHead(g.skill) + g.edit(target) + AI_COMMON;
|
|
1136
|
+
return el("a", { class: "ai-edit-btn", href: codeUrl(prompt), target: "_blank", rel: "noopener", text: "AIで編集" });
|
|
1137
|
+
}
|
|
789
1138
|
// 本文HTMLは bodies/<i>.html に外出しされている。詳細表示時にfetchして埋める(キャッシュ・失敗時フォールバック付き)
|
|
790
1139
|
var bodyCache = {};
|
|
791
1140
|
function loadBody(rec, mount) {
|
|
@@ -812,7 +1161,7 @@ const CLIENT_JS = `
|
|
|
812
1161
|
window.scrollTo(0, 0);
|
|
813
1162
|
}
|
|
814
1163
|
|
|
815
|
-
var listState = { tab: DEFAULT_TAB, q: "", category: "", month: "", page: 1 };
|
|
1164
|
+
var listState = { tab: DEFAULT_TAB, q: "", category: "", month: "", status: "", page: 1 };
|
|
816
1165
|
|
|
817
1166
|
// 一覧のページネーション(描画コスト対策。1ページあたりの件数)
|
|
818
1167
|
var PAGE_SIZE = 30;
|
|
@@ -869,11 +1218,14 @@ const CLIENT_JS = `
|
|
|
869
1218
|
btnLabel: "実行履歴を確認 →",
|
|
870
1219
|
btnUrl: base ? base + "/actions/workflows/update-decision-log.yml" : null,
|
|
871
1220
|
},
|
|
872
|
-
"dir
|
|
873
|
-
text: "毎晩の自動走査が新しい用語を draft として直接追加します(update-glossary-auto)。AI
|
|
1221
|
+
"dir:Glossary": {
|
|
1222
|
+
text: "毎晩の自動走査が新しい用語を draft として直接追加します(update-glossary-auto)。AIが生成した定義は仮のものです。「未確認」の用語は内容を確認し、適切な定義に置き換えて status: active にしてください。",
|
|
874
1223
|
btnLabel: "実行履歴を確認 →",
|
|
875
1224
|
btnUrl: base ? base + "/actions/workflows/update-glossary.yml" : null,
|
|
876
1225
|
},
|
|
1226
|
+
"dir:Rules": {
|
|
1227
|
+
text: "案件で継続的に守る制約・ルールの一覧です。AIはここを読んで、違反する提案を避けます。",
|
|
1228
|
+
},
|
|
877
1229
|
"graph": {
|
|
878
1230
|
text: "決定・用語・レポートと、その根拠になった課題・議事録・資料のつながりを自動でつないだ地図です。点をクリックすると、そのページや実際のシステム(Backlog・GitHub等)に移動できます。",
|
|
879
1231
|
},
|
|
@@ -881,9 +1233,7 @@ const CLIENT_JS = `
|
|
|
881
1233
|
text: "決定・用語・レポートを起点に、つながり(根拠・出典・リンク)を1列ずつ辿る表示です。行をクリックすると右に次の列が開きます。",
|
|
882
1234
|
},
|
|
883
1235
|
"dir:レポート": {
|
|
884
|
-
text: "
|
|
885
|
-
btnLabel: "実行履歴を確認 →",
|
|
886
|
-
btnUrl: base ? base + "/actions/workflows/weekly-report.yml" : null,
|
|
1236
|
+
text: "レポートの生成は終了し、履歴として凍結されています(レポートはSlack配信に一本化されました)。以下は過去に生成されたレコードです。",
|
|
887
1237
|
},
|
|
888
1238
|
};
|
|
889
1239
|
var infoKey = listState.tab === "graph" ? (knowledgeView === "map" ? "graph" : "explorer") : listState.tab;
|
|
@@ -938,8 +1288,8 @@ const CLIENT_JS = `
|
|
|
938
1288
|
if (!challenges.length) return; // 最小データ(チュートリアル無し)では出さない
|
|
939
1289
|
|
|
940
1290
|
var sec = el("section", { class: "tut-section" });
|
|
941
|
-
sec.appendChild(el("h2", { class: "tut-section-head", text: "はじめに — このプロジェクトを掴む
|
|
942
|
-
sec.appendChild(el("p", { class: "tut-intro", text: "AIS Viewer と Claude Code を使ってこのプロジェクトを掴むための
|
|
1291
|
+
sec.appendChild(el("h2", { class: "tut-section-head", text: "はじめに — このプロジェクトを掴む" + challenges.length + "ステップ" }));
|
|
1292
|
+
sec.appendChild(el("p", { class: "tut-intro", text: "AIS Viewer と Claude Code を使ってこのプロジェクトを掴むための" + challenges.length + "ステップです。各ボタンを押すと、質問が入力済みの状態で Claude Code Web が開きます(このリポジトリへのアクセス権が必要です)。" }));
|
|
943
1293
|
|
|
944
1294
|
// 進捗ヘッダ({完了数}/5・バー・全完了で祝福)
|
|
945
1295
|
var doneCount = challenges.filter(function (c) { return tutIsDone(c.n); }).length;
|
|
@@ -1401,8 +1751,14 @@ const CLIENT_JS = `
|
|
|
1401
1751
|
filters.appendChild(buildSelect("すべての期間", SITE.months, listState.month, function (v) { listState.month = v; listState.page = 1; drawCards(); }, monthLabel));
|
|
1402
1752
|
}
|
|
1403
1753
|
filters.appendChild(buildSelect("すべてのカテゴリー", SITE.categories, listState.category, function (v) { listState.category = v; listState.page = 1; drawCards(); }));
|
|
1754
|
+
if (hasUnverified(SITE.decisions)) {
|
|
1755
|
+
filters.appendChild(buildSelect("すべての状態", ["draft"], listState.status, function (v) { listState.status = v; listState.page = 1; drawCards(); }, statusLabel));
|
|
1756
|
+
}
|
|
1404
1757
|
app.appendChild(filters);
|
|
1405
1758
|
|
|
1759
|
+
var addBarD = aiAddBar("Decisions");
|
|
1760
|
+
if (addBarD) app.appendChild(addBarD);
|
|
1761
|
+
|
|
1406
1762
|
var listWrap = el("div", { class: "card-list", id: "card-list" });
|
|
1407
1763
|
app.appendChild(listWrap);
|
|
1408
1764
|
drawCards();
|
|
@@ -1425,6 +1781,7 @@ const CLIENT_JS = `
|
|
|
1425
1781
|
var items = SITE.decisions.filter(function (d) {
|
|
1426
1782
|
if (listState.month && d.date.slice(0, 7) !== listState.month) return false;
|
|
1427
1783
|
if (listState.category && d.category !== listState.category) return false;
|
|
1784
|
+
if (listState.status && d.rstatus !== listState.status) return false;
|
|
1428
1785
|
if (q) {
|
|
1429
1786
|
var hay = (d.title + " " + d.summary + " " + d.searchText + " " + d.deciders.join(" ")).toLowerCase();
|
|
1430
1787
|
if (hay.indexOf(q) === -1) return false;
|
|
@@ -1459,7 +1816,7 @@ const CLIENT_JS = `
|
|
|
1459
1816
|
meta.appendChild(traceD);
|
|
1460
1817
|
var card = el("div", { class: "card" }, [
|
|
1461
1818
|
meta,
|
|
1462
|
-
el("div", { class: "card-title", text: d.title }),
|
|
1819
|
+
el("div", { class: "card-title", text: d.title }, [unverifiedMark(d)]),
|
|
1463
1820
|
d.summary ? el("p", { class: "card-summary", text: d.summary }) : null,
|
|
1464
1821
|
]);
|
|
1465
1822
|
card.addEventListener("click", function () { go(d.id); });
|
|
@@ -1480,14 +1837,21 @@ const CLIENT_JS = `
|
|
|
1480
1837
|
var search = el("input", { type: "search", placeholder: "キーワード検索" });
|
|
1481
1838
|
search.value = listState.q;
|
|
1482
1839
|
filters.appendChild(search);
|
|
1840
|
+
if (hasUnverified(items)) {
|
|
1841
|
+
filters.appendChild(buildSelect("すべての状態", ["draft"], listState.status, function (v) { listState.status = v; listState.page = 1; draw(); }, statusLabel));
|
|
1842
|
+
}
|
|
1483
1843
|
app.appendChild(filters);
|
|
1484
1844
|
|
|
1845
|
+
var addBarG = aiAddBar(listState.tab.replace(/^dir:/, ""));
|
|
1846
|
+
if (addBarG) app.appendChild(addBarG);
|
|
1847
|
+
|
|
1485
1848
|
var listWrap = el("div", { class: "card-list" });
|
|
1486
1849
|
app.appendChild(listWrap);
|
|
1487
1850
|
|
|
1488
1851
|
function draw() {
|
|
1489
1852
|
var q = listState.q.trim().toLowerCase();
|
|
1490
1853
|
var shown = items.filter(function (r) {
|
|
1854
|
+
if (listState.status && r.rstatus !== listState.status) return false;
|
|
1491
1855
|
if (!q) return true;
|
|
1492
1856
|
return (r.title + " " + r.summary + " " + r.searchText).toLowerCase().indexOf(q) !== -1;
|
|
1493
1857
|
});
|
|
@@ -1503,7 +1867,6 @@ const CLIENT_JS = `
|
|
|
1503
1867
|
(pg.pages > 1 ? "(" + pg.page + "/" + pg.pages + "ページ)" : "");
|
|
1504
1868
|
pg.slice.forEach(function (r) {
|
|
1505
1869
|
var meta = el("div", { class: "card-meta" }, [
|
|
1506
|
-
r.rstatus === "draft" ? el("span", { class: "badge draft", text: "AI生成・未確認" }) : null,
|
|
1507
1870
|
r.date ? el("span", { class: "mono", text: r.date }) : null,
|
|
1508
1871
|
el("span", { class: "mono", text: r.id }),
|
|
1509
1872
|
]);
|
|
@@ -1514,7 +1877,7 @@ const CLIENT_JS = `
|
|
|
1514
1877
|
meta.appendChild(traceR);
|
|
1515
1878
|
var card = el("div", { class: "card" }, [
|
|
1516
1879
|
meta,
|
|
1517
|
-
el("div", { class: "card-title", text: r.title }),
|
|
1880
|
+
el("div", { class: "card-title", text: r.title }, [unverifiedMark(r)]),
|
|
1518
1881
|
r.summary ? el("p", { class: "card-summary", text: r.summary }) : null,
|
|
1519
1882
|
]);
|
|
1520
1883
|
card.addEventListener("click", function () { go(r.id); });
|
|
@@ -1537,17 +1900,18 @@ const CLIENT_JS = `
|
|
|
1537
1900
|
app.appendChild(back);
|
|
1538
1901
|
|
|
1539
1902
|
var head = el("div", { class: "detail-head" });
|
|
1540
|
-
head.appendChild(el("div", {}, [ el("h1", { class: "detail-title", text: r.title }) ]));
|
|
1903
|
+
head.appendChild(el("div", {}, [ el("h1", { class: "detail-title", text: r.title }, [unverifiedMark(r)]) ]));
|
|
1541
1904
|
var traceBtn2 = el("a", { class: "edit-btn", href: "?tab=graph", text: "🕸 つながり" });
|
|
1542
1905
|
traceBtn2.addEventListener("click", function (ev) { ev.preventDefault(); openExplorerFor(r); });
|
|
1543
1906
|
head.appendChild(traceBtn2);
|
|
1544
1907
|
if (r.editUrl) {
|
|
1545
1908
|
head.appendChild(el("a", { class: "edit-btn", href: r.editUrl, target: "_blank", rel: "noopener", text: "✏️ GitHubで編集" }));
|
|
1546
1909
|
}
|
|
1910
|
+
var aiEditR = aiEditBtn(r, r._section, r.title);
|
|
1911
|
+
if (aiEditR) head.appendChild(aiEditR);
|
|
1547
1912
|
app.appendChild(head);
|
|
1548
1913
|
|
|
1549
1914
|
app.appendChild(el("div", { class: "detail-meta" }, [
|
|
1550
|
-
r.rstatus === "draft" ? el("span", { class: "badge draft", text: "AI生成・未確認" }) : null,
|
|
1551
1915
|
r.date ? el("span", { class: "mono", text: r.date }) : null,
|
|
1552
1916
|
el("span", { class: "mono", text: r.id }),
|
|
1553
1917
|
r.summary ? el("span", { text: r.summary }) : null,
|
|
@@ -1556,13 +1920,6 @@ const CLIENT_JS = `
|
|
|
1556
1920
|
var en2 = fmErrorNote(r);
|
|
1557
1921
|
if (en2) app.appendChild(en2);
|
|
1558
1922
|
|
|
1559
|
-
if (r.rstatus === "draft") {
|
|
1560
|
-
app.appendChild(el("div", { class: "draft-note" }, [
|
|
1561
|
-
el("span", { text: "⚠️" }),
|
|
1562
|
-
el("span", { text: "この定義はAIが自動生成したものです(人間未確認)。必ず内容を確認し、適切な定義に置き換えたうえで frontmatter の status を active に変更してください。" }),
|
|
1563
|
-
]));
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
1923
|
var genBody = el("div", { class: "body" });
|
|
1567
1924
|
app.appendChild(genBody);
|
|
1568
1925
|
loadBody(r, genBody);
|
|
@@ -2191,7 +2548,7 @@ const CLIENT_JS = `
|
|
|
2191
2548
|
app.appendChild(back);
|
|
2192
2549
|
|
|
2193
2550
|
var head = el("div", { class: "detail-head" });
|
|
2194
|
-
var headLeft = el("div", {}, [ el("h1", { class: "detail-title", text: d.title }) ]);
|
|
2551
|
+
var headLeft = el("div", {}, [ el("h1", { class: "detail-title", text: d.title }, [unverifiedMark(d)]) ]);
|
|
2195
2552
|
head.appendChild(headLeft);
|
|
2196
2553
|
var traceBtn = el("a", { class: "edit-btn", href: "?tab=graph", text: "🕸 つながり" });
|
|
2197
2554
|
traceBtn.addEventListener("click", function (ev) { ev.preventDefault(); openExplorerFor(d); });
|
|
@@ -2199,6 +2556,8 @@ const CLIENT_JS = `
|
|
|
2199
2556
|
if (d.editUrl) {
|
|
2200
2557
|
head.appendChild(el("a", { class: "edit-btn", href: d.editUrl, target: "_blank", rel: "noopener", text: "✏️ GitHubで編集" }));
|
|
2201
2558
|
}
|
|
2559
|
+
var aiEditD = aiEditBtn(d, "Decisions", d.title);
|
|
2560
|
+
if (aiEditD) head.appendChild(aiEditD);
|
|
2202
2561
|
app.appendChild(head);
|
|
2203
2562
|
|
|
2204
2563
|
var meta = el("div", { class: "detail-meta" }, [
|
|
@@ -2294,7 +2653,7 @@ const CLIENT_JS = `
|
|
|
2294
2653
|
// パンくず(フォルダ › レコード › つながり…)
|
|
2295
2654
|
var crumbs = [];
|
|
2296
2655
|
if (!q && explorerState.folder) {
|
|
2297
|
-
crumbs.push({ label: explorerState.folder, click: function () { explorerState.path = []; renderList(); } });
|
|
2656
|
+
crumbs.push({ label: dirLabel(explorerState.folder), click: function () { explorerState.path = []; renderList(); } });
|
|
2298
2657
|
}
|
|
2299
2658
|
explorerState.path.forEach(function (id, i) {
|
|
2300
2659
|
crumbs.push({
|
|
@@ -2392,7 +2751,7 @@ const CLIENT_JS = `
|
|
|
2392
2751
|
return nodeById[id] && recordText(byId[id]).indexOf(q2) !== -1;
|
|
2393
2752
|
});
|
|
2394
2753
|
if (!hits.length) return;
|
|
2395
|
-
itemsBox.appendChild(el("div", { class: "mc-group", text: g.name }));
|
|
2754
|
+
itemsBox.appendChild(el("div", { class: "mc-group", text: dirLabel(g.name) }));
|
|
2396
2755
|
hits.forEach(function (id) { itemsBox.appendChild(makeRecordRow(id)); });
|
|
2397
2756
|
});
|
|
2398
2757
|
if (!itemsBox.children.length) itemsBox.appendChild(el("div", { class: "mc-empty", text: "一致なし" }));
|
|
@@ -2400,7 +2759,7 @@ const CLIENT_JS = `
|
|
|
2400
2759
|
goldGroups.forEach(function (g) {
|
|
2401
2760
|
var row = el("div", { class: "mc-item mc-folder" + (explorerState.folder === g.name ? " selected" : "") });
|
|
2402
2761
|
row.appendChild(el("span", { text: "📁" }));
|
|
2403
|
-
row.appendChild(el("span", { class: "mc-label", text: g.name }));
|
|
2762
|
+
row.appendChild(el("span", { class: "mc-label", text: dirLabel(g.name) }));
|
|
2404
2763
|
row.appendChild(el("span", { class: "mc-count", text: String(g.ids.length) }));
|
|
2405
2764
|
row.addEventListener("click", function () {
|
|
2406
2765
|
explorerState.folder = g.name;
|
|
@@ -2432,7 +2791,7 @@ const CLIENT_JS = `
|
|
|
2432
2791
|
goldGroups.forEach(function (g) { if (g.name === explorerState.folder) g0 = g; });
|
|
2433
2792
|
if (g0) {
|
|
2434
2793
|
var colR = el("div", { class: "mc-col" });
|
|
2435
|
-
colR.appendChild(el("div", { class: "mc-col-head" }, [el("span", { text: g0.name + "(" + g0.ids.length + ")" })]));
|
|
2794
|
+
colR.appendChild(el("div", { class: "mc-col-head" }, [el("span", { text: dirLabel(g0.name) + "(" + g0.ids.length + ")" })]));
|
|
2436
2795
|
g0.ids.forEach(function (id) { if (nodeById[id]) colR.appendChild(makeRecordRow(id)); });
|
|
2437
2796
|
if (!g0.ids.length) colR.appendChild(el("div", { class: "mc-empty", text: "レコードはまだありません" }));
|
|
2438
2797
|
cols.appendChild(colR);
|
package/package.json
CHANGED