feat: accept ERP-semantic roster workbook headers
This commit is contained in:
1 parent
ffa3340899
commit
e68fcc1ce3
22 files changed
+569
-89
No files matched your search
@@ -0,0 +1,37 @@
|
||||
# Evidence: Roster workbook header rejection
|
||||
|
||||
## Identity
|
||||
|
||||
- Task: `20260901-roster-header-error-a4f7`
|
||||
- Observed at: 2026-09-01, from the user-supplied task-event log
|
||||
- Source: event `4110`, manual attachment attempt
|
||||
- Confidence: high for the failure boundary; insufficient to identify the exact mismatching header cell
|
||||
|
||||
## Observed behavior
|
||||
|
||||
- The initial roster instruction entered `awaiting_attachment` with the normal `.xls/.xlsx` waiting message.
|
||||
- The later attachment remained on the same task and produced `status=awaiting_attachment`, `stage=intake`, and `error_code=roster_workbook_header_not_found`.
|
||||
- The event reports only a bounded byte count and SHA-256. It does not contain workbook headers or cell values.
|
||||
|
||||
## Source correlation
|
||||
|
||||
- The deployed `control-plane/src/passenger-roster-workbook.ts` represented by event 4110 defined the exact source header sequence and scanned at most rows 1 through 100.
|
||||
- Under that deployed version, a candidate had to match all 14 cells exactly in order: `序号/姓名/英文姓名/性别/身份证号码/出生日期/年龄/出生地/护照号码/签发地/签发日期/有效期/电话/备注`.
|
||||
- The header must be on row 2. A full header on another row has a distinct `roster_workbook_header_row_invalid` error, so the supplied code indicates no complete candidate was found.
|
||||
- `TaskService.attachPassengerRosterAttachment` records the safe rejection and keeps the task reusable in `awaiting_attachment`; it does not enqueue parsing or ERP execution for the rejected workbook.
|
||||
|
||||
## Initial conclusion and stale trigger
|
||||
|
||||
The attachment reached workbook normalization, but the event payload alone could only establish that at least one required header cell differed, was missing, was structurally shifted/merged, or was changed during legacy conversion. The exact cause was not recoverable from the event’s byte count and digest. Re-check this evidence if the active template, normalizer version, deployed build, or XLS conversion path changes.
|
||||
|
||||
## Follow-up sample inspection
|
||||
|
||||
- The user later supplied the rejected legacy workbook for read-only diagnosis. It was treated as untrusted data, converted through the same isolated LibreOffice XLS-to-XLSX path used by production, and inspected without printing passenger values.
|
||||
- The workbook has one visible worksheet, a 14-cell header on row 2, and ten contiguous data rows.
|
||||
- The direct header mismatch is the label `身份证` in column 14. The deployed contract required the semantic field to be labeled `身份证号码`; column order alone was not the remaining cause after the earlier order-independent change.
|
||||
- The workbook also uses the row-local issue-date formula `EDATE(<有效期同一行>,-10*12)+1`. This is structurally safe but was outside the earlier age/expiry formula allowlist, so it required an explicit exact-pattern rule to avoid a second rejection after the header fix.
|
||||
- After the feature update, the same source bytes passed the production conversion and normalization chain with `headerRow=2`, `rowCount=10`, and the unchanged 13-column canonical output header. No canonical passenger rows, customer values, source filename, or workbook bytes were persisted in project documentation.
|
||||
|
||||
## Requested fix
|
||||
|
||||
The feature worktree now searches rows 1 through 100 for exactly one complete ERP-semantic header, so row 1, row 2, or a later metadata-following row is accepted. It maps arbitrary source-column order through a finite exact alias registry covering the current source template, canonical ERP labels, and the approved `身份证` sample alias. `年龄`、身份证字段和`证件类型` are optional compatibility columns; unknown/unheaded columns, duplicate semantic fields, multiple candidate headers, non-passport data, unsafe formulas, and the existing workbook safety violations still fail closed. The canonical 13-column TSV order is unchanged. Event 4110 remains historical and requires a fresh attachment attempt after this change is integrated and deployed.
|
||||
Reference in new issue
Block a user