feat(report): birth-sky report cover bound to the report's birth fingerprint (F1–F3)
Product decision A (TASK-birth-sky-followup-20260928): - every generation path writes subject.birthFingerprint (stored-row fingerprint, same function as the chart page's profileFingerprint); never into the evidence bundle the model reads - GET /api/reports/:id compares on the server and returns only report.coverSubject (subject id or null); legacy reports never get one - report page shows the night cover above the body, paper cover alone on the first printed A4 page; silent on any failure, no waiting state - TS / JSON schema / Python contract accept the optional field - BLOCKED T5 struck through; DESIGN §17, CHANGELOG, checklist, PROGRESS Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
14ef18ac24
commit
a9a917d50c
@@ -61,6 +61,7 @@ FAILURE_CODES = (
|
||||
UUID_PATTERN = re.compile(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
|
||||
SHA256_PATTERN = re.compile(r"^[0-9a-f]{64}$")
|
||||
SHA1_PATTERN = re.compile(r"^[0-9a-f]{40}$")
|
||||
BIRTH_FINGERPRINT_PATTERN = re.compile(r"^[0-9a-f]{32}$")
|
||||
SKILL_NAME_PATTERN = re.compile(r"^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$")
|
||||
SKILL_VERSION_PATTERN = re.compile(
|
||||
r"^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)"
|
||||
@@ -301,7 +302,9 @@ def _validate_subject(result: ValidationResult, value: Any) -> None:
|
||||
if subject is None:
|
||||
return
|
||||
required = ("displayName", "birthTimeStatus", "birthPlaceLabel")
|
||||
_check_keys(result, "subject", subject, required)
|
||||
_check_keys(result, "subject", subject, required, (*required, "birthFingerprint"))
|
||||
if "birthFingerprint" in subject:
|
||||
_check_pattern(result, "subject.birthFingerprint", subject.get("birthFingerprint"), BIRTH_FINGERPRINT_PATTERN, "birth fingerprint")
|
||||
_check_text(result, "subject.displayName", subject.get("displayName"), TEXT_LIMITS["displayName"])
|
||||
_check_enum(result, "subject.birthTimeStatus", subject.get("birthTimeStatus"), BIRTH_TIME_STATUSES)
|
||||
_check_text(result, "subject.birthPlaceLabel", subject.get("birthPlaceLabel"), TEXT_LIMITS["birthPlaceLabel"])
|
||||
|
||||
Reference in New Issue
Block a user