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
@@ -495,6 +495,100 @@
"maxLength": 80
}
},
"rows": {
"type": "array",
"maxItems": 2000,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"sourcePath",
"cells"
],
"properties": {
"sourcePath": {
"type": "string",
"minLength": 1,
"maxLength": 400,
"pattern": "^[A-Za-z0-9_.\\[\\]-]+$"
},
"cells": {
"type": "array",
"minItems": 1,
"maxItems": 16,
"items": {
"anyOf": [
{
"type": "string",
"maxLength": 300
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "null"
}
]
}
}
}
}
},
"subtables": {
"type": "array",
"maxItems": 8,
"items": {
"$ref": "#/definitions/factSubtable"
}
}
}
},
"factSubtable": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"title",
"sourcePath",
"note",
"columns",
"rows"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"maxLength": 80,
"pattern": "^[a-z][a-z0-9_-]*$"
},
"title": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"sourcePath": {
"type": "string",
"minLength": 1,
"maxLength": 400,
"pattern": "^[A-Za-z0-9_.\\[\\]-]+$"
},
"note": {
"type": "string",
"maxLength": 500
},
"columns": {
"type": "array",
"minItems": 1,
"maxItems": 16,
"items": {
"type": "string",
"minLength": 1,
"maxLength": 80
}
},
"rows": {
"type": "array",
"maxItems": 2000,