iter(g104): 留痕校验回查提交真实性
This commit is contained in:
@@ -1188,6 +1188,14 @@
|
||||
"acceptance": "有筛选词时显示「没有符合「关键词」的行」并给「清除筛选」按钮(一次性清空关键字信号与内核筛选、回第 1 页);无筛选词时显示「暂无数据」且不出现按钮;关键字用受控信号持有,与筛选框同源;每行文件仍 ≤ 200 行;npm run check 全绿",
|
||||
"notes": "自补:可用性;空状态行抽到 tableEmpty.ts,dataTable 顺手把 api 类型别名下沉到 types.ts 才没破 200 行",
|
||||
"status": "done"
|
||||
},
|
||||
{
|
||||
"id": "g104",
|
||||
"title": "留痕校验回查提交是否真实存在",
|
||||
"motivation": "iterations.log 目前只校验字段格式:commit 随便写个哈希、或复制粘贴时抄错一位,门禁照样全绿。留痕是「这条迭代真的落过」的唯一凭证,凭证本身不可验证等于没校验",
|
||||
"acceptance": "ua lint-iterations 额外做双向核对:每行 commit 必须能在 git 历史里按前缀命中,且该提交主题以 iter(<id>) 开头(兼容早期无 scope 的 iter: <id>);伪造 / 抄错的哈希报违规并退出码 1;非 git 环境(打包分发)自动跳过该维度;ITERATION.md 留痕章节写明该校验;npm run check 全绿",
|
||||
"notes": "自补:门禁工具链;一次 git log 建索引,150 行留痕不额外起进程",
|
||||
"status": "open"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ qa/probe ──门禁通过──▶ qa/stable ──人工审阅──▶ main
|
||||
4. **门禁**:跑 `npm run check`(build → demo → style → typecheck → smoke → index → verify)。
|
||||
- **通过**:提交到 `qa/probe`,提交信息按 `COMMITTING.md` 规范(`iter(<条目id>): <中文祈使句>`,元数据变更用 `chore(backlog): 记录 <id> 完成`;commit-msg 钩子自动校验),推送 `qa/probe`,fast-forward 合并到 `qa/stable` 并推送;将 backlog 条目 `status` 置为 `done` 并随迭代提交。
|
||||
- **失败**:尝试修复一次;仍失败则放弃本轮——`qa/probe` 直接重置回 `qa/stable`,backlog 条目在 `notes` 里追加失败原因、`status` 保持 `open`,提交并推送该元数据变更(仅改 `.ua/backlog.json`,不碰代码)。
|
||||
5. **留痕**:在 `.ua/iterations.log` 追加一行 JSON,**字段统一**:`{"ts":"本地ISO时间","id":"条目id","result":"done|aborted","commit":"短哈希","summary":"一句话"}`。硬性规范:`ts` 必须来自 `date` 命令实测(本地时间,带 +08:00 偏移,**禁止手写或用 UTC 换算**);时长结论必须来自两次时间查询之差,禁止使用「大约/接近」等估算词;并发实例格式不得自创变体。随本轮提交。
|
||||
5. **留痕**:在 `.ua/iterations.log` 追加一行 JSON,**字段统一**:`{"ts":"本地ISO时间","id":"条目id","result":"done|aborted","commit":"短哈希","summary":"一句话"}`。硬性规范:`ts` 必须来自 `date` 命令实测(本地时间,带 +08:00 偏移,**禁止手写或用 UTC 换算**);时长结论必须来自两次时间查询之差,禁止使用「大约/接近」等估算词;并发实例格式不得自创变体。随本轮提交。`ua lint-iterations` 会把每行 `commit` 拿到 git 历史里回查:哈希必须真实存在、主题必须指向同一条目(`iter(<id>)`,早期无 scope 的 `iter: <id>` 也认),伪造或抄错哈希直接判违规。
|
||||
6. **边界**:不改 `main` 分支保护、不删分支、不动 `.workbuddy/`、不重写历史、不 force push 到 `qa/stable` 与 `main`。
|
||||
|
||||
## 选题规则(自主补点子时)
|
||||
|
||||
@@ -1017,6 +1017,18 @@ function cmdCommitLint(args) {
|
||||
console.log(`commit-lint OK (${type}${scope ? `(${scope})` : ''})`);
|
||||
}
|
||||
|
||||
/*** 提交主题索引:一次 git log 换「短哈希 → 主题」表,供留痕回查,避免逐行起进程 ***/
|
||||
function commitSubjects() {
|
||||
const r = spawnSync('git', ['log', '--all', '--pretty=%h|%s'], { cwd: ROOT, encoding: 'utf8' });
|
||||
if (r.status !== 0) return null; // 非 git 环境(打包分发等)跳过该维度,不让整条门禁失效
|
||||
const pairs = [];
|
||||
for (const line of String(r.stdout ?? '').split('\n')) {
|
||||
const cut = line.indexOf('|');
|
||||
if (cut > 0) pairs.push([line.slice(0, cut), line.slice(cut + 1)]);
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
|
||||
/*** 迭代留痕校验:.ua/iterations.log 每行 JSON 字段与格式必须符合 ITERATION.md 规范 ***/
|
||||
function cmdLintIterations() {
|
||||
const file = path.join(INDEX_DIR, 'iterations.log');
|
||||
@@ -1041,6 +1053,23 @@ function cmdLintIterations() {
|
||||
if (o.result === 'aborted' && commit && !/^[0-9a-f]{7,40}$/.test(commit)) issues.push(`${tag} aborted 条目 commit 须为空或哈希`);
|
||||
if (!String(o.summary ?? '').trim()) issues.push(`${tag} summary 不能为空`);
|
||||
});
|
||||
// —— 留痕 ↔ 提交双向核对:哈希必须真实存在,且主题要指向同一条目(防伪造 / 防抄错哈希)——
|
||||
const pairs = commitSubjects();
|
||||
if (pairs) {
|
||||
lines.forEach((line, i) => {
|
||||
const tag = `iterations.log:${i + 1}`;
|
||||
let o;
|
||||
try { o = JSON.parse(line); } catch { return; } // 行格式问题已在上轮报过
|
||||
const hash = String(o.commit ?? '');
|
||||
if (!hash) return; // aborted 允许留空
|
||||
const hit = pairs.find(([h]) => h.startsWith(hash));
|
||||
if (!hit) { issues.push(`${tag} commit ${hash} 不在仓库历史中`); return; }
|
||||
const legacy = `iter: ${o.id}`; // 早期提交用「iter: <id> 描述」,无 scope
|
||||
if (!hit[1].startsWith(`iter(${o.id})`) && !hit[1].startsWith(legacy)) {
|
||||
issues.push(`${tag} commit ${hash} 的主题「${hit[1]}」没有指向条目 ${o.id}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (issues.length) {
|
||||
for (const it of issues) console.error('lint-iterations: ' + it);
|
||||
console.error(`${issues.length} violation(s)`);
|
||||
|
||||
Reference in New Issue
Block a user