@takagaki/cortex-decisions-viewer 0.12.8 → 0.12.9
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 +111 -0
- package/dist/render.js +190 -7
- package/package.json +1 -1
package/dist/build.js
CHANGED
|
@@ -38,6 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.readFleetSources = readFleetSources;
|
|
40
40
|
exports.readGoldProposals = readGoldProposals;
|
|
41
|
+
exports.buildHomeGrounding = buildHomeGrounding;
|
|
41
42
|
exports.findBacklogDir = findBacklogDir;
|
|
42
43
|
exports.build = build;
|
|
43
44
|
exports.createRefResolver = createRefResolver;
|
|
@@ -517,6 +518,108 @@ async function readGoldProposals(repoRoot) {
|
|
|
517
518
|
}
|
|
518
519
|
return byPath;
|
|
519
520
|
}
|
|
521
|
+
// ---- Home(案件の自己記述)--------------------------------------------------
|
|
522
|
+
//
|
|
523
|
+
// Home.md は「案件そのものの説明」に絞る再構成の途中にある(engine 側で進行中)。
|
|
524
|
+
// **画面はどちらの形でも動く必要がある**——ビューアのほうが先に配られるので、
|
|
525
|
+
// 移行前のリポジトリでも壊れず、移行後に自然に新しい形へ寄る作りにする。
|
|
526
|
+
//
|
|
527
|
+
// 27案件を実測したところ、案件の目的が記入済みなのは3件だけだった。
|
|
528
|
+
// 残る24案件では、毎晩のAI生成が**案件を知らないまま**抽出を続けている。
|
|
529
|
+
// ビューアの仕事は、その未記入を見えるようにして「書かせる圧」をかけること。
|
|
530
|
+
/** 新しい形の自己記述の節。画面の最上部に出す */
|
|
531
|
+
const HOME_GROUNDING_HEADINGS = ["この案件について", "ゴール", "体制"];
|
|
532
|
+
/** 旧い形。1つの節に「解きたいこと」「達成した状態」が同居していた */
|
|
533
|
+
const HOME_LEGACY_GROUNDING_HEADING = "このプロジェクトが目指すもの";
|
|
534
|
+
/**
|
|
535
|
+
* 旧 Home.md が持っていた「使い方の説明」。**ビューア側(操作タブ)へ移した。**
|
|
536
|
+
*
|
|
537
|
+
* 案件ごとのリポジトリに同じ説明が27枚コピーされている状態で、文言を直すのに
|
|
538
|
+
* 全案件へマイグレーションが要った。説明はツールの一部なので、ツールが持つ。
|
|
539
|
+
* ここでは表示から落とすだけ(ファイルからの削除は engine 側のマイグレーションが行う)。
|
|
540
|
+
*/
|
|
541
|
+
const HOME_LEGACY_USAGE_HEADINGS = ["この仕組みについて", "情報の見方", "このサイトで見られるもの"];
|
|
542
|
+
/** 記入待ちの穴(雛形が置いていく {{…}}) */
|
|
543
|
+
const PLACEHOLDER = /\{\{[^{}]*\}\}/;
|
|
544
|
+
/** 本文を `##` の見出しで節に切る(見出しの無い前置きは heading: null で先頭に入る) */
|
|
545
|
+
function splitByH2(content) {
|
|
546
|
+
const out = [{ heading: null, lines: [] }];
|
|
547
|
+
let inFence = false;
|
|
548
|
+
for (const line of content.split("\n")) {
|
|
549
|
+
// **コードブロックの中は見出しとして数えない。** 手順の例に ## が出てくることがある
|
|
550
|
+
if (/^\s*(```|~~~)/.test(line))
|
|
551
|
+
inFence = !inFence;
|
|
552
|
+
const m = inFence ? null : /^##[ \t]+(.+?)[ \t]*$/.exec(line);
|
|
553
|
+
if (m)
|
|
554
|
+
out.push({ heading: m[1], lines: [] });
|
|
555
|
+
else
|
|
556
|
+
out[out.length - 1].lines.push(line);
|
|
557
|
+
}
|
|
558
|
+
return out.map((s) => ({ heading: s.heading, body: s.lines.join("\n") }));
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* 節の中身が「まだ書かれていない」か。
|
|
562
|
+
*
|
|
563
|
+
* 🔴 **見出しの配下だけを見る。** 導入行の `{{プロジェクト名}}` のような、節の外に残った
|
|
564
|
+
* 雛形の穴で発火させない——あれは案件の自己記述ではないので、埋まっていなくても
|
|
565
|
+
* 毎晩のAI生成が案件を誤解する原因にはならない。ここを本文全体に広げると、
|
|
566
|
+
* ほぼ全案件で警告が出っぱなしになり、**本当に書いてほしい案件が埋もれる**。
|
|
567
|
+
*
|
|
568
|
+
* HTML コメントは先に落とす。雛形は書き手への指示をコメントで置いており、
|
|
569
|
+
* その中の例示({{…}})は「未記入」の証拠ではない。
|
|
570
|
+
*/
|
|
571
|
+
function isUnwritten(body) {
|
|
572
|
+
return PLACEHOLDER.test(body.replace(/<!--[\s\S]*?-->/g, ""));
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Home.md から「案件の自己記述」を取り出し、残りの本文と分ける。
|
|
576
|
+
*
|
|
577
|
+
* @returns sections … 最上部に出す節(新形式・旧形式のどちらでも拾う)
|
|
578
|
+
* unfilled … 案件の概要・ゴールが未記入か(警告カードを出すか)
|
|
579
|
+
* restHtml … 自己記述と旧説明を除いた残りの本文(使用ツール等)
|
|
580
|
+
*/
|
|
581
|
+
async function buildHomeGrounding(rawMarkdown) {
|
|
582
|
+
const content = (0, gray_matter_1.default)(rawMarkdown).content;
|
|
583
|
+
const parts = splitByH2(content);
|
|
584
|
+
const find = (h) => parts.find((p) => p.heading === h);
|
|
585
|
+
const legacy = find(HOME_LEGACY_GROUNDING_HEADING);
|
|
586
|
+
// **新形式が1つでもあれば新形式として扱う。** 移行の途中で両方が並ぶことがあり、
|
|
587
|
+
// そのとき旧い節を自己記述として出すと、同じ内容が2度出る
|
|
588
|
+
const hasNew = HOME_GROUNDING_HEADINGS.some((h) => find(h));
|
|
589
|
+
const groundingHeadings = hasNew ? HOME_GROUNDING_HEADINGS : legacy ? [HOME_LEGACY_GROUNDING_HEADING] : [];
|
|
590
|
+
const sections = [];
|
|
591
|
+
for (const h of groundingHeadings) {
|
|
592
|
+
const hit = find(h);
|
|
593
|
+
// 「体制」のように**無くてよい節**は、無ければ出さない(空の見出しを並べない)
|
|
594
|
+
if (!hit || !hit.body.trim())
|
|
595
|
+
continue;
|
|
596
|
+
sections.push({
|
|
597
|
+
heading: h,
|
|
598
|
+
html: externalLinksToNewTab(await marked_1.marked.parse(hit.body, { async: true })),
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
// 未記入の判定。新形式は「この案件について」と「ゴール」の2つ、旧形式は1つの節を見る。
|
|
602
|
+
// **どちらの節も無ければ未記入。** 節ごと消えている案件が実在する
|
|
603
|
+
const checkHeadings = hasNew ? ["この案件について", "ゴール"] : [HOME_LEGACY_GROUNDING_HEADING];
|
|
604
|
+
const unfilled = checkHeadings.some((h) => {
|
|
605
|
+
const hit = find(h);
|
|
606
|
+
return !hit || !hit.body.trim() || isUnwritten(hit.body);
|
|
607
|
+
});
|
|
608
|
+
// 残りの本文=自己記述の節と、旧い使い方の説明を除いたもの
|
|
609
|
+
// **旧い自己記述は、新形式へ移ったあとも本文から落とす。** 移行の途中で新旧が並ぶと、
|
|
610
|
+
// 新しい節を最上部に出したうえで古い節が本文にも出て、どちらが今の説明か分からなくなる
|
|
611
|
+
const dropped = new Set([
|
|
612
|
+
...groundingHeadings,
|
|
613
|
+
HOME_LEGACY_GROUNDING_HEADING,
|
|
614
|
+
...HOME_LEGACY_USAGE_HEADINGS,
|
|
615
|
+
]);
|
|
616
|
+
const rest = parts
|
|
617
|
+
.filter((p) => !(p.heading != null && dropped.has(p.heading)))
|
|
618
|
+
.map((p) => (p.heading == null ? p.body : `## ${p.heading}\n${p.body}`))
|
|
619
|
+
.join("\n");
|
|
620
|
+
const restHtml = externalLinksToNewTab((await marked_1.marked.parse(rest, { async: true })).replace(/^\s*<h1[^>]*>[\s\S]*?<\/h1>\s*/, ""));
|
|
621
|
+
return { sections, unfilled, restHtml };
|
|
622
|
+
}
|
|
520
623
|
/** パスがディレクトリとして存在するか */
|
|
521
624
|
async function isDirectory(dirAbs) {
|
|
522
625
|
try {
|
|
@@ -1389,11 +1492,18 @@ async function build(opts) {
|
|
|
1389
1492
|
decisions.push(rec);
|
|
1390
1493
|
}
|
|
1391
1494
|
let home = null;
|
|
1495
|
+
let homeGrounding;
|
|
1392
1496
|
const sections = [];
|
|
1393
1497
|
if (knowledgeRoot) {
|
|
1394
1498
|
try {
|
|
1395
1499
|
const raw = await node_fs_1.promises.readFile(path.join(knowledgeRoot, "Home.md"), "utf8");
|
|
1396
1500
|
home = await parseGeneric(raw, "Home.md", toRepoRelative(knowledgeRoot), repo.baseUrl, repo.branch);
|
|
1501
|
+
// 自己記述の節を取り出し、**本文からは抜く**(最上部に出すので、残すと2度出る)。
|
|
1502
|
+
// 旧い使い方の説明もここで落ちる(説明はビューアが持つようになった)
|
|
1503
|
+
const grounding = await buildHomeGrounding(raw);
|
|
1504
|
+
homeGrounding = { sections: grounding.sections, unfilled: grounding.unfilled };
|
|
1505
|
+
home.bodyHtml = grounding.restHtml;
|
|
1506
|
+
home.searchText = grounding.sections.map((s) => s.heading).join(" ") + " " + home.searchText;
|
|
1397
1507
|
}
|
|
1398
1508
|
catch {
|
|
1399
1509
|
// ホーム未作成の案件では着地画面なし(Decisionsタブが既定になる)
|
|
@@ -1442,6 +1552,7 @@ async function build(opts) {
|
|
|
1442
1552
|
branch: repo.branch,
|
|
1443
1553
|
decisions,
|
|
1444
1554
|
home,
|
|
1555
|
+
homeGrounding: homeGrounding,
|
|
1445
1556
|
sections,
|
|
1446
1557
|
graph,
|
|
1447
1558
|
categories,
|
package/dist/render.js
CHANGED
|
@@ -2078,6 +2078,36 @@ a:hover { text-decoration: underline; }
|
|
|
2078
2078
|
.promote-btn:disabled { opacity: .6; cursor: default; }
|
|
2079
2079
|
/* 何を上げようとしているか(リポジトリ上のパス)。リンクではないので控えめな色にする */
|
|
2080
2080
|
.promote-target { font-size: 12.5px; word-break: break-all; color: var(--muted); margin: 0 0 12px; }
|
|
2081
|
+
/* ---- Home(案件の自己記述)---- */
|
|
2082
|
+
/* 未記入の警告。**画面でいちばん強い赤にする**——27案件中24案件が未記入のまま
|
|
2083
|
+
毎晩のAI生成が走っている状態で、控えめに出しても読まれない */
|
|
2084
|
+
.home-unfilled {
|
|
2085
|
+
display: flex; flex-wrap: wrap; gap: 14px; align-items: center; justify-content: space-between;
|
|
2086
|
+
background: #fef2f2; border: 2px solid #fca5a5; border-radius: 10px;
|
|
2087
|
+
padding: 16px 18px; margin: 4px 0 18px;
|
|
2088
|
+
}
|
|
2089
|
+
.home-unfilled-body { flex: 1 1 320px; min-width: 0; }
|
|
2090
|
+
.home-unfilled-title { font-size: 15.5px; font-weight: 700; color: #b91c1c; margin-bottom: 6px; }
|
|
2091
|
+
.home-unfilled-text { font-size: 13.5px; color: #991b1b; line-height: 1.8; }
|
|
2092
|
+
.home-unfilled-actions { flex: 0 0 auto; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
2093
|
+
.home-grounding { margin: 0 0 8px; }
|
|
2094
|
+
.home-grounding-title {
|
|
2095
|
+
font-size: 17px; font-weight: 700; margin: 18px 0 8px;
|
|
2096
|
+
padding-bottom: 6px; border-bottom: 1px solid var(--border);
|
|
2097
|
+
}
|
|
2098
|
+
.home-grounding > .home-grounding-title:first-child { margin-top: 0; }
|
|
2099
|
+
/* ---- 操作タブ末尾の「この仕組みについて」(旧 Home.md から移設)---- */
|
|
2100
|
+
.about-cortex { margin-top: 36px; padding-top: 24px; border-top: 1px solid var(--border); }
|
|
2101
|
+
.about-cortex .section-title { font-size: 17px; font-weight: 700; margin: 0 0 10px; }
|
|
2102
|
+
.about-lead { font-size: 13.5px; line-height: 1.9; color: var(--muted); margin: 0 0 8px; }
|
|
2103
|
+
.about-sub { font-size: 14px; font-weight: 700; margin: 18px 0 6px; }
|
|
2104
|
+
.about-list { margin: 0; padding-left: 1.3em; font-size: 13.5px; line-height: 1.9; }
|
|
2105
|
+
.about-list li { margin-bottom: 2px; }
|
|
2106
|
+
.about-note { font-size: 13.5px; line-height: 1.9; margin: 12px 0 0; }
|
|
2107
|
+
.about-quote {
|
|
2108
|
+
margin: 14px 0 0; padding: 10px 14px; border-left: 3px solid var(--border);
|
|
2109
|
+
background: #f8f9fa; font-size: 13px; line-height: 1.9; color: var(--muted);
|
|
2110
|
+
}
|
|
2081
2111
|
/* AIからの更新提案がある印。draft(黄・要対応)とも latest(緑・新着)とも別の色にする
|
|
2082
2112
|
——「読んで直すかどうか決める」という、どちらとも違う行動を求めるものなので */
|
|
2083
2113
|
.badge.proposed { background: #eef2ff; color: #3730a3; border: 1px solid #c7d2fe; }
|
|
@@ -3163,11 +3193,29 @@ ${deriveCapTile.toString()}
|
|
|
3163
3193
|
// Home(案件の入口)のAI編集。Gold層の4区画と違い規約READMEが無いので、Home自身を読ませて直させる。
|
|
3164
3194
|
// 「このプロジェクトが目指すもの」はAIが判断の方向を決める材料なので、未記入なら埋めることを促す。
|
|
3165
3195
|
var HOME_EDIT_PROMPT = [
|
|
3166
|
-
"Cortex/Home.md
|
|
3167
|
-
"
|
|
3196
|
+
"Cortex/Home.md を読んでから、この案件の入口ページを修正してください。",
|
|
3197
|
+
"何を直すかは、まずわたしに質問してください。「この案件について」「ゴール」が未記入なら、そこを埋めるところから始めてください。",
|
|
3168
3198
|
"frontmatter(識別カード・engine 設定)は触らないでください。日付・進捗・実績値は書かないでください(変わるものの正本は課題管理ツール等の外部にあります)。",
|
|
3199
|
+
"このサイトの使い方の説明は書かないでください(説明は画面の側が持っています)。",
|
|
3169
3200
|
"書き込む前に、変更内容を提示して承認を得てください。",
|
|
3170
3201
|
].join("\\n");
|
|
3202
|
+
/**
|
|
3203
|
+
* 未記入の Home を埋めるためのプロンプト(「AIで書く」)。
|
|
3204
|
+
*
|
|
3205
|
+
* **「編集」とは別に用意する。** 編集のプロンプトは「何を直すか質問して」から始まるが、
|
|
3206
|
+
* ここで必要なのは**ゼロから聞き出して書く**こと。27案件中24案件が未記入のまま、
|
|
3207
|
+
* 毎晩のAI生成が案件を知らずに抽出を続けている状態を解くのが目的なので、
|
|
3208
|
+
* 「何をする案件か・誰のためか・どうなったら成功か」を必ず聞かせる。
|
|
3209
|
+
*/
|
|
3210
|
+
var HOME_WRITE_PROMPT = [
|
|
3211
|
+
"Cortex/Home.md を読んでから、この案件の「この案件について」「ゴール」の2つの節を埋めてください。",
|
|
3212
|
+
"まず、わたしに質問して内容を聞き出してください。少なくとも次の3つを確かめてください: 何をする案件か/誰のための案件か(顧客・利用者は誰か)/どうなったら成功と言えるか。",
|
|
3213
|
+
"聞き出した内容をもとに、2つの節を具体的な散文で書いてください。雛形の {{…}} は残さず、実際の内容に置き換えてください。",
|
|
3214
|
+
"この2つの節は、毎晩のAI生成(決定事項・用語集・メンバー・ルールの抽出)が案件を理解するために読む場所です。抽象的な言葉ではなく、この案件に固有の具体で書いてください。",
|
|
3215
|
+
"このサイトの使い方の説明は書かないでください(説明は画面の側が持っています)。",
|
|
3216
|
+
"frontmatter(識別カード・engine 設定)は触らないでください。日付・進捗・実績値は書かないでください(変わるものの正本は課題管理ツール等の外部にあります)。",
|
|
3217
|
+
"書き込む前に、書いた内容を提示して承認を得てください。",
|
|
3218
|
+
].join("\\n");
|
|
3171
3219
|
var GOLD_SKILL = {
|
|
3172
3220
|
"Decisions": {
|
|
3173
3221
|
skill: "update-decision",
|
|
@@ -3390,12 +3438,13 @@ ${deriveCapTile.toString()}
|
|
|
3390
3438
|
}
|
|
3391
3439
|
// 本文HTMLは bodies/<i>.html に外出しされている。詳細表示時にfetchして埋める(キャッシュ・失敗時フォールバック付き)
|
|
3392
3440
|
var bodyCache = {};
|
|
3393
|
-
function loadBody(rec, mount) {
|
|
3394
|
-
|
|
3395
|
-
if (
|
|
3441
|
+
function loadBody(rec, mount, after) {
|
|
3442
|
+
function done() { if (typeof after === "function") after(mount); }
|
|
3443
|
+
if (!rec || !rec.bodyRef) { mount.innerHTML = linkifyWiki((rec && rec.bodyHtml) || ""); done(); return; }
|
|
3444
|
+
if (bodyCache[rec.bodyRef] != null) { mount.innerHTML = bodyCache[rec.bodyRef]; done(); return; }
|
|
3396
3445
|
mount.innerHTML = '<div class="body-loading">読み込み中…</div>';
|
|
3397
3446
|
fetch(rec.bodyRef).then(function (res) { if (!res.ok) throw new Error("http " + res.status); return res.text(); })
|
|
3398
|
-
.then(function (html) { var lk = linkifyWiki(html); bodyCache[rec.bodyRef] = lk; mount.innerHTML = lk; })
|
|
3447
|
+
.then(function (html) { var lk = linkifyWiki(html); bodyCache[rec.bodyRef] = lk; mount.innerHTML = lk; done(); })
|
|
3399
3448
|
.catch(function () {
|
|
3400
3449
|
mount.innerHTML = '<div class="body-loading">本文を読み込めませんでした(静的サーバで配信してください)。' +
|
|
3401
3450
|
(rec.editUrl ? ' <a href="' + rec.editUrl + '" target="_blank" rel="noopener">GitHubで開く</a>' : '') + '</div>';
|
|
@@ -3603,13 +3652,90 @@ ${deriveCapTile.toString()}
|
|
|
3603
3652
|
}
|
|
3604
3653
|
head.appendChild(el("div", { class: "detail-actions" }, [ homeEditRow ]));
|
|
3605
3654
|
app.appendChild(head);
|
|
3655
|
+
|
|
3656
|
+
// **案件の自己記述を最上部に出す。** ここが埋まっていないと、毎晩のAI生成は
|
|
3657
|
+
// 案件を知らないまま抽出を続ける。未記入なら、本文より先に警告と書く導線を出す
|
|
3658
|
+
var g = SITE.homeGrounding;
|
|
3659
|
+
if (g && g.unfilled) app.appendChild(homeUnfilledCard());
|
|
3660
|
+
if (g && g.sections.length) app.appendChild(homeGroundingSections(g.sections));
|
|
3661
|
+
|
|
3606
3662
|
var homeBody = el("div", { class: "body" });
|
|
3607
3663
|
app.appendChild(homeBody);
|
|
3608
|
-
|
|
3664
|
+
// **旧い節が本文に残っていたら落とす(防御)。** 本来は build 側で抜けているが、
|
|
3665
|
+
// 落とし損ねると自己記述が2度出る・移設したはずの説明が両方に出る、という
|
|
3666
|
+
// 一番読み手を混乱させる形になるので、描画側でも同じ見出しを見張る。
|
|
3667
|
+
// **本文が入った後に呼ぶ**(外出しされていると fetch なので、直後ではまだ空)
|
|
3668
|
+
loadBody(h, homeBody, dropLegacyHomeSections);
|
|
3609
3669
|
// Markdown本文の下にオンボーディングのチュートリアルを差し込む
|
|
3610
3670
|
renderTutorialSection();
|
|
3611
3671
|
}
|
|
3612
3672
|
|
|
3673
|
+
/** 最上部に出す「案件の自己記述」。中身は build 側で組み立て済み(Markdown由来のHTML) */
|
|
3674
|
+
function homeGroundingSections(sections) {
|
|
3675
|
+
var box = el("section", { class: "home-grounding" });
|
|
3676
|
+
sections.forEach(function (s) {
|
|
3677
|
+
box.appendChild(el("h2", { class: "home-grounding-title", text: s.heading }));
|
|
3678
|
+
// **ここだけ innerHTML。** 中身は案件リポジトリの Markdown を build 側で
|
|
3679
|
+
// レンダリングしたもので、本文(.body)と同じ出どころ・同じ扱い
|
|
3680
|
+
box.appendChild(el("div", { class: "body", html: s.html }));
|
|
3681
|
+
});
|
|
3682
|
+
return box;
|
|
3683
|
+
}
|
|
3684
|
+
|
|
3685
|
+
/**
|
|
3686
|
+
* 未記入の警告。**「書かれていないと何が起きるか」まで書く。**
|
|
3687
|
+
*
|
|
3688
|
+
* 「未記入です」だけだと、埋めない理由(忙しい・後でいい)に勝てない。
|
|
3689
|
+
* 実際に起きているのは「毎晩のAI生成が案件を誤解したまま走り続ける」ことなので、
|
|
3690
|
+
* その因果を出す。27案件中24案件が未記入という実測がこの文面の根拠。
|
|
3691
|
+
*/
|
|
3692
|
+
function homeUnfilledCard() {
|
|
3693
|
+
var card = el("div", { class: "home-unfilled" }, [
|
|
3694
|
+
el("div", { class: "home-unfilled-body" }, [
|
|
3695
|
+
el("div", { class: "home-unfilled-title", text: "この案件の概要とゴールが未記入です。" }),
|
|
3696
|
+
el("div", {
|
|
3697
|
+
class: "home-unfilled-text",
|
|
3698
|
+
text: "書かれていないと、毎晩のAI生成(決定事項・用語・ルール・名簿)がこの案件を誤解したまま抽出を続けます。",
|
|
3699
|
+
}),
|
|
3700
|
+
]),
|
|
3701
|
+
]);
|
|
3702
|
+
var actions = el("div", { class: "home-unfilled-actions" }, [
|
|
3703
|
+
el("a", { class: "ai-add-btn", href: codeUrl(HOME_WRITE_PROMPT), target: "_blank", rel: "noopener", text: "AIで書く" }),
|
|
3704
|
+
]);
|
|
3705
|
+
if (SITE.home && SITE.home.editUrl) {
|
|
3706
|
+
actions.appendChild(el("a", { class: "edit-btn", href: SITE.home.editUrl, target: "_blank", rel: "noopener", text: "GitHubで編集" }));
|
|
3707
|
+
}
|
|
3708
|
+
card.appendChild(actions);
|
|
3709
|
+
return card;
|
|
3710
|
+
}
|
|
3711
|
+
|
|
3712
|
+
/**
|
|
3713
|
+
* 本文に残った旧い節(使い方の説明・旧い自己記述)を、見出しから次の見出しまで丸ごと外す。
|
|
3714
|
+
*
|
|
3715
|
+
* 移行前のリポジトリでも重複表示しないための防御。移行後はそもそも本文に無いので
|
|
3716
|
+
* 何も起きない(自然消滅する)。
|
|
3717
|
+
*/
|
|
3718
|
+
var HOME_DROP_HEADINGS = {
|
|
3719
|
+
"この仕組みについて": 1,
|
|
3720
|
+
"情報の見方": 1,
|
|
3721
|
+
"このサイトで見られるもの": 1,
|
|
3722
|
+
"この案件について": 1,
|
|
3723
|
+
"ゴール": 1,
|
|
3724
|
+
"体制": 1,
|
|
3725
|
+
"このプロジェクトが目指すもの": 1,
|
|
3726
|
+
};
|
|
3727
|
+
function dropLegacyHomeSections(mount) {
|
|
3728
|
+
if (!mount) return;
|
|
3729
|
+
var kids = Array.prototype.slice.call(mount.children);
|
|
3730
|
+
var dropping = false;
|
|
3731
|
+
kids.forEach(function (n) {
|
|
3732
|
+
if (n.tagName === "H2") dropping = !!HOME_DROP_HEADINGS[(n.textContent || "").trim()];
|
|
3733
|
+
// H2 より上位の見出しが来たら、そこで打ち切る(節の外まで消さない)
|
|
3734
|
+
else if (n.tagName === "H1") dropping = false;
|
|
3735
|
+
if (dropping && n.parentNode) n.parentNode.removeChild(n);
|
|
3736
|
+
});
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3613
3739
|
// ---------- データソースと自動化(fleet-status.json 由来。無ければ非表示) ----------
|
|
3614
3740
|
// 顧客も読む面なので内部用語(cron・stub等)を避け「毎晩自動で〜」調にする。
|
|
3615
3741
|
var DS_TYPE = {
|
|
@@ -8640,6 +8766,63 @@ ${deriveCapTile.toString()}
|
|
|
8640
8766
|
refreshStateTimer();
|
|
8641
8767
|
// **取り込みカードと鍵カードは能力セクションへ移した**(#101)。
|
|
8642
8768
|
// ここで再度出すと二重になる。手動投入は 会議 / 共有資料 の中にある。
|
|
8769
|
+
app.appendChild(buildAboutSection());
|
|
8770
|
+
}
|
|
8771
|
+
|
|
8772
|
+
/**
|
|
8773
|
+
* 「この仕組みについて」——旧 Home.md にあった使い方の説明。**ビューアが持つ。**
|
|
8774
|
+
*
|
|
8775
|
+
* 案件ごとのリポジトリに同じ説明が27枚コピーされている状態で、文言を1つ直すのに
|
|
8776
|
+
* 全案件へマイグレーションが要った。説明はツールの一部なので、ツールが持つのが正しい。
|
|
8777
|
+
*
|
|
8778
|
+
* **操作タブの最下部に置く。** Home は案件の自己記述に絞る(そこがAI生成の入力になる)ので、
|
|
8779
|
+
* ツールの説明が上に載っていると、案件を知りたい人にとっての雑音になる。
|
|
8780
|
+
* 使い方を知りたい人は設定を見に来た人と重なるので、操作タブの末尾が近い。
|
|
8781
|
+
*
|
|
8782
|
+
* **文言は旧 Home.md から持ってきて、いまの画面に合わせて直してある(分類B)。**
|
|
8783
|
+
* 直したのは1点——「各ページの『AIで編集』から直せます」は、確認済みボタン(0.12.7)が
|
|
8784
|
+
* 入って「直さずに確認だけする」経路ができたので、両方を書く形にした。
|
|
8785
|
+
* 旧文面のままだと、押せるボタンのうち片方しか案内されない。
|
|
8786
|
+
*/
|
|
8787
|
+
function buildAboutSection() {
|
|
8788
|
+
var sec = el("section", { class: "about-cortex" });
|
|
8789
|
+
sec.appendChild(el("h2", { class: "section-title", text: "この仕組みについて" }));
|
|
8790
|
+
sec.appendChild(el("p", { class: "about-lead", text:
|
|
8791
|
+
"議事録・課題・共有資料・デザイン・ソースコードといった案件の情報は、普段使っているツールに散らばっています。この仕組みはそれらを自動で集め、「あとで判断のよりどころになる確定した情報」だけを抽出した層を毎晩育てます。人もAIも、まずここを読めば案件を誤らずに把握できる、という状態を作るのが目的です。" }));
|
|
8792
|
+
|
|
8793
|
+
sec.appendChild(el("h3", { class: "about-sub", text: "情報の見方は2つあります" }));
|
|
8794
|
+
var ways = el("ul", { class: "about-list" });
|
|
8795
|
+
ways.appendChild(el("li", {}, [
|
|
8796
|
+
el("strong", { text: "このサイト" }),
|
|
8797
|
+
el("span", { text: ": 精製された確定情報を読む" }),
|
|
8798
|
+
]));
|
|
8799
|
+
var codeLi = el("li", {}, [
|
|
8800
|
+
el("a", { href: "https://claude.ai/code/", target: "_blank", rel: "noopener", text: "Claude Code" }),
|
|
8801
|
+
el("span", { text: ": 議事録・課題・資料の生データまで含めて、AIに質問・調査する" }),
|
|
8802
|
+
]);
|
|
8803
|
+
ways.appendChild(codeLi);
|
|
8804
|
+
sec.appendChild(ways);
|
|
8805
|
+
|
|
8806
|
+
sec.appendChild(el("h3", { class: "about-sub", text: "このサイトで見られるもの" }));
|
|
8807
|
+
var what = el("ul", { class: "about-list" });
|
|
8808
|
+
[
|
|
8809
|
+
["決定事項", "何が決まったか(1決定=1ページ)。議事録や課題から毎晩自動で追加されます"],
|
|
8810
|
+
["用語集", "この案件固有の言葉の意味。人とAIの語彙を揃えます"],
|
|
8811
|
+
["メンバー", "誰が関わっているか。人名の表記ゆれを解決する名簿でもあります"],
|
|
8812
|
+
["ルール", "この案件で継続的に守る約束事(例:「本番リリースは金曜禁止」)"],
|
|
8813
|
+
].forEach(function (row) {
|
|
8814
|
+
what.appendChild(el("li", {}, [
|
|
8815
|
+
el("strong", { text: row[0] }),
|
|
8816
|
+
el("span", { text: ": " + row[1] }),
|
|
8817
|
+
]));
|
|
8818
|
+
});
|
|
8819
|
+
sec.appendChild(what);
|
|
8820
|
+
sec.appendChild(el("p", { class: "about-note", text:
|
|
8821
|
+
"自動で追加されたものには「AI生成・未確認」と表示されます。内容を確認して、そのままでよければ「確認済みにする」を押してください。直したいところがあれば「AIで編集」から修正できます。どちらの場合も、その印は外れます。" }));
|
|
8822
|
+
|
|
8823
|
+
sec.appendChild(el("blockquote", { class: "about-quote", text:
|
|
8824
|
+
"要件・仕様・議事録などの個別ドキュメントはここに置きません。正本は普段お使いのツール(Backlog・Google Drive・GitHub 等)にあり、その写しが自動で同期されます。この仕組みのために新しく書く場所は増えません。" }));
|
|
8825
|
+
return sec;
|
|
8643
8826
|
}
|
|
8644
8827
|
|
|
8645
8828
|
/**
|
package/package.json
CHANGED