fix(report): make density facts readable and printable
Independent Staging Quality Gate / validate (push) Failing after 11m4s
Independent Staging Quality Gate / publish (push) Skipped

Unify reader cleanup rules, lock writer table guards, and register the exact fictional timestamp collision. Preserve existing ordinary-report safety contracts and source-data gaps.

Validation: report Node 165/165, final safety 29/29, Python 101/101, Chrome 28/28; both PDFs retain all 130 rows. Full Node 3704 tests with the same 91 baseline failures. Privacy test: 62 passed, 1 failed due to 17 protected-file READ_ERRORs; not a green gate. Build, DB, manual checklist and controlled-login gaps remain documented. User explicitly authorized staging push with these gaps disclosed.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
jesse-ux
2026-09-23 15:26:25 +08:00
co-authored by Claude Code
parent 0d37bec15a
commit a12f2c0d26
27 changed files with 1220 additions and 210 deletions
+25 -27
View File
@@ -2,29 +2,30 @@
from __future__ import annotations
import json
from pathlib import Path
import re
STATUS_LABELS = {
"parameter_sensitive": "参数敏感",
"pyjhora_behavior_only": "仅单一外部参照,未做多引擎核对",
"not_multiengine_parity": "仅单一外部参照,未做多引擎核对",
"unresolved_external_tuple_boundary": "外部边界未对齐",
"partial_verified": "部分核验",
"raw_appendix_only": "仅原始附录可见",
"missing_in_local": "本地暂无",
"internal_reference_omitted": "内部参照已省略",
}
CELL_LABELS = {"blocked": "暂不可用", "executed": "已执行", "available": "可用", "computed": "已计算"}
_TOKEN = re.compile(r"\b(" + "|".join(STATUS_LABELS) + r")\b")
_PRODUCT = re.compile(
r"\bPL9(?:\.pdf)?(?:[ \t]*(?:第[ \t]*\d+(?:[ \t]*[–—/-][ \t]*\d+)*[ \t]*页|"
r"(?:pages?|p)[ \t-]*\d+(?:[ \t]*[–—/-][ \t]*\d+)*))?\b|"
r"\bPL9[ \t]*第[ \t]*\d+(?:[ \t]*[–—/-][ \t]*\d+)*[ \t]*页",
re.IGNORECASE,
)
_FUNCTION = re.compile(r"\b(?:jyotish_engine\.)?(?:cmd_[a-z0-9_]+|render_pl9_markdown|build_professional_report_reference_packet)\b")
_CELL = re.compile(r"(?<=\|)([ \t]*)(`?)(blocked|executed|available|computed)\2([ \t]*)(?=\|)")
# Both runtimes consume this file. ASCII regex semantics deliberately match JS:
# Python's default Unicode \b would leave Chinese page references untranslated.
_RULES = json.loads(Path(__file__).with_suffix(".rules.json").read_text(encoding="utf-8"))
_CHART_FENCE = re.compile(_RULES["chartFencePattern"], re.MULTILINE | re.ASCII)
_REPLACEMENTS = [
(re.compile(rule["pattern"], re.ASCII | (re.IGNORECASE if rule.get("ignoreCase") else 0)), rule)
for rule in _RULES["rules"]
]
def _replace(match: re.Match[str], rule: dict) -> str:
if "replacement" in rule:
return rule["replacement"]
return (
rule.get("prefix", "")
+ "".join(match[group] for group in rule.get("beforeGroups", []))
+ rule["labels"][match[rule["labelGroup"]]]
+ "".join(match[group] for group in rule.get("afterGroups", []))
)
def clean_reader_appendix_markdown(markdown: str) -> str:
@@ -33,13 +34,10 @@ def clean_reader_appendix_markdown(markdown: str) -> str:
Ambiguous English words are changed only as complete pipe-table cells.
Chart fences are immutable: their JSON is a separate renderer contract.
"""
parts = re.split(r"(^[ \t]*```jyotish-chart[^\n]*\n[\s\S]*?^[ \t]*```[^\n]*(?:\n|$))", markdown, flags=re.MULTILINE)
parts = _CHART_FENCE.split(markdown)
for index in range(0, len(parts), 2):
value = _TOKEN.sub(lambda match: STATUS_LABELS[match[0]], parts[index])
value = _FUNCTION.sub("本地计算", value)
value = re.sub(r"\b(?:[a-z0-9_]+pl9[a-z0-9_]*|pl9_[a-z0-9_]+)(?:\.v\d+)?\b", "外部参照资料", value, flags=re.IGNORECASE)
value = _PRODUCT.sub("外部参照资料", value)
value = re.sub(r"\b(?:PyJHora|JHora)\b", "外部参照引擎", value, flags=re.IGNORECASE)
value = _CELL.sub(lambda match: f"{match[1]}{match[2]}{CELL_LABELS[match[3]]}{match[2]}{match[4]}", value)
value = parts[index]
for pattern, rule in _REPLACEMENTS:
value = pattern.sub(lambda match: _replace(match, rule), value)
parts[index] = value
return "".join(parts)