test(reports): lock CRLF fence-only export changes
Independent Staging Quality Gate / validate (push) Failing after 10m37s
Independent Staging Quality Gate / publish (push) Skipped

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
jesse-ux
2026-09-24 18:27:14 +08:00
co-authored by Claude Code
parent fa8fef559b
commit 133aca49db
4 changed files with 34 additions and 5 deletions
+1 -1
View File
@@ -11,7 +11,7 @@
## BUG-1020:CRLF 无 JSON 与旧导出逐字节合同冲突(2026-09-24)
- 2026-09-24 产品批准 D5 有限例外(D14),裁决阻塞解除,修复已在本地完成;待定向门禁、staging 推送与部署 health 复核。
- 2026-09-24 产品批准 D5 有限例外(D14),本地修复与回归已完成;默认 Gitea 写入认证返回 `Failed to authenticate user`,因此 staging 推送、门禁和部署 health 仍 blocked。
- 独立审查使用真实虚构golden只转换换行,正文下载保留22段图盘JSON,同时仍等于旧导出。根因是旧FENCE_RE仅接受语言标记后的LF,属于继承缺陷。
- D13只放开安全SVG,没有授权改变D5;未静默修复或声称全部验收通过。建议CRLF围栏输入作有限例外后最小修复,待裁决,见 `docs/tasks/TASK-report-chapter-export-fix-20260924.md`。
+1 -1
View File
@@ -13590,7 +13590,7 @@
## BUG-1020 | CRLF 普通报告下载保留图盘 JSON 围栏
- 状态:resolved(本地修复,待 staging 门禁与部署 health 复核)
- 状态:blocked(本地修复已完成,staging 写入认证失败,待 staging 门禁与部署 health 复核)
- 首次发现 / 最近更新:2026-09-24。
- 影响面:旧普通Markdown下载与新分块导出的正文组。
- 现象 / 触发:真实引擎虚构golden仅将LF换成CRLF,正文下载残留22段图盘JSON;新分盘组仍可提取22盘。
@@ -2,7 +2,7 @@
## 当前结论
已按 D14 有限例外完成最小修复:图盘语言围栏的两个换行边界均接受 LF/CRLF;未标准化整篇正文。真实虚构 reader golden 的 LF、CRLF、混合换行均不再残留 JSON 围栏,LF 输出保留冻结 SHA。已提交 `d0cec97071f6979c59453d1a011c0f67639a61f9`;推送 staging 时远端认证失败,尚未取得 staging/deploy health 验收。
已按 D14 有限例外完成最小修复:图盘语言围栏的两个换行边界均接受 LF/CRLF;未标准化整篇正文。真实虚构 reader golden 的 LF、CRLF、混合换行均不再残留 JSON 围栏,LF 输出保留冻结 SHA。实现及初始回归已在本地提交;当前最终状态见交付状态,尚未取得 staging/deploy health 验收。
## 实现与验收
@@ -16,7 +16,7 @@
## 测试与环境
- 开工 pre-work check 已运行:远端可见性、适配器和碎片扫描通过;focused preflight 复现既有 `.workbuddy/skills/jyotish-vedic-astrology` 镜像路径断言失败,整体退出 1。未改测试、未伪造镜像。
- 定向报告测试 23/23 通过;`tsc --noEmit` 通过;`npm run lint` 0 errors、119 个既有 warnings。完整测试/build、真机/部署按清单如实记录。
- 定向报告测试 23/23 通过;`tsc --noEmit` 通过;`npm run lint` 0 errors、119 个既有 warnings。完整测试 3682 pass / 84 fail(失败名称与基线既有环境失败一致,未因本单新增);build 因 Windows Skill symlink/动态文件系统 tracing 在 `/api/birth-time-guide` 失败;真机/部署按清单如实记录。
## 既有断言三栏
@@ -28,4 +28,4 @@
## 交付状态
已提交 `d0cec97071f6979c59453d1a011c0f67639a61f9`;按任务书同步 `origin/staging` 后尝试 `git push origin HEAD:staging`,远端返回 `Failed to authenticate user`,因此未推送、未部署,等待具备远端认证后重试。
已整理为本地提交 `9f12ae546b92fc168c1897056f9f273f17aeecec`;按任务书同步 `origin/staging` 后尝试 `git push origin HEAD:staging`,远端返回 `Failed to authenticate user`,因此未推送、未部署,等待具备远端认证后重试。
@@ -71,6 +71,35 @@ test("CRLF and mixed-newline golden exports remove every JSON chart fence", () =
assert.equal((output.match(/```jyotish-chart/g) ?? []).length, 0);
assert.equal((output.match(/<svg\b/gi) ?? []).length, 22);
assert.deepEqual(ordinaryOutputLeaks(output), []);
const selected = buildReportExportBlocks({ markdown });
const bodyOutput = joinExportBlocks(selected.filter(block => block.group === "body"));
assert.equal(bodyOutput, output);
assert.equal(selected.filter(block => block.group === "chart").length, 22);
const projected = projectOrdinaryReportMarkdown(markdown);
assert.deepEqual(
[...output.matchAll(/<svg\b[^>]*>[\s\S]*?<\/svg>/g)].map(match => match[0]),
[...projected.matchAll(/<svg\b[^>]*>[\s\S]*?<\/svg>/g)].map(match => match[0]),
);
// Independent line scanner: only fence lines and their adjacent boundary
// whitespace may change; the retired stripper's LF blank-run rule remains.
const lines = projected.match(/[^\n]*\n|[^\n]+$/g) ?? [];
let expected = "";
let insideFence = false;
for (let index = 0; index < lines.length; index += 1) {
const line = lines[index];
if (!insideFence && line.trim() === "```jyotish-chart") {
expected = expected.replace(/\r?\n[ \t]*$/, "");
insideFence = true;
} else if (insideFence && line.trim() === "```") {
expected += "\n\n";
if (index + 1 < lines.length) lines[index + 1] = lines[index + 1].replace(/^[ \t]*/, "");
insideFence = false;
} else if (!insideFence) {
expected += line;
}
}
assert.equal(insideFence, false);
assert.equal(output, expected.replace(/\n{3,}/g, "\n\n"), "D14 permits no other prose or newline changes");
}
});
test("all-group export adds charts and tables after unchanged ordinary body", () => {