Releases: danafitkowski/cpp-xer-parser
Release list
v0.2.1 — The validation report carries a summary and its worst severity
A patch release. The bundled ValidationReport serialises with the summary CPP's internal report carries, so a caller can read a report's worst severity from it.
Added
ValidationReport.to_dict()['summary']:block,warn,infoandpass(the number of findings at each severity),total, andworst_severity, the worst severity present, ranked BLOCK > WARN > INFO > PASS, and PASS for a report with no findings. The keys and values are the internal report's, in its order.cpp-critical-path-validatorreadssummary['worst_severity']from its embedded DCMA-14 report.ValidationReport.worst_severity, the property the summary reads, andcount()with no argument, the number of all findings.
count, worst_severity, the summary block and the severity ranking are AST-identical to the internal module without docstrings.
Nothing moves
The release adds a key, a property and an optional argument, and changes no existing value. to_dict() still carries counts and lists findings in the order they were added (the internal report sorts them worst first), and count(severity) is unchanged. xer_parser.py and config_profiles.py are unchanged.
Why a patch. Before 1.0 this project moves the minor number for a release that changes results a caller already reads, as v0.2.0 did, and the patch number for one that only adds.
Testing
tests/test_report_summary_2026_09_29.py has 9 synthetic tests; all 9 fail against v0.2.0's validation.py, and 7 mutants of the port are each killed. pytest tests/ is 109 tests across 11 files: 108 pass and the engine-parity test skips, and all 109 pass with cpp-cpm-engine's python_reference on sys.path. CI is green on Linux, macOS and Windows against Python 3.10, 3.11 and 3.12.
See CHANGELOG.md.
v0.2.0 — Calendars decode in both slot orders; working-day arithmetic, the writer and the summary are corrected
The first release since v0.1.0. Calendar decoding, working-day arithmetic, the XER writer and the schedule summary are corrected, a blank activity calendar id resolves to the project calendar, and the two validation entry points run from a plain clone.
Output changes
None of the public function signatures changed, but several results did, each from wrong to right:
- Finding
check_ids areXER-*(XER-PROJECT-MISSING,XER-CALENDAR-MISSING,XER-NO-TASKPREDand the rest), no longerAACE-31R-03-*. - Working-day counts and steps move on a finish-first calendar, on a worked exception day, for datetimes whose clock times differ, for half-day values, and for a zero-day step from a non-working day.
generate_summary:loe_countno longer counts WBS summary rows,critical_activitiesis the complete list, andcritical_pathhas nonotekey.validate_scheduleraises the new activity-calendar findings.
Fixed
-
Calendar time slots decode in either field order. P6 writes a slot as
(s|08:00|f|16:00)or(f|16:00|s|08:00), per calendar. Finish-first calendars decoded to no working days and were counted as Mon-Fri, and their worked exception days were filed as holidays. With it:- worked exceptions separated from their date by P6's line markers are no longer holidays;
- exception dates from 1970 to 2099 are kept (the window was 1990-2050);
- a day carrying work hours is never also a holiday.
-
Working-day arithmetic (
get_work_days_between,add_work_days,subtract_work_days):- worked exception days (
special_workdays) count; - both dates are read on their calendar day, so Friday 17:00 to Monday 08:00 counts both days, and a
datecompares with adatetime; - a span over 100 years returns
None; - half-days round half-up;
- a zero-day step snaps off a non-working day, as
cpp-cpm-enginedoes.
The
add_work_daysdocstring now states the gap contract:EF = add_work_days(ES, D - 1). - worked exception days (
-
generate_xercollapses tabs and line breaks inside values, so a value can no longer shift or split its row. -
parse_xerkeeps cells beyond a row's header under__extra_<column>keys. -
TABLE_ORDERwrites the resource-code assignment table asRSRCRCAT, the header P6 writes, and drops a phantomRISKTYPES. -
generate_summarycounts LOE and WBS summary rows separately (newwbs_count), adds a work-only completion (work_task_count,complete_work,percent_complete_work), and lists every critical activity. -
validate_scheduleandaace_31r_compliancerun from a plain clone.
Added
- Activity calendars:
resolve_task_calendars,with_resolved_calendarsandcalendar_resolution_blockread a blankTASK.clndr_idas the project calendar, then the default calendar;validate_scheduleraises BLOCKXER-TASK-CALENDAR-UNRESOLVEDand INFOXER-TASK-CALENDAR-FALLBACK;generate_summaryconverts float on the resolved calendar;get_calendar_mapentries carrydefault_flag.
Changed
- README:
- a Scope section states what this package does not include: a date-field gate, a calendar-decode warning channel, and working-day arithmetic beyond
get_work_days_between/duration_hours_to_days; - the XER generation rules give the measured field counts (PROJECT 71, SCHEDOPTIONS 25, PROJWBS 26, TASK 61, TASKPRED 11 at P6 23.10 to 24.12) in place of 72/26/27/62/12;
- the live test badge and a version badge replace the static "stable" badge.
- a Scope section states what this package does not include: a date-field gate, a calendar-decode warning channel, and working-day arithmetic beyond
- Validation findings cite the documents that govern them (AACE 29R-03, 38R-06, DCMA 14-Point #1), and seven finding messages are worded as sentences.
references/table-reference.mddocuments both time-slot orders again.SECURITY.mdsupports 0.2.x.
Testing
- Tests: 100 across 10 files, all on synthetic data (15 across 2 files at v0.1.0).
- Engine parity: one test compares 6,490
add_work_days/subtract_work_dayscalls withcpp-cpm-enginev2.9.49. It runs when the engine'spython_referencedirectory is onsys.pathand skips otherwise. - CI: 9/9 green on Linux, macOS and Windows with Python 3.10 to 3.12.
Full details: CHANGELOG.md.
v0.1.0 — Initial public release
Initial public release. Companion to cpp-cpm-engine.
Features
- Parse any Primavera P6 XER file into a structured Python dict with all tables, fields, and records preserved.
- Generate valid P6 24.12 XER files from parsed or hand-built data.
- Calendar decoding including full work-week patterns, special workdays, and holidays.
- Cross-reference maps for WBS hierarchy, resource assignments, predecessors/successors, activity codes, and UDFs.
- MIP 3.4 half-step XER generator (
compute_half_step_xer) — AACE 29R-03 MIP 3.4 (Modelled / Additive / Multiple Base — Contemporaneous Split). - BOM-aware encoding detection (UTF-8 BOM / UTF-16 LE/BE BOM).
- Schedule integrity manifest with SHA-256 source hash and AACE 31R-03 compliance scoring.
- Schema drift detection between two parsed XERs.
Engine compatibility
Tested against cpp-cpm-engine v2.9.x (current as of 2026-05-16: v2.9.11+). The parse output is consumed by cpm-engine.parseXER() and is independent of the engine math.
Security
See SECURITY.md — 90-day coordinated disclosure, hello@criticalpathpartners.ca with SECURITY in the subject.
See CHANGELOG.md for the full v0.1.0 entry.