@takagaki/cortex-decisions-viewer 0.12.76 → 0.12.78
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 +44 -12
- package/dist/rederivation.js +33 -18
- package/package.json +1 -1
package/dist/build.js
CHANGED
|
@@ -40,6 +40,7 @@ exports.PROJECT_ICON_EXTS = void 0;
|
|
|
40
40
|
exports.sanitizeBody = sanitizeBody;
|
|
41
41
|
exports.findProjectIcon = findProjectIcon;
|
|
42
42
|
exports.readFleetSources = readFleetSources;
|
|
43
|
+
exports.attachRederived = attachRederived;
|
|
43
44
|
exports.readGoldProposals = readGoldProposals;
|
|
44
45
|
exports.buildHomeGrounding = buildHomeGrounding;
|
|
45
46
|
exports.collectMeetings = collectMeetings;
|
|
@@ -672,7 +673,9 @@ async function readFleetSources(repoRoot) {
|
|
|
672
673
|
* 🔴 **突き合わせはビルド時にここで閉じる**(`proposals` と同じ)。画面側でパスを組み立て直すと、
|
|
673
674
|
* `repoPathOf` が `editUrl` 由来なので **`repoBaseUrl` が無い案件で帯が黙って消える**。
|
|
674
675
|
*/
|
|
675
|
-
async function attachRederived(records, recordsDir, ctx, nowIso
|
|
676
|
+
async function attachRederived(records, recordsDir, ctx, nowIso,
|
|
677
|
+
// 番人テストが「git に渡った key」を数えるための差し替え口。本番は常に既定の `readBlobsAt`
|
|
678
|
+
readBlobs = repo_1.readBlobsAt) {
|
|
676
679
|
if (!ctx)
|
|
677
680
|
return records;
|
|
678
681
|
// 🔴 **レコードのパスは `repoRoot` から作る**(`toRepoRelative` の `process.cwd()` 起点で
|
|
@@ -684,32 +687,46 @@ async function attachRederived(records, recordsDir, ctx, nowIso) {
|
|
|
684
687
|
// ——ここで別のものを渡すと、画面の札と食い違う(「未確認」の札が付いた記録に帯が出る)
|
|
685
688
|
const statusOf = (r) => r.rstatus;
|
|
686
689
|
// 決定表の行 8(中身が変わったか)の材料。**印の候補になったレコードのぶんだけ**、
|
|
687
|
-
//
|
|
690
|
+
// 今の版を読み、`<基準コミット>:<path>` をまとめて 1 回引く。
|
|
688
691
|
// 🔴 **キーが 0 件の区画では git を起こさない**(この関数は区画ごとに呼ばれる)
|
|
689
692
|
const keyOf = new Map();
|
|
690
|
-
for (const r of records) {
|
|
691
|
-
const key = (0, rederivation_1.rederivedContentKey)(pathOf(r), statusOf(r), ctx.ledgers);
|
|
692
|
-
if (key)
|
|
693
|
-
keyOf.set(r, key);
|
|
694
|
-
}
|
|
695
|
-
const bases = keyOf.size ? (0, repo_1.readBlobsAt)(ctx.repoRoot, [...keyOf.values()]) : new Map();
|
|
696
693
|
// 今の版は**作業ツリーから読む**——画面が描いているのはこのファイルであって HEAD ではない
|
|
697
694
|
const now = new Map();
|
|
698
|
-
for (const r of
|
|
695
|
+
for (const r of records) {
|
|
696
|
+
const key = (0, rederivation_1.rederivedContentKey)(pathOf(r), statusOf(r), ctx.ledgers);
|
|
697
|
+
if (!key)
|
|
698
|
+
continue;
|
|
699
|
+
const p = pathOf(r);
|
|
699
700
|
try {
|
|
700
|
-
now.set(
|
|
701
|
+
now.set(p, await node_fs_1.promises.readFile(path.join(ctx.repoRoot, p), "utf8"));
|
|
701
702
|
}
|
|
702
703
|
catch {
|
|
703
704
|
// 読めなければ「引けなかった」側(下の verdict が unknown に倒す)
|
|
704
705
|
}
|
|
706
|
+
// 🔴 **帳簿の指紋が今の中身と一致する記録は git の key に入れない**(engine #546)。
|
|
707
|
+
// 答えは下の verdict で `same` になるので、基準版を引く意味が無い——ここで外さないと、
|
|
708
|
+
// engine が指紋を書いても用語 1400 件の案件で毎晩 1400 個の blob を読み続ける。
|
|
709
|
+
// 指紋が無い・食い違う・今の版が読めない記録は今までどおり git へ落とす
|
|
710
|
+
const nowRaw = now.get(p);
|
|
711
|
+
const sha = ctx.ledgers.confirmation.get(p)?.contentSha;
|
|
712
|
+
if (nowRaw != null && sha && sha === (0, rederivation_1.contentShaOf)(nowRaw)) {
|
|
713
|
+
if (ctx.blobs)
|
|
714
|
+
ctx.blobs.skipped++;
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
keyOf.set(r, key);
|
|
705
718
|
}
|
|
719
|
+
if (ctx.blobs)
|
|
720
|
+
ctx.blobs.read += keyOf.size;
|
|
721
|
+
const bases = keyOf.size ? readBlobs(ctx.repoRoot, [...keyOf.values()]) : new Map();
|
|
706
722
|
const verdict = (p, baseCommit) => {
|
|
707
723
|
const nowRaw = now.get(p);
|
|
708
724
|
if (nowRaw == null) {
|
|
709
725
|
ctx.miss.unreadable.add(p);
|
|
710
726
|
return "unknown";
|
|
711
727
|
}
|
|
712
|
-
// 🔴 **帳簿が中身の指紋を持つならそれを先に使う**(engine
|
|
728
|
+
// 🔴 **帳簿が中身の指紋を持つならそれを先に使う**(engine #546 が書く。一致した記録は
|
|
729
|
+
// 上で git の key から外してある)。
|
|
713
730
|
// 一致したときだけ「変わっていない」と言い、食い違ったら git の二段目へ落とす——
|
|
714
731
|
// engine が別の綴りで指紋を作っていた場合に、全レコードへ誤報が出るのを避ける
|
|
715
732
|
const conf = ctx.ledgers.confirmation.get(p);
|
|
@@ -968,10 +985,18 @@ async function loadGenericRecords(dirAbs, exclude, repoBaseUrl, branch) {
|
|
|
968
985
|
records.push(await parseGeneric(raw, e.name, repoRelDir, repoBaseUrl, branch));
|
|
969
986
|
}
|
|
970
987
|
// 日付降順 → タイトル昇順(用語集のように日付が同一でも安定して並ぶ)
|
|
988
|
+
//
|
|
989
|
+
// 🔴 **第 2 鍵(コード順)を外さない**(#576)。`localeCompare(…, "ja")` は**別の綴りでも
|
|
990
|
+
// 0 を返す**(実測: `が`/`ガ`・`サーバ`/`さーば`・`AI`/`AI`・`あ行`/`ア行`)。0 のまま
|
|
991
|
+
// 安定ソートに任せると、その 2 語の順を決めるのは**`readdir` が返した順**になり、Node は
|
|
992
|
+
// その順を保証しない——中身を 1 文字も変えていない日に、用語集の並びが環境で変わる。
|
|
993
|
+
// cortex-engine の記憶の目次(`scripts/memory-index.mjs` の `cmpTerm`)はこの並びに
|
|
994
|
+
// **上位 20 件の集合**を合わせているので、ここが揺れると目次との一致も揺れる。
|
|
995
|
+
// 引き分けだったところに順を決めるだけで、**決まっていた並びは 1 つも変えていない**。
|
|
971
996
|
records.sort((a, b) => {
|
|
972
997
|
if (a.date !== b.date)
|
|
973
998
|
return a.date < b.date ? 1 : -1;
|
|
974
|
-
return a.title.localeCompare(b.title, "ja");
|
|
999
|
+
return a.title.localeCompare(b.title, "ja") || (a.title < b.title ? -1 : a.title > b.title ? 1 : 0);
|
|
975
1000
|
});
|
|
976
1001
|
return records;
|
|
977
1002
|
}
|
|
@@ -1959,6 +1984,7 @@ async function build(opts) {
|
|
|
1959
1984
|
repoRoot: repoRoot,
|
|
1960
1985
|
identities: ledgers.confirmation.size ? (0, repo_1.collectGoldCommitIdentities)(repoRoot) : new Map(),
|
|
1961
1986
|
miss: { unresolved: new Set(), unreadable: new Set() },
|
|
1987
|
+
blobs: { read: 0, skipped: 0 },
|
|
1962
1988
|
}
|
|
1963
1989
|
: null;
|
|
1964
1990
|
const decisions = [];
|
|
@@ -2051,6 +2077,12 @@ async function build(opts) {
|
|
|
2051
2077
|
`(浅い clone か、確認の後に改名・削除された。変わったかを言えないので印は出しません): ` +
|
|
2052
2078
|
paths.slice(0, 3).join(", ") + (paths.length > 3 ? " ほか" : ""));
|
|
2053
2079
|
}
|
|
2080
|
+
// 🔴 **指紋(engine #546)が効いているかを 1 行残す。** 一致した記録は git を読まないので、
|
|
2081
|
+
// 「読んだ件数」が候補の数より減っていれば効いている。警告ではないので console.log
|
|
2082
|
+
if (rederive?.blobs && rederive.blobs.read + rederive.blobs.skipped > 0) {
|
|
2083
|
+
console.log(`gold-confirmation.json: 人が確認した版の中身を git から ${rederive.blobs.read} 件読みました` +
|
|
2084
|
+
`(中身の指紋が一致した ${rederive.blobs.skipped} 件は読んでいません)`);
|
|
2085
|
+
}
|
|
2054
2086
|
const unmatched = [...PROPOSALS_BY_PATH.keys()].filter((k) => !PROPOSAL_PATHS_MATCHED.has(k));
|
|
2055
2087
|
if (unmatched.length) {
|
|
2056
2088
|
console.warn(`gold-proposals.json: レコードに突き合わない提案が ${unmatched.length} 件ありました(表示しません): ` +
|
package/dist/rederivation.js
CHANGED
|
@@ -141,7 +141,7 @@ async function readRederivationLedgers(repoRoot) {
|
|
|
141
141
|
const changedBy = Array.isArray(row?.changed_by)
|
|
142
142
|
? row.changed_by.map((s) => String(s)).filter((s) => s !== "")
|
|
143
143
|
: [];
|
|
144
|
-
// 中身の指紋は**文字列のときだけ**持つ(engine
|
|
144
|
+
// 中身の指紋は**文字列のときだけ**持つ(engine #546 が書く。古い帳簿の行には無い)
|
|
145
145
|
const contentSha = typeof confirmed.content_sha === "string" ? confirmed.content_sha : "";
|
|
146
146
|
out.confirmation.set(p, {
|
|
147
147
|
at: confirmed.at != null ? String(confirmed.at) : "",
|
|
@@ -311,9 +311,12 @@ function sameRederivedContent(a, b) {
|
|
|
311
311
|
/**
|
|
312
312
|
* 「説明文と本文」の指紋。**帳簿の `confirmed.content_sha` と突き合わせる綴り**。
|
|
313
313
|
*
|
|
314
|
-
* 🔴 engine
|
|
314
|
+
* 🔴 比べる相手は engine #546 が書く `confirmed.content_sha`。**一致したときだけ
|
|
315
315
|
* 「変わっていない」と言い、食い違ったら git へ落とす**(`attachRederived`)——engine が
|
|
316
316
|
* 別の綴りで指紋を作っていた場合に、全レコードへ誤報が出るのを避けるため。
|
|
317
|
+
*
|
|
318
|
+
* engine の写し: `cortex-engine/scripts/rederive/content-sha.mjs`・一致の番人:
|
|
319
|
+
* `cortex-engine/test/rederive-history.test.mjs` の #546 の節(ここを変えたら engine の `VIEWER_SHA` を計算し直す)
|
|
317
320
|
*/
|
|
318
321
|
function contentShaOf(raw) {
|
|
319
322
|
const c = comparableContent(raw);
|
|
@@ -462,23 +465,39 @@ function rederivedBandOf(recordPath, status, ledgers, identities, verdict, miss)
|
|
|
462
465
|
};
|
|
463
466
|
}
|
|
464
467
|
/**
|
|
465
|
-
* 用語集の並び(#432 裁定 5-5
|
|
468
|
+
* 用語集の並び(#432 裁定 5-5 → #690 で群分けを撤廃)。**活性度の降順だけで決める。**
|
|
469
|
+
*
|
|
470
|
+
* 🔴 **確認済みかどうかは並びに使わない**(便 #690・オーナー決定 2026-09-21 逐語
|
|
471
|
+
* 「触れられた回数とか、携わってる人、携わってる回数が多い人が上に出てくる方がいい。
|
|
472
|
+
* **アクティブ、ドラフト関係なく**」)。engine の関係者の並び(`scripts/engagement/tiers.mjs`
|
|
473
|
+
* の `order`・便 #543)に当てたのと同じ形で、**同じ画面の中で並び方を揃える**。
|
|
474
|
+
*
|
|
475
|
+
* 前はここで「確認済みが先頭群」を先に見ていたので、**群の境目が活性度より強く**、
|
|
476
|
+
* ほとんど触られていない確認済みの語が先頭に並び、**いま出てきたばかりの下書きが下に沈んだ**。
|
|
477
|
+
* 理由は 2 つ:
|
|
478
|
+
* - 「確認済みかどうか」は**札で分かる**(`render.ts` の「AI生成・未確認」)ので、
|
|
479
|
+
* 並びで二重に表現する必要がない。下書きが上に来るのは「**新しく出てきた言葉**」なので、
|
|
480
|
+
* むしろ見たいもの
|
|
481
|
+
* - 🔴 **この並びは「索引の上から N 件だけを AI に読ませる」構想の土台**(engine #544)。
|
|
482
|
+
* 「上に来るものが重要」でなければ、その仕組みが成り立たない
|
|
466
483
|
*
|
|
467
|
-
* 🔴
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
* の用語集で 25 件)。帳簿の役目は「どの版に戻すか」だけになった。
|
|
484
|
+
* 🔴 **`isConfirmedStatus` は消さない**——このファイルの**印の門(`rederivedContentKey`)と
|
|
485
|
+
* 帯の門(`rederivedBandOf`)**が使う。`render.ts` の札は `rec.rstatus === "draft"` の
|
|
486
|
+
* **別実装**で、2 つが一致していることは `rederived-mark-ui.test.mjs` の `[札との一致]` が見る。
|
|
487
|
+
* ここで変えるのは**並びだけ**で、札・帯・印・プロンプトに渡る材料は 1 つも変えていない。
|
|
472
488
|
*
|
|
473
489
|
* - 活性度を持つレコードが 1 件も無い区画は **1 バイトも触らない**(帳簿が無い案件は従来順)
|
|
474
|
-
* -
|
|
490
|
+
* - 活性度を知らないレコードは**末尾**へ、**元の並びのまま**(安定)
|
|
491
|
+
* - 同じ活性度なら元の並び(日付降順 → タイトル昇順がそのまま残る)
|
|
475
492
|
* - 用語集だけ(メンバーの並びは便 14・Decisions と Rules は対象外)
|
|
476
493
|
*
|
|
477
|
-
* ℹ️ `ledgers`
|
|
478
|
-
*
|
|
494
|
+
* ℹ️ `ledgers` と `statusOf` は**受け取り続ける**。`ledgers` は活性度のために要る。
|
|
495
|
+
* `statusOf` は並びに使わなくなったが、**引数から落とすと「群分けを足し戻す」退行が
|
|
496
|
+
* コンパイルで止まる代わりに、変異検証でそれを実演できなくなる**(`ledgers` と同じ流儀)。
|
|
497
|
+
* 番人(`rederivation-ledgers.test.mjs` の `[並び]`)はこの 1 行の足し戻しで赤くなる。
|
|
479
498
|
*
|
|
480
499
|
* @param records 区画のレコード(`repoPathOf` で引けるパスを持つもの。並びは変えずに新しい配列を返す)
|
|
481
|
-
* @param statusOf そのレコードの `rstatus`(`String()`
|
|
500
|
+
* @param statusOf そのレコードの `rstatus`(`String()` 済み)を引く関数。**並びには使わない**(上の ℹ️)
|
|
482
501
|
*/
|
|
483
502
|
function orderByActivity(records, pathOf, statusOf, ledgers, nowIso) {
|
|
484
503
|
if (!records.length)
|
|
@@ -490,7 +509,6 @@ function orderByActivity(records, pathOf, statusOf, ledgers, nowIso) {
|
|
|
490
509
|
return {
|
|
491
510
|
r: r,
|
|
492
511
|
i: i,
|
|
493
|
-
confirmed: inSection && isConfirmedStatus(statusOf(r)),
|
|
494
512
|
score: inSection ? activityScore(ledgers.activity.get(p), nowIso) : null,
|
|
495
513
|
};
|
|
496
514
|
});
|
|
@@ -499,15 +517,12 @@ function orderByActivity(records, pathOf, statusOf, ledgers, nowIso) {
|
|
|
499
517
|
return scored
|
|
500
518
|
.slice()
|
|
501
519
|
.sort((a, b) => {
|
|
502
|
-
// 1.
|
|
503
|
-
if (a.confirmed !== b.confirmed)
|
|
504
|
-
return a.confirmed ? -1 : 1;
|
|
505
|
-
// 2. 群の中は活性度の降順。知らないものは群の末尾
|
|
520
|
+
// 1. 活性度の降順だけ(便 #690・確認済みかどうかでは分けない)。知らないものは末尾
|
|
506
521
|
if (a.score != null && b.score != null && a.score !== b.score)
|
|
507
522
|
return b.score - a.score;
|
|
508
523
|
if ((a.score == null) !== (b.score == null))
|
|
509
524
|
return a.score == null ? 1 : -1;
|
|
510
|
-
//
|
|
525
|
+
// 2. 同点は元の並び(安定・日付降順 → タイトル昇順がそのまま残る)
|
|
511
526
|
return a.i - b.i;
|
|
512
527
|
})
|
|
513
528
|
.map((s) => s.r);
|
package/package.json
CHANGED