跨端: feat(对齐): 参照物版本登记(CalendarView.tsx @d78f19f,变了即红)+ 圆角按语义配对(数值来源不同另行登记)
pi 2026-09-14 骨架开工前两件。 1. **对齐参照物要有版本号**:WebUI `CalendarView.tsx` 可能同时在动(gui-lab 有未合入改动), 照工作副本画完之后参照物一变,这版就成了"照一份没人认领的草案对齐的",而**没人能判它对不对**。 新增 `docs/ALIGN-REFS.json`(blob 哈希 + 登记于哪个 commit + "以哪次为准") + 判据 `test/align-refs.test.mjs`:哈希变了即红,报错按 §14 写明 「正确修法 = 读差异→判断骨架要不要改→再更新登记」与 「最常见的错误修法 = 把新哈希抄进去(那是把闸门降级成状态记录)」。变异确认会红。 当前登记:`d78f19f`「日历页面补上圆角」,工作副本干净 —— 若另有未合入的,合入后再对一次。 2. **圆角必须走令牌,且跨端按语义配对**:鸿蒙侧已有 `Theme.ets:105/107` 的 `radiusCard`/`radiusControl`(**系统**资源),WebUI 是 `--radius-card: 0.875rem` / `--radius-control: 0.5rem`。⇒ 端**语义对齐、数值来源不同**,所以登记写成"按语义配对", 并且判据要求每条都写明"按语义还是按数值"(否则下一个人会直接去比数字)。 数值差异本身按形态差异进余额:`radius-card-numeric-divergence`(等设备并排看再决定以谁为准)。 鸿蒙侧不许把 14 / 0.875 抄成裸数字 —— 与当初 14 处 Material 调色板清零同一形态,量纲换成长度。
This commit is contained in:
66
client/electron/test/align-refs.test.mjs
Normal file
66
client/electron/test/align-refs.test.mjs
Normal file
@ -0,0 +1,66 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { prose } from './lib/read.mjs';
|
||||
|
||||
/*
|
||||
★ 对齐参照物必须有**版本号**(pi 2026-09-14 §1)。
|
||||
|
||||
WebUI 的 `CalendarView.tsx` 可能同时在动(gui-lab 有未合入的改动)。照工作副本画完之后,
|
||||
参照物一变,这一版就成了"照一份没人认领的草案对齐的" —— 而且**没人能判它对不对,
|
||||
因为参照物没有版本号**。所以把参照物的 blob 哈希登记在 `docs/ALIGN-REFS.json`,
|
||||
**它一变就红**,逼一次"重新核对再更新登记"。
|
||||
|
||||
报错按 §14 写"正确修法 + 最常见的错误修法":正确修法是**重新核对对齐**(读差异、改骨架、再更新登记),
|
||||
**不是**把新哈希抄进去 —— 那是把这条判据降级成"记录当前状态",它就不再是闸门了。
|
||||
*/
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = join(HERE, '..', '..', '..');
|
||||
|
||||
test('★ 对齐参照物的版本必须与登记一致(变了就重新核对,不是抄新哈希)', () => {
|
||||
const reg = JSON.parse(prose(join(ROOT, 'docs', 'ALIGN-REFS.json')));
|
||||
assert.ok(Array.isArray(reg.refs) && reg.refs.length > 0, '登记里至少要有一个参照物');
|
||||
|
||||
const drifted = [];
|
||||
for (const r of reg.refs) {
|
||||
const res = spawnSync('git', ['hash-object', r.path], { cwd: ROOT, encoding: 'utf8' });
|
||||
assert.equal(res.status, 0, `要能算 ${r.path} 的 blob 哈希:${res.stderr}`);
|
||||
const now = res.stdout.trim();
|
||||
if (now !== r.blob) drifted.push({ id: r.id, path: r.path, registered: r.blob.slice(0, 12), now: now.slice(0, 12), at: r.atCommit });
|
||||
}
|
||||
assert.deepEqual(drifted, [],
|
||||
`对齐参照物变了,登记还是旧的:\n ${drifted.map(d => `${d.id}(${d.path}):登记 ${d.registered}(@${d.at})→ 现在 ${d.now}`).join('\n ')}\n` +
|
||||
`**正确修法**:读一遍参照物的差异 → 判断骨架要不要跟着改(并说明改了哪里)→ 再把登记的 blob/commit 更新。\n` +
|
||||
`**最常见的错误修法**:把新哈希抄进去就完事 —— 那是把这条判据降级成"记录当前状态",\n` +
|
||||
`它就不再是闸门,"照一份没人认领的草案对齐"这件事会静默发生。`);
|
||||
|
||||
// 每一条都要有出处(哪个 commit)与它对齐的是什么,否则"版本号"只是个数字
|
||||
for (const r of reg.refs) {
|
||||
assert.ok(r.atCommit && r.atCommitSubject, `参照物 ${r.id} 必须写明登记于哪个 commit(否则无人能判断对齐目标)`);
|
||||
assert.ok(r.note && r.note.trim(), `参照物 ${r.id} 必须写明"以哪次为准"`);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
★ 圆角也是"裸值"那一族:从 `index.css` 抄一个数字进 `.ets`,今天看起来一样,
|
||||
等 WebUI 改一次半径,鸿蒙这边**没有任何东西会红**(与当初 14 处 Material 调色板同一形态,
|
||||
量纲从颜色换成长度)。所以:**鸿蒙侧圆角必须来自 Theme.ets 令牌**,
|
||||
且语义配对登记在 ALIGN-REFS.json 里(数值来源不同属于形态差异,另行登记)。
|
||||
*/
|
||||
test('★ 圆角走令牌:鸿蒙侧必须有 radius 令牌,且每一条语义都在登记里配了对', () => {
|
||||
const reg = JSON.parse(prose(join(ROOT, 'docs', 'ALIGN-REFS.json')));
|
||||
const theme = prose(join(ROOT, 'client', 'harmony', 'entry', 'src', 'main', 'ets', 'common', 'Theme.ets'));
|
||||
assert.match(theme, /radiusCard/, 'Theme.ets 必须有卡片圆角令牌(不许在页面里写裸数字)');
|
||||
assert.match(theme, /radiusControl/, 'Theme.ets 必须有控件圆角令牌');
|
||||
|
||||
assert.ok(Array.isArray(reg.radius) && reg.radius.length >= 2, '圆角的语义配对要登记');
|
||||
for (const r of reg.radius) {
|
||||
assert.ok(r.semantic && r.webui && r.harmony, `圆角条目必须写明语义、WebUI 侧与鸿蒙侧出处`);
|
||||
assert.match(r.webui, /--radius-/, `WebUI 侧要指向变量(不是抄来的数字):${r.semantic}`);
|
||||
assert.match(r.harmony, /Theme\.ets/, `鸿蒙侧要指向令牌出处:${r.semantic}`);
|
||||
assert.ok(r.judgement && r.judgement.includes('语义'), `${r.semantic} 必须写明按语义对齐还是按数值对齐(否则下一个人会去比数字)`);
|
||||
}
|
||||
});
|
||||
@ -77,6 +77,7 @@ const SUITE = [
|
||||
['test/appearance-defaults.test.mjs', [], 4],
|
||||
['test/build-stamp.test.mjs', [], 7],
|
||||
['test/packaging.test.mjs', [], 5],
|
||||
['test/align-refs.test.mjs', [], 2],
|
||||
['test/harmony-calendar.test.mjs', ['--experimental-strip-types', '--no-warnings'], 10],
|
||||
['test/debt-visibility.test.mjs', [], 1],
|
||||
['test/commit-hygiene.test.mjs', ['--experimental-strip-types', '--no-warnings'], 2],
|
||||
|
||||
Reference in New Issue
Block a user