数字我 Digital Me:全量入库(大文件走 Git LFS)
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s

This commit is contained in:
2026-10-10 16:24:43 +08:00
commit 0593ff7e62
1893 changed files with 361723 additions and 0 deletions
@@ -0,0 +1,90 @@
// 采【加权求和版】引擎的产出 —— 这一刀的「旧版」参照。
//
// ★★ 这个脚本【只在改 dynasties.js 之前跑过一次】,跑完它采下来的 dynasties-weighted-sum.json
// 就是死的。★ 绝不要在改完引擎之后再跑它来「更新」参照 —— 那等于把被告改成原告。
//
// ⚠ 它自证真伪:采下来的五个单轨朝代,指纹必须与 dynasties-pre-multitrack.json 里
// 【旧代码采的那份】逐字相同。对得上 ⇒ 这份快照确实是旧引擎的产出,不是我编的。
// (本项目的铁律:最难发现的错是「假订正」。一份自己造的「旧版」参照,就是假订正的温床。)
//
// 跑:node scripts/capture-weighted-sum.mjs
//
// ⚠ 它住在 scripts/ 而不是 test/,是【故意的】:`node --test` 会把 test/ 底下的【每一个】文件
// 都当测试跑(不只是 *.test.js)。而本脚本的自证在引擎改完之后【必然抛异常】——
// 那是它设计上的正确行为,却会把 npm test 弄红。放在 scripts/ 下,它才是它该是的东西:
// 一次性的采集工具,不是测试。
import crypto from 'node:crypto';
import fs from 'node:fs';
import { DYNASTIES, computeRank, profileFromSubs } from '../src/dynasties.js';
import { SUB_REGISTRY } from '../src/talents.js';
// ⚠ 必须与 dynasties-tracks.test.js 的 matrix() 【完全同构】,否则指纹对不上。
function matrix() {
const ALL = SUB_REGISTRY.map((s) => s.id);
const combos = [[]];
for (const s of ALL) combos.push([s]);
for (let i = 0; i < ALL.length; i++) for (let j = i + 1; j < ALL.length; j++) combos.push([ALL[i], ALL[j]]);
combos.push(['rigorous', 'datadriven', 'concise', 'shortfirst', 'patient', 'calm']);
combos.push(['poetic', 'story', 'vivid']);
combos.push(['socratic', 'humor', 'poetic', 'story', 'vivid']);
combos.push(['blunt', 'motivate']);
combos.push(ALL);
const out = new Map();
for (const subs of combos) {
for (const wang of [0, 30, 55, 60, 75, 80, 90, 100]) {
out.set(`${subs.join('+') || '∅'}|w${wang}`, profileFromSubs(subs, { wang }));
}
}
return [...out.entries()];
}
// ── 自证:五个单轨朝代的指纹必须与【旧代码采的】 pre-multitrack fixture 对得上 ──
const PRE = JSON.parse(fs.readFileSync(new URL('../test/fixtures/dynasties-pre-multitrack.json', import.meta.url), 'utf8'));
const rows = matrix();
if (rows.length !== PRE._matrix.count) throw new Error(`矩阵变了:${rows.length} ≠ ${PRE._matrix.count}`);
const sorted = rows.slice().sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));
for (const d of ['han', 'weijin', 'nanchao', 'tang', 'ming']) {
const h = crypto.createHash('sha256');
for (const [k, p] of sorted) h.update(k + '|' + JSON.stringify(computeRank(p, d)));
const got = h.digest('hex');
if (got !== PRE.hashes[d]) {
throw new Error(
`✗ ${d} 的指纹与 pre-multitrack 对不上 —— 当前代码【已经不是】加权求和版了。\n` +
' 这个脚本只能在改引擎【之前】跑。现在跑它,采到的是新引擎的产出,' +
'整个「新旧对照」就成了自己跟自己比。'
);
}
}
// ── 采:七朝 × 1128 profile 的【判定投影】──
// ⚠ 只采判定相关的格子,不采 reasons/cites(那是文案,几十 MB,且不参与判定)。
const proj = (r) => (r === null ? null : {
ch: r.channel ? r.channel.id : null,
tier: r.rank.tier,
title: r.rank.title,
grade: r.rank.grade,
unit: r.rank.unit,
ceil: r.ceiling ? r.ceiling.tier : null,
cat: r.category || '',
stig: !!r.stigma,
blk: r.blocked.length,
});
const out = {
_what: '【加权求和版】引擎(score += val(k)*weight → tier = round(score/100*5))的产出,七朝 × 1128 profile。',
_why:
'★ 这一刀【必须】让输出变(原文里没有加权求和的原型)。所以这个文件【不是迁移锁】—— ' +
'它是【被告】:新引擎每改动一格,都要在 dynasties-shape.test.js 里说清楚是哪条原文要求它这么改。',
_dontRegen:
'★★ 绝不要用新引擎重新生成本文件。它的全部价值在于它是【旧代码】的产出。' +
'重生成 = 把被告改成原告 = 本项目铁律里的「假订正」。' +
'自证:五个单轨朝代的指纹与 dynasties-pre-multitrack.json 逐字相同(采集时已校验并通过)。',
_capturedBy: 'scripts/capture-weighted-sum.mjs(2026-07-16,改引擎之前)',
_matrix: PRE._matrix,
_selfCheck: '✓ han/weijin/nanchao/tang/ming 五朝指纹 = dynasties-pre-multitrack.json 的指纹(采集时校验通过)',
rows: Object.fromEntries(
sorted.map(([k, p]) => [k, Object.fromEntries(DYNASTIES.map((d) => [d.id, proj(computeRank(p, d.id))]))])
),
};
fs.writeFileSync(new URL('../test/fixtures/dynasties-weighted-sum.json', import.meta.url), JSON.stringify(out));
console.log(`✓ 采到 ${sorted.length} 个 profile × ${DYNASTIES.length} 朝;五朝指纹自证通过。`);