Skip to content

Releases: danafitkowski/cpp-cpm-engine

v2.9.27 — Audit closeout (13 items); crossval 444→747

18 May 14:39

Choose a tag to compare

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_days MonFri fast path (~250× speedup at 30d walks)

Python parity backports

  • R9 tf_working_days + _count_work_days_between helper
  • 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_count vs hashed_relationship_count, algorithm: null for empty

Engine MED/HIGH

  • R10 Python _cal_for honors project_calendar fallback (was JS-only)
  • R6 MS_Start/SO constraint-widens-lf WARN (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:

  1. Section D full calendar-awareness (fold Section C into runCPM)
  2. Welford's online variance for Bayesian
  3. Lognormal/Beta exact-quantile inverse-CDF CIs
  4. Sub-day lag precision (engine-wide ripple)
  5. Python TT_Hammock + TT_LOE implementation
  6. Engine epoch move (fixes R12 epoch collision)
  7. 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

18 May 11:38

Choose a tag to compare

v2.9.26 — Provenance sidecars + citation polish

3 audit items closed.

Provenance

  • R20 LOWnpm run attest writes cpm-engine.js.sha256 and python_reference/cpm.py.sha256 sidecar files for mechanical shasum -c verification

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

18 May 11:33

Choose a tag to compare

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 _isCleanMonFri uses bitmask not Set alloc (~200k fewer throw-away Sets per CPM run)
  • R21 Section D constraint helpers hoist projectStart parse (~300k fewer redundant Date constructions)

Python parity (1 partial)

  • R21 Python add_work_days caches 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_override schedule 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)

18 May 11:26

Choose a tag to compare

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)

18 May 11:19

Choose a tag to compare

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_factor configurable (default 0.5)
  • R22 opts.computed_at override for byte-identical determinism

Holiday rules (1)

  • R11 CA-AB / CA-SK Family Day effective_from year guards

Daubert / brand polish (4)

  • R17 README MIP claims rescoped to "math primitives"
  • R17 docs/citations.md MIP 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)

18 May 10:55

Choose a tag to compare

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 ')
  • _strictParseFloat rejects '5abc' partial-parse poison
  • Typed INVALID_INPUT on non-array activities/relationships
  • getHolidays clamps cascade escapees outside requested year window
  • Date-coerce alert no longer false-positives '2020-01-01'
  • actual_start=epoch collision 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_mode switches MIP 3.6 / 3.7 + retrospective SCL §4 caveat

Bayesian docs (2)

  • Lognormal mu convention documented (treats duration_days as MEDIAN)
  • prior_strength is NOT a Bayesian pseudocount — docstring corrected

Test infrastructure

  • New tests/no-truncation.test.js regression guard
  • tests/no-fabricated-citations.test.js now scans python_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)

18 May 10:34

Choose a tag to compare

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 verify references; 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_DURATION WARN when RD > OD.
  • Salvage cycle ordering deterministic across relationship-input shuffling (Daubert reproducibility).
  • Bayesian >= 0 for analyst-supplied zero; INVALID_PRIOR throw on Dirac priors; _normalQuantile docstring corrected to Acklam (2003).

Polish:

  • Em-dash (U+2014) → ASCII hyphen in 3 alert messages (result.alerts flows into Daubert disclosure JSON).
  • hammock_unsupported_rel_count fossil 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

17 May 12:49

Choose a tag to compare

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, structured test_count). Existing 1.0 consumers unaffected.
  • Numeric robustnessparseFloat()||0 swept for Number.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_cpm parity 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

17 May 11:40

Choose a tag to compare

Sequential pass closes 9 long-tail HIGH findings prior fix-wave agents skipped.

Engine:

  • A3-HIGH: opts.projectFinish parameter (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

17 May 11:24

Choose a tag to compare

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.