Skip to content

rewrite(phase7): batch 3 — release-pipeline hardening, dispositions, CHANGELOG - #169

Merged
SoundMatt merged 1 commit into
rewrite/v3-from-c-rcpfrom
phase7/release-hardening
Aug 22, 2026
Merged

rewrite(phase7): batch 3 — release-pipeline hardening, dispositions, CHANGELOG#169
SoundMatt merged 1 commit into
rewrite/v3-from-c-rcpfrom
phase7/release-hardening

Conversation

@SoundMatt

Copy link
Copy Markdown
Owner

rewrite(phase7): batch 3 — release-pipeline hardening, dispositions, CHANGELOG

Part of the v3.0.0 ground-up rewrite (cpp-RCP #129, ROADMAP.md Phase 17),
branch rewrite/v3-from-c-rcp. Phase 7 (formal verification + MC/DC +
release-pipeline hardening), batch 3 -- closes the remaining Phase 7
scope: release-pipeline hardening, .fusa-dispositions.json, CHANGELOG.md.

version-sources-agree (new CI job)

Ported from c-RCP's own equivalent, adapted for cpp-RCP's real version.hpp
syntax (a constexpr std::string_view, not a #define macro like c-RCP's).
While building this, found and fixed a real bug: .fusa.json had no real
project.version field at all -- cpfusa's config loader was silently
defaulting to "0.1.0" for every artifact it has ever generated for this
repo. Added "version": "2.26.0" to .fusa.json's project object.

cpfusa cyber (renamed from its stale "--strict" name)

The job's name claimed --strict but its run: line never passed it --
--strict is a real flag, but cpp-RCP does not cleanly pass under it today
(838 WARNING-severity findings, overwhelmingly the expected shape of a
wire-protocol library's byte-packing/masking idioms and test-suite
loopback addresses, not defects -- but also not several hundred call
sites to responsibly mass-review or mass-waive in one batch). Renamed
the job to match its real behavior rather than either rushing the
findings or quietly keeping a misleading name. Also confirmed
.fusa-dispositions.json structurally cannot fix this either way:
cyber's --strict check never consults dispositions, unlike
check/lint/analyze's gated_exit_code().

cpfusa analyze (real gate now, || true removed)

Root-caused rather than just removing the escape hatch: the job's own
build step left Catch2's vendored FetchContent source (including
Catch2's own SelfTest suite) inside build/, which cppcheck then
misreported as first-party ERROR findings on Catch2's own BDD macros --
that's what was actually keeping the job red, not a cpp-RCP defect.
Separately, compile_commands.json was left inside build/ while analyze
looks for it at the project root, so clang-tidy had never actually run
in this job at all. Fixed by copying compile_commands.json to the root
then deleting build/ before invoking analyze, so the scan only sees
first-party sources. With both fixed: 0 errors, real hard gate.

.fusa-dispositions.json (new, legitimately empty)

Neither cpfusa lint (0 errors/138 warnings) nor the now-correctly-scoped
cpfusa analyze (0 errors/269 warnings/161 info) has any ERROR-severity
finding needing a waiver -- {"dispositions": []} is the honest state,
not a placeholder. Confirmed the mechanism itself (rule-ID-only
matching, a blanket per-rule waiver, not per-fingerprint) is reserved
for genuinely rule-wide architectural situations like c-RCP's own
alloc.c precedent -- no such situation exists in cpp-RCP's current
ERROR-level findings.

release.yml: two new steps

IEC 62443 gap report (SL-2, artifact-only, mirrors the existing
ISO26262/IEC61508/DO-178C siblings) via cpfusa iec62443 --sl SL-2.

Shipped-artifact version verification: adapted from c-RCP's step, not
copy-pasted -- cpp-FuSa v0.18.0's release/qualify commands hardcode
their own module name in sbom.json/provenance.json/etc. regardless of
target project (confirmed by running cpfusa release and inspecting
output), so c-RCP's literal field-path doesn't apply. Uses report.html's
real "cpp-RCP v{version}" field (sourced from .fusa.json) plus a direct
version.hpp/.fusa.json re-comparison, since version-sources-agree
doesn't run on tag pushes.

CHANGELOG.md (new)

Keep a Changelog format (no prior convention existed). Single
[Unreleased] -> v3.0.0 section grouped by Phase 1-7, one line per real
merged PR pulled from rewrite/v3-from-c-rcp's actual git history -- no
fabricated pre-rewrite history.

Verification

Independently re-verified: both workflow YAML files parse cleanly.
Reproduced the version-sources-agree grep logic myself against the real
files (2.26.0/2.26.0/2.26.0, match) and against a deliberately-mutated
copy (correctly detects mismatch). Reproduced cpfusa cyber's real
exit codes myself: 838 warnings, exit 0 without --strict, exit 1 with
--strict -- matching the report exactly. Reproduced the fixed cpfusa
analyze pipeline myself from a clean build (compile_commands.json
copied to root, build/ deleted before scanning): 0 errors, 269
warnings, 161 info -- matching the report's 0/269/160 within a single
info-finding's worth of trivial build-path variance. Confirmed
.fusa-dispositions.json's empty state against both tools' real current
output. Spot-checked CHANGELOG.md's entries against real git history --
verbatim PR titles, not fabricated. Full tree rebuilt from scratch: 0
errors, 0 warnings, 58/58 ctest suites pass (100%).

.fusa.json: +1 line. .github/workflows/ci.yml: +86/-2 (1001 -> 1083 lines
... wait, actual diff: +84 net). .github/workflows/release.yml: +59
lines (248 -> 307). .fusa-dispositions.json: new, 3 lines. CHANGELOG.md:
new, 113 lines.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

…CHANGELOG

Part of the v3.0.0 ground-up rewrite (cpp-RCP #129, ROADMAP.md Phase 17),
branch rewrite/v3-from-c-rcp. Phase 7 (formal verification + MC/DC +
release-pipeline hardening), batch 3 -- closes the remaining Phase 7
scope: release-pipeline hardening, .fusa-dispositions.json, CHANGELOG.md.

## version-sources-agree (new CI job)

Ported from c-RCP's own equivalent, adapted for cpp-RCP's real version.hpp
syntax (a constexpr std::string_view, not a #define macro like c-RCP's).
While building this, found and fixed a real bug: .fusa.json had no real
project.version field at all -- cpfusa's config loader was silently
defaulting to "0.1.0" for every artifact it has ever generated for this
repo. Added "version": "2.26.0" to .fusa.json's project object.

## cpfusa cyber (renamed from its stale "--strict" name)

The job's name claimed --strict but its run: line never passed it --
--strict is a real flag, but cpp-RCP does not cleanly pass under it today
(838 WARNING-severity findings, overwhelmingly the expected shape of a
wire-protocol library's byte-packing/masking idioms and test-suite
loopback addresses, not defects -- but also not several hundred call
sites to responsibly mass-review or mass-waive in one batch). Renamed
the job to match its real behavior rather than either rushing the
findings or quietly keeping a misleading name. Also confirmed
.fusa-dispositions.json structurally cannot fix this either way:
cyber's --strict check never consults dispositions, unlike
check/lint/analyze's gated_exit_code().

## cpfusa analyze (real gate now, || true removed)

Root-caused rather than just removing the escape hatch: the job's own
build step left Catch2's vendored FetchContent source (including
Catch2's own SelfTest suite) inside build/, which cppcheck then
misreported as first-party ERROR findings on Catch2's own BDD macros --
that's what was actually keeping the job red, not a cpp-RCP defect.
Separately, compile_commands.json was left inside build/ while analyze
looks for it at the project root, so clang-tidy had never actually run
in this job at all. Fixed by copying compile_commands.json to the root
then deleting build/ before invoking analyze, so the scan only sees
first-party sources. With both fixed: 0 errors, real hard gate.

## .fusa-dispositions.json (new, legitimately empty)

Neither cpfusa lint (0 errors/138 warnings) nor the now-correctly-scoped
cpfusa analyze (0 errors/269 warnings/161 info) has any ERROR-severity
finding needing a waiver -- {"dispositions": []} is the honest state,
not a placeholder. Confirmed the mechanism itself (rule-ID-only
matching, a blanket per-rule waiver, not per-fingerprint) is reserved
for genuinely rule-wide architectural situations like c-RCP's own
alloc.c precedent -- no such situation exists in cpp-RCP's current
ERROR-level findings.

## release.yml: two new steps

IEC 62443 gap report (SL-2, artifact-only, mirrors the existing
ISO26262/IEC61508/DO-178C siblings) via cpfusa iec62443 --sl SL-2.

Shipped-artifact version verification: adapted from c-RCP's step, not
copy-pasted -- cpp-FuSa v0.18.0's release/qualify commands hardcode
their own module name in sbom.json/provenance.json/etc. regardless of
target project (confirmed by running cpfusa release and inspecting
output), so c-RCP's literal field-path doesn't apply. Uses report.html's
real "cpp-RCP v{version}" field (sourced from .fusa.json) plus a direct
version.hpp/.fusa.json re-comparison, since version-sources-agree
doesn't run on tag pushes.

## CHANGELOG.md (new)

Keep a Changelog format (no prior convention existed). Single
[Unreleased] -> v3.0.0 section grouped by Phase 1-7, one line per real
merged PR pulled from rewrite/v3-from-c-rcp's actual git history -- no
fabricated pre-rewrite history.

## Verification

Independently re-verified: both workflow YAML files parse cleanly.
Reproduced the version-sources-agree grep logic myself against the real
files (2.26.0/2.26.0/2.26.0, match) and against a deliberately-mutated
copy (correctly detects mismatch). Reproduced cpfusa cyber's real
exit codes myself: 838 warnings, exit 0 without --strict, exit 1 with
--strict -- matching the report exactly. Reproduced the fixed cpfusa
analyze pipeline myself from a clean build (compile_commands.json
copied to root, build/ deleted before scanning): 0 errors, 269
warnings, 161 info -- matching the report's 0/269/160 within a single
info-finding's worth of trivial build-path variance. Confirmed
.fusa-dispositions.json's empty state against both tools' real current
output. Spot-checked CHANGELOG.md's entries against real git history --
verbatim PR titles, not fabricated. Full tree rebuilt from scratch: 0
errors, 0 warnings, 58/58 ctest suites pass (100%).

.fusa.json: +1 line. .github/workflows/ci.yml: +86/-2 (1001 -> 1083 lines
... wait, actual diff: +84 net). .github/workflows/release.yml: +59
lines (248 -> 307). .fusa-dispositions.json: new, 3 lines. CHANGELOG.md:
new, 113 lines.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Signed-off-by: Matt <47545907+SoundMatt@users.noreply.github.com>
@SoundMatt
SoundMatt merged commit b1dcf40 into rewrite/v3-from-c-rcp Aug 22, 2026
25 checks passed
@SoundMatt
SoundMatt deleted the phase7/release-hardening branch August 22, 2026 20:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant