feat(report): add personal report contract and persistence

This commit is contained in:
Jesse
2026-08-06 12:43:10 +08:00
parent 03d3b58ff7
commit 82dab96b07
14 changed files with 3796 additions and 0 deletions
@@ -0,0 +1,432 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://jyotisha.chat/contracts/personal-report/report-document.v1.schema.json",
"title": "ReportDocument v1",
"description": "Server-issued personal astrology report document. This contract is enforced identically by the JSON Schema below, frontend/src/lib/personal-report-contract.ts (Zod), and scripts/personal_report_contract.py (stdlib Python validator). Semantics that JSON Schema draft-07 cannot express are enforced by both runtime validators and their tests: (1) charts must contain exactly one D1 chart, chart ids must be unique, and the D1 chart must contain all twelve house numbers 1..12 (enough real houses to render without fabrication); (2) every houseNumber must be unique within its chart; (3) evidence ids (id fields of techniqueAudit, conflicts and calculationEvidence rows) must be globally unique across the whole evidence appendix so evidenceRefs are never ambiguous; (4) provenance.evidenceHash is a deterministic recomputation over the evidence appendix (techniqueAudit, conflicts, calculationEvidence in canonical field order) - it is never trusted as a model self-report; the cryptographic hash is verified by the server runtime (frontend/src/lib/personal-report-contract.server.ts) and by the Python validator (scripts/personal_report_contract.py), and a document whose evidenceHash does not equal the recomputed value is rejected; the isomorphic frontend contract validates structure only and never recomputes the hash; (5) every entry in evidenceRefs must reference an id present in evidenceAppendix.techniqueAudit, evidenceAppendix.conflicts, or evidenceAppendix.calculationEvidence; (6) sections whose claimStatus is blocked must not contain deterministic predictions (e.g. 必然, 必定, 一定会, 肯定会, 绝对会, guaranteed, definitely will); (7) the UTF-8 JSON serialization of the whole document must not exceed 1572864 bytes (1.5 MiB). Fixed reader order: this schema defines the display sequence executiveSummary, thematicNarrative, evidenceAppendix as a UI/type-level presentation contract; JSON object key order is not validated (objects are unordered by definition). Privacy rule: subject/provenance metadata must never repeat full birth date, precise coordinates, or a raw chart payload. Content rule: no HTML/JS/CSS, no executable URLs (javascript:, vbscript:, data:text/html, file:), no internal filesystem paths, no prompt/tool traces or exception stacks, no model secrets or JWTs.",
"type": "object",
"definitions": {
"claimStatus": {
"type": "string",
"enum": [
"multi_system_consensus",
"single_system_inference",
"parameter_sensitive",
"unclosed_divisional_chart",
"user_history_verification_required",
"blocked"
]
},
"evidenceId": {
"type": "string",
"pattern": "^ev-[a-z0-9_-]{1,63}$",
"minLength": 4,
"maxLength": 67
},
"sha256Hex": {
"type": "string",
"pattern": "^[0-9a-f]{64}$",
"minLength": 64,
"maxLength": 64
},
"iso8601": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,9})?(Z|[+-]\\d{2}:\\d{2})$",
"minLength": 20,
"maxLength": 40
},
"house": {
"type": "object",
"additionalProperties": false,
"properties": {
"houseNumber": {
"type": "integer",
"minimum": 1,
"maximum": 12
},
"sign": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"occupants": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"maxItems": 12
}
},
"required": ["houseNumber", "sign", "occupants"]
},
"planet": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"sign": {
"type": "string",
"minLength": 1,
"maxLength": 40
},
"longitudeDegrees": {
"type": "number",
"minimum": 0,
"exclusiveMaximum": 360
},
"houseNumber": {
"type": "integer",
"minimum": 1,
"maximum": 12
},
"retrograde": {
"type": "boolean"
}
},
"required": ["name", "sign", "longitudeDegrees", "houseNumber", "retrograde"]
},
"chart": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"enum": ["D1", "D9", "D10"]
},
"title": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"houses": {
"type": "array",
"items": {
"$ref": "#/definitions/house"
},
"maxItems": 12
},
"planets": {
"type": "array",
"items": {
"$ref": "#/definitions/planet"
},
"maxItems": 12
},
"claimStatus": {
"$ref": "#/definitions/claimStatus"
}
},
"required": ["id", "title", "houses", "claimStatus"]
},
"thematicSection": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z][a-z0-9_-]{0,63}$",
"minLength": 1,
"maxLength": 64
},
"title": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"narrative": {
"type": "string",
"minLength": 1,
"maxLength": 4000
},
"actions": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 400
},
"maxItems": 12
},
"caveats": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 400
},
"maxItems": 12
},
"claimStatus": {
"$ref": "#/definitions/claimStatus"
},
"evidenceRefs": {
"type": "array",
"items": {
"$ref": "#/definitions/evidenceId"
},
"maxItems": 24
}
},
"required": ["id", "title", "narrative", "actions", "caveats", "claimStatus", "evidenceRefs"]
},
"techniqueAuditRow": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"$ref": "#/definitions/evidenceId"
},
"techniqueId": {
"type": "string",
"pattern": "^[a-z0-9_.-]{1,80}$",
"minLength": 1,
"maxLength": 80
},
"techniqueName": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"status": {
"type": "string",
"enum": ["verified", "partial", "blocked"]
},
"used": {
"type": "boolean"
},
"notes": {
"type": "string",
"maxLength": 500
}
},
"required": ["id", "techniqueId", "techniqueName", "status", "used"]
},
"conflictRow": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"$ref": "#/definitions/evidenceId"
},
"description": {
"type": "string",
"minLength": 1,
"maxLength": 1000
},
"impact": {
"type": "string",
"minLength": 1,
"maxLength": 500
},
"status": {
"type": "string",
"enum": ["unresolved", "partial", "resolved"]
}
},
"required": ["id", "description", "impact", "status"]
},
"calculationEvidenceRow": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"$ref": "#/definitions/evidenceId"
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"value": {
"type": "string",
"minLength": 1,
"maxLength": 500
},
"source": {
"type": "string",
"minLength": 1,
"maxLength": 200
}
},
"required": ["id", "label", "value", "source"]
}
},
"additionalProperties": false,
"properties": {
"schemaVersion": {
"type": "string",
"const": "report_document.v1"
},
"reportId": {
"type": "string",
"format": "uuid",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
},
"reportType": {
"type": "string",
"enum": ["personal_full", "personal_thematic"]
},
"presentationMode": {
"type": "string",
"enum": ["default", "research"]
},
"generatedAt": {
"$ref": "#/definitions/iso8601"
},
"subject": {
"type": "object",
"additionalProperties": false,
"properties": {
"displayName": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"birthTimeStatus": {
"type": "string",
"enum": ["reported", "candidate", "accepted", "confirmed"]
},
"birthPlaceLabel": {
"type": "string",
"minLength": 1,
"maxLength": 200
}
},
"required": ["displayName", "birthTimeStatus", "birthPlaceLabel"]
},
"provenance": {
"type": "object",
"additionalProperties": false,
"properties": {
"skillSourceCommit": {
"type": ["string", "null"],
"pattern": "^[0-9a-f]{40}$",
"minLength": 40,
"maxLength": 40
},
"skillSnapshotSha256": {
"$ref": "#/definitions/sha256Hex"
},
"calculationHash": {
"$ref": "#/definitions/sha256Hex"
},
"evidenceHash": {
"$ref": "#/definitions/sha256Hex"
},
"reportContractVersion": {
"type": "string",
"const": "1"
}
},
"required": ["skillSourceCommit", "skillSnapshotSha256", "calculationHash", "evidenceHash", "reportContractVersion"]
},
"executiveSummary": {
"type": "object",
"additionalProperties": false,
"properties": {
"headline": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"summary": {
"type": "string",
"minLength": 1,
"maxLength": 2000
},
"priorities": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 200
},
"maxItems": 8
},
"overallClaimStatus": {
"$ref": "#/definitions/claimStatus"
}
},
"required": ["headline", "summary", "priorities", "overallClaimStatus"]
},
"charts": {
"type": "array",
"items": {
"$ref": "#/definitions/chart"
},
"minItems": 1,
"maxItems": 3
},
"thematicNarrative": {
"type": "array",
"items": {
"$ref": "#/definitions/thematicSection"
},
"maxItems": 12
},
"evidenceAppendix": {
"type": "object",
"additionalProperties": false,
"properties": {
"expandedByDefault": {
"type": "boolean"
},
"techniqueAudit": {
"type": "array",
"items": {
"$ref": "#/definitions/techniqueAuditRow"
},
"maxItems": 100
},
"conflicts": {
"type": "array",
"items": {
"$ref": "#/definitions/conflictRow"
},
"maxItems": 50
},
"calculationEvidence": {
"type": "array",
"items": {
"$ref": "#/definitions/calculationEvidenceRow"
},
"maxItems": 100
},
"blockedTechniques": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"maxItems": 100
}
},
"required": ["expandedByDefault", "techniqueAudit", "conflicts", "calculationEvidence", "blockedTechniques"]
},
"disclaimer": {
"type": "string",
"minLength": 1,
"maxLength": 2000
}
},
"required": [
"schemaVersion",
"reportId",
"reportType",
"presentationMode",
"generatedAt",
"subject",
"provenance",
"executiveSummary",
"charts",
"thematicNarrative",
"evidenceAppendix",
"disclaimer"
]
}