Releases: danafitkowski/cpp-cpm-engine
v2.9.27 — Audit closeout (13 items); crossval 444→747
v2.9.27 — Audit closeout + crossval expansion
Final addressable-scope release before v3.0. Closes 13 specific audit findings by direct file:line cross-reference, including all three longest-standing deferred paired-fix items.
Headline metric
Crossval JS↔Python bit-identical surface went from 444 → 747 checks across 43 fixtures, via backporting tf_working_days, ff, and ff_working_days to Python (F24 documented JS-only gap LIFTED).
Paired JS+Python fixes (the three deferred items)
- R6 Completed-successor skip in backward pass (SCL Protocol §4 / AACE 29R-03 §4 retained-logic)
- R12 data_date floor snaps forward to next workday on non-workday calendars
- R21 Python
add_work_daysMonFri fast path (~250× speedup at 30d walks)
Python parity backports
- R9
tf_working_days+_count_work_days_betweenhelper - F24
ff+ff_working_days(full FF loop, FF/SF-binding-succ calendar correction) - A12-M1/M2/M4 topology hash hardenings:
str()coercion,input_relationship_countvshashed_relationship_count,algorithm: nullfor empty
Engine MED/HIGH
- R10 Python
_cal_forhonorsproject_calendarfallback (was JS-only) - R6 MS_Start/SO
constraint-widens-lfWARN (paired with existing MS_Finish/MFO WARN) - R18 5 method_ids gained AACE-canonical methodology labels (computeScheduleHealth, computeBayesianUpdate, computeKinematicDelay, computeTopologyHash, computeFloatBurndown)
Disclosure / docs / test
- R16 DAUBERT/CONTRIBUTING crossval counts refreshed to 1071/747/43
- R14 Array.isArray() topology-hash gate + coverage-gap caveat
- R8 T3.18 in-progress test extended with TF/LF/CP assertions
- R7 docs/api.md activity-code contract documented
Test state
| Metric | v2.9.26 | v2.9.27 |
|---|---|---|
| Unit tests | 1056/0 | 1071/0 |
| Crossval fixtures | 43/0 | 43/0 |
| Crossval checks | 444/444 | 747/747 |
Audit ledger status
This release closes every patchable engineering item from the 20-agent audit ledger. Remaining items are all v3.0 architectural scope:
- Section D full calendar-awareness (fold Section C into runCPM)
- Welford's online variance for Bayesian
- Lognormal/Beta exact-quantile inverse-CDF CIs
- Sub-day lag precision (engine-wide ripple)
- Python TT_Hammock + TT_LOE implementation
- Engine epoch move (fixes R12 epoch collision)
- Hammock-of-hammocks LS_CEIL walker class
The v2.9.x audit-driven engineering wave is complete. v3.0 will be a design-and-implement cycle, not a patch wave.
v2.9.26 — Provenance sidecars + citation polish
v2.9.26 — Provenance sidecars + citation polish
3 audit items closed.
Provenance
- R20 LOW —
npm run attestwritescpm-engine.js.sha256andpython_reference/cpm.py.sha256sidecar files for mechanicalshasum -cverification
Bayesian citations
- R22 LOW — Elshaer (2013) full citation; paraphrased "38%" percentage removed
- R22 LOW — Bayesian + kinematic Python parity gap explicitly disclosed in DAUBERT.md
Test state
| Metric | v2.9.25 | v2.9.26 |
|---|---|---|
| Unit tests | 1056/0 | 1056/0 |
| Crossval | 444/444 | 444/444 |
Audit ledger
~98 cumulative closed. ~12 still open (Python F4/F6 backports, hammock-of-hammocks LS walker, MCP-side, 7 v3.0 architectural).
v2.9.25 — Perf wave + Python parity partial
v2.9.25 — Perf wave + Python parity partial
Engine perf (3)
- R21 OoS detector memoizes actual_start offsets (~500k fewer Date constructions on 25k-activity schedules)
- R21
_isCleanMonFriuses bitmask not Set alloc (~200k fewer throw-away Sets per CPM run) - R21 Section D constraint helpers hoist
projectStartparse (~300k fewer redundant Date constructions)
Python parity (1 partial)
- R21 Python
add_work_dayscaches holiday Set on calendar_info (avoids 73M list-to-set ops on 50k×365-holiday schedules). MonFri fast-path reverted — broke 444/444 → 440/444; paired-fix candidate documented.
Daubert doc (1)
- R8 DAUBERT.md notes
progress_overrideschedule mode is unsupported (retained-logic only, already alerted; now also in public disclosure docs).
Test state
| Metric | v2.9.24 | v2.9.25 |
|---|---|---|
| Unit tests | 1056/0 | 1056/0 |
| Crossval fixtures | 43/0 | 43/0 |
| Crossval checks | 444/444 | 444/444 |
Audit ledger
~95 cumulative closed v2.9.13–v2.9.25. ~15-20 still open (Python F4/F6 backports, hammock FS hard-precedence, MCP-side). ~7 deferred to v3.0.
v2.9.24 — Continued small-batch (5 items)
v2.9.24 — Continued small-batch fix wave
Five more audit findings closed/documented; per-fix-per-commit cadence.
Engine
- R7 HIGH _mcTopologicalSort fallback codepoint sort (deterministic for numeric-string codes)
- R8 HIGH OoS detector flags pred.actual_start > data_date (retroactive-edit signature)
- R12 HIGH data_date calendar-aware floor — documented as Python-parity-paired-fix candidate
- R15 HIGH Hammock-of-hammocks FS-succ all-hammock chain edge case documented
Investigations that turned out already-closed
13 audit codes checked against current code: R6 LF backward pin, R9 FF clamp, R9 _findLatestFinish, R10 lag math, R12 actual_start>actual_finish, R13 parseInt, R14 verifyReport, R14 delimiter escape, R14 float roundoff, R16 fixture-count stale, R17 rule string FRE 707, R18 prong-4 firm names, R19 self-loop — all addressed earlier in v2.9.13–v2.9.22, not double-counted.
Test state
| Metric | v2.9.23 | v2.9.24 |
|---|---|---|
| Unit tests | 1056/0 | 1056/0 |
| Crossval fixtures | 43/0 | 43/0 |
| Crossval checks | 444/444 | 444/444 |
Audit ledger
~90 cumulative closed v2.9.13–v2.9.24. ~20-25 still open (perf, Python parity backports for R6/R12, MCP-side, hammock FS hard-precedence). ~7 deferred to v3.0.
v2.9.23 — Small-batch fix wave (16 audit items closed)
v2.9.23 — Small-batch fix wave
Sixteen audit findings closed by per-fix-per-commit cadence (each fix tested + crossval-verified before moving to the next).
Engine math + correctness (7)
- R12 SUB_DAY_LAG alert dedup (no more 500-copy spam)
- R13 codepoint string comparator (JS↔Python sort parity for non-ASCII)
- R15 TARGET_DRTN_MISSING WARN on in-progress without target_drtn_hr_cnt
- R9 ALAP-slide-violates-succ WARN per affected successor
- R21 stable quadratic-formula form (kinematic breach forecast)
- R13 Math.min(...candidates) invariant comment
- R6 completed-succ LF-backward-pull documented as Python-parity blocker
Bayesian (2)
- R22
opts.sigma_shrinkage_factorconfigurable (default 0.5) - R22
opts.computed_atoverride for byte-identical determinism
Holiday rules (1)
- R11 CA-AB / CA-SK Family Day
effective_fromyear guards
Daubert / brand polish (4)
- R17 README MIP claims rescoped to "math primitives"
- R17
docs/citations.mdMIP 3.3 synonym acknowledgment - R17 Sanders citation date format normalized
- R18 method_caveat backticks instead of escaped quotes
Test + supply chain (5)
- R21 crossval exit-code belt-and-suspenders
- R21 close() helper retention rationale
- R20 npm tarball excludes attestations/*.json
- R20 SECURITY.md forked-PR isolation note
- R8 + R12 DAUBERT.md known-limitations expansion
Test state
| Metric | v2.9.22 | v2.9.23 |
|---|---|---|
| Unit tests | 1056/0 | 1056/0 |
| Crossval fixtures | 43/0 | 43/0 |
| Crossval checks | 444/444 | 444/444 |
Audit ledger
~85 cumulative findings closed across v2.9.13–v2.9.23. ~25-35 still open (Python parity backports, hammock FS hard-precedence, MCP-side items, perf). ~7 deferred to v3.0 (architectural).
v2.9.22 — Audit HIGH wave (10 items closed)
v2.9.22 — Audit HIGH wave
Ten specific HIGH-priority findings from the 20-agent audit closed by direct file:line cross-reference.
Engine correctness (6)
- Relationship endpoint whitespace trim (no more silent DANGLING on
' A ') _strictParseFloatrejects'5abc'partial-parse poison- Typed
INVALID_INPUTon non-arrayactivities/relationships getHolidaysclamps cascade escapees outside requested year window- Date-coerce alert no longer false-positives
'2020-01-01' actual_start=epochcollision documented (v3.0 fix)
Daubert disclosure (3)
provenance.engine_sha256+python_reference_sha256(caller-supplied)prong_2_peer_review.answer = "Yes"(binary, matches other prongs)manifest.tia_modeswitches MIP 3.6 / 3.7 + retrospective SCL §4 caveat
Bayesian docs (2)
- Lognormal
muconvention documented (treatsduration_daysas MEDIAN) prior_strengthis NOT a Bayesian pseudocount — docstring corrected
Test infrastructure
- New
tests/no-truncation.test.jsregression guard tests/no-fabricated-citations.test.jsnow scanspython_reference/
Test state
| Metric | v2.9.21 | v2.9.22 |
|---|---|---|
| Unit tests | 1037 / 0 | 1056 / 0 |
| Crossval fixtures | 43 / 0 | 43 / 0 |
| Crossval checks | 444 / 444 | 444 / 444 |
Audit ledger status (honest)
- ~50 engineering items still open (Python parity backports, perf, hammock FS hard-precedence, doc updates)
- ~6 deferred to v3.0 (Section D cal-aware, Welford variance, lognormal exact-quantile CIs, sub-day precision, hammock/LOE crossval, epoch move)
This release is honest progress, not a closeout. See CHANGELOG for the per-finding cross-reference.
v2.9.21 — Real audit cross-reference (13 findings closed)
v2.9.21 — Real audit cross-reference
The v2.9.20 release was framed as "218/218 audit ledger closed". That framing was wrong (see v2.9.20 release-notes correction). v2.9.21 closes specific verifiable findings from the 20-agent audit by cross-referencing each finding's file:line citation against current code state — no fabricated audit-closure language this time.
Findings closed (13)
Daubert evidence-prose (court-exhibit-critical):
- Prong 1 — added Sigstore + Rekor + GitHub Actions +
npm run verifyreferences; fixture count refreshed 40×416 → 43×444. - Prong 2 — added FRE 702 (Dec 1, 2023 amendment) leading clause tying to Rule 702(c)/(d).
- Prong 3 — separated computational vs epistemic error rate.
XSS surface:
esc()and_svgEsc()now escape'and/(defense-in-depth on activity names rendered into HTML attributes).
Real correctness:
REMAINING_EXCEEDS_DURATIONWARN when RD > OD.- Salvage cycle ordering deterministic across relationship-input shuffling (Daubert reproducibility).
- Bayesian
>= 0for analyst-supplied zero;INVALID_PRIORthrow on Dirac priors;_normalQuantiledocstring corrected to Acklam (2003).
Polish:
- Em-dash (U+2014) → ASCII hyphen in 3 alert messages (
result.alertsflows into Daubert disclosure JSON). hammock_unsupported_rel_countfossil documented as v3.0 removal candidate.- AACE 10S-90 free-float citation replaced with AACE 29R-03 §4 + Wickwire (3rd ed., 2010).
Test state
| Metric | v2.9.20 | v2.9.21 |
|---|---|---|
| Unit tests | 1018 / 0 | 1037 / 0 (+19 assertions) |
| Crossval fixtures | 43 / 0 | 43 / 0 |
| Crossval checks | 444 / 444 | 444 / 444 |
Audit ledger status (honest)
- Closed before v2.9.21: ~15 (v2.9.20 calendar + hash + input-validation work)
- Closed in v2.9.21: ~13 (this release)
- Stale findings (already addressed pre-audit-cross-ref): ~5
- Still open: ~65 (hammock FS hard-precedence, perf, Python parity backports, doc updates)
- Deferred to v3.0 (architectural): ~6
The audit ledger is NOT closed. v2.9.21 closes 13 specific items by file:line cross-reference; ~65 remain on the engineering backlog.
v2.9.20 — 218-audit MED+LOW closeout
v2.9.20 — MED + LOW polish wave
Engine maintenance release. The "audit" framing in the prior release notes overstated what this version closed — those notes have been corrected.
What actually shipped
- Daubert disclosure 1.0 → 1.1 — additive provenance fields (
commit_sha,repository_url,release_tag,release_url,verification_command,attestation_url, structuredtest_count). Existing 1.0 consumers unaffected. - Numeric robustness —
parseFloat()||0swept forNumber.isFinite()everywhere ±Infinity could leak (salvager cycle-break, MFP predMap, Bayesian actuals, XER hours-per-day, addWorkDays/subtractWorkDays). - Bayesian module — negative actuals rejected with WARN; Infinity prior_strength rejected; small-denominator percentage guards on prior_vs_posterior_shift;
result.alerts[]channel added. - Security caps — module-level DOS caps (100k activities / 500k relationships) enforced at every public entry point; prototype-pollution hardening on caller-supplied
wbs_groups; iteration-bound caps on salvager and MFP. - Brand polish — Daubert HTML body font swapped Georgia → Inter (system fallback, no CDN); single source for brand colors.
- Public-API edge-case coverage — regression tests for degenerate inputs to
computeCPMWithStrategies,computeTIA,computeBayesianUpdate,buildDaubertDisclosure,computeTopologyHash,renderDaubertMarkdown. - Engine math edge cases — targeted regression tests across the forward/backward pass, constraints, calendar fallback, hammocks, MS_Finish, calendar inheritance, TIA shape, linear-chain CP, JSON round-trip.
Test state
| Metric | v2.9.19 | v2.9.20 |
|---|---|---|
| Unit tests | 913 / 0 | 1018 / 0 (+105 regression assertions) |
| Crossval fixtures | 43 / 0 | 43 / 0 |
| Crossval checks | 444 / 444 | 444 / 444 |
Deferred
Several items remain unaddressed and are architectural rather than polish:
- Section D calendar-awareness (runCPM is ordinal-only)
- Welford's online algorithm for Bayesian group variance
- Lognormal / Beta exact-quantile CIs (currently Normal-symmetric with
max(0, ci_low)clamp) - Python
compute_cpmparity backports (F4 LPM, F6 iterative hammock walker) - Sub-day lag precision (engine is day-granular)
- Full hammock + LOE crossval parity (Python reference doesn't implement those activity types)
See CHANGELOG.md for the per-batch commit detail.
v2.9.19 — 9 HIGH-priority sweep
Sequential pass closes 9 long-tail HIGH findings prior fix-wave agents skipped.
Engine:
- A3-HIGH:
opts.projectFinishparameter (P6 'Must Finish By') - A4-HIGH: shadow-driver records MAX-drive pred (not FIRST)
- A6-HIGH: NL nearest-Monday observance (St. Patrick's, St. George's, Discovery, Orangemen's)
- A8-HIGH: lag conversion uses successor
calendar.day_hr_cnt(was hardcoded /8) - A11-HIGH ×3: FF/SF slack cal-aware, Section D ordinal-only ALERT, hammock resolver covered
Supply chain:
- A20-HIGH: GH Actions pinned to SHA (tag-hijack vector eliminated; dependabot wired for weekly bumps)
- A20-HIGH: package-lock.json regenerated (was 6 versions and one rename behind)
Tests: 913 / 0 unit, 43 / 0 crossval, 444 / 444 checks. +16 new regression assertions across the 9 items.
v2.9.18 — Honest audit re-verification
Systematic verification of every CRITICAL claim in CHANGELOG against the actual code. Prior fix-wave agents had marked items as 'fixed' or 'deferred for principle' — turned out 7 were either still broken or never tested. This release closes all 7.
Real engine bugs:
- A8-CRIT-1: Hammock walker FS pred-chain used upstream H.ES instead of H.EF + walker MIN'd FS/SS together (FS-precedence requires MAX). Walker AND 3 hammock unit tests updated.
- A16-CRIT-3: dateToNum silently returned 0 for invalid dates — now emits invalid-date-coerced ALERT.
- A10-HIGH: parseInt accepted trailing garbage ('2026.5' → 2026) — now strict regex.
- A17-CRIT-4: progress_override mode silently ignored — now emits ALERT.
Missing tests added (CRITICAL findings audit said were never tested):
- T-FIX-A17-1: SO constraint (4 assertions; was never tested).
- T-FIX-A17-2: MFO constraint (2 assertions; was never tested).
- T-FIX-A17-3: DUPLICATE_ACTIVITY_CODE for computeCPM path (3 assertions).
Test state: 897 / 0 unit. 43 / 0 crossval fixtures. 444 / 444 checks.