# C++ Object-Oriented Modular Refactoring Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use > `superpowers:subagent-driven-development` (recommended) or > `superpowers:executing-plans` to implement this plan task-by-task. Steps use > checkbox (`- [ ]`) syntax for tracking. > > In FESA, those task-by-task semantics are mediated by the project Harness. Do not > invoke an implementation skill or select a Step directly; a separate user request > must start `scripts/execute.py`, which selects exactly one pending Step. **Goal:** Preserve the current B33, MITC4, and linear-static numerical and external contracts while converting the FESA C++ production code to explicit object-oriented boundaries, focused modules, shared utilities, Google C++ style, and production-only Doxygen documentation. **Architecture:** Domain owns immutable polymorphic semantic definitions through `std::unique_ptr` and stable `EntityIndex` positions. `ElementDefinition` remains separate from runtime numerical `Element`, and load, boundary-condition, analysis, material, and property abstractions each have independent hierarchies. Existing deterministic assembly, result identity, HDF5 schema, and reference comparison contracts remain unchanged. **Tech Stack:** C++17, MSVC x64 Debug, CMake, CTest, GoogleTest, Intel oneMKL, Intel oneTBB, HDF5, clang-format, clang-tidy, and optional Doxygen configuration. ## Global Constraints - Follow `/docs/CODINGSTYLE.md` and the official Google C++ Style Guide baseline. - Use PascalCase for every C++ function and accessor; use `.h` production headers with full-path include guards; retain `.cpp` as the FESA source-file exception. - Add Doxygen comments only to production code. Do not add Doxygen coverage to tests. - Keep C++17 and MSVC x64 Debug compatibility and add no compiler warnings under `/W4 /WX`. - Preserve the approved B33 and MITC4 formulations, signs, units, coordinate systems, reduction order, result row identity, HDF5 schema, tolerances, and reference files. - Do not implement MITC3, solid elements, dynamics, eigenvalue analysis, response spectrum, random vibration, density, plasticity, anisotropy, distributed load, body force, or MPC behavior. - Do not expose MKL, TBB, HDF5, Win32, or vendor integer types from public solver-core headers. - Every C++ production change requires a related C++ test and an in-Step `RED -> observed failure -> minimal GREEN -> focused/full VERIFY` cycle. - Do not run `scripts/execute.py` until the user gives a separate explicit execution request. - Doxygen comments and `Doxyfile` configuration are in scope; generated Doxygen output is deferred and is not a blocking command for this phase. --- ## 1. Metadata | Field | Value | | --- | --- | | `feature_id` | `cpp-object-oriented-modular-refactoring` | | `source_requirement` | `/docs/superpowers/specs/2026-08-16-cpp-object-oriented-modular-refactoring-design.md` | | `source_research` | Existing repository duplication and ownership audit captured by the approved design; no new FEM research is required | | `source_formulation` | `/docs/linear-static-3d-euler-beam/formulation.md`; `/docs/linear-static-mitc4-shell/formulation.md` | | `source_numerical_review` | `/docs/linear-static-3d-euler-beam/numerical-review.md`; `/docs/linear-static-mitc4-shell/numerical-review.md` | | `source_io_definition` | `/docs/linear-static-3d-euler-beam/io.md`; `/docs/linear-static-mitc4-shell/io.md` | | `source_reference_models` | `/docs/linear-static-3d-euler-beam/reference-model.md`; `/docs/linear-static-mitc4-shell/reference-model.md` | | `status` | `ready-for-implementation` | | `owner_agent` | `implementation-planning-agent` | | `date` | `2026-08-16` | ## 2. Readiness Check - The written refactoring design and the 25-Step draft were explicitly approved on 2026-08-16. - B33 and MITC4 requirements, formulations, numerical reviews, I/O projections, and reference contracts already exist and remain upstream read-only inputs. - Required reference inputs and CSVs are present under `/reference/cantilever beam/` and `/reference/shell/`. - `clang-format.exe` and `clang-tidy.exe` are present at `C:/Program Files/LLVM/bin/`; the current long-lived process PATH need not contain that directory because the plan uses the absolute paths. - Doxygen generation is intentionally deferred by user decision. The implementation still adds production comments and a warning-strict `Doxyfile` for later use. - No missing formulation, tolerance, HDF5 projection, or artifact decision prevents implementation planning. ## 3. Implementation Scope ### Included - Repository policy/tooling and Implementation Agent enforcement. - Mechanical `.hpp` to `.h`, header guard, PascalCase, formatting, and production Doxygen conversion in reviewable module slices. - Shared `Vector3`, dense-BLAS internal adapter, ASCII utilities, `SourceTargetResolver`, and owner-based DOF invariant validation. - Independent abstract boundaries for material, element property, semantic element definition, runtime element, load, boundary condition, and analysis. - Current concrete B33, MITC4, isotropic linear elasticity, beam/shell property, concentrated nodal load, prescribed displacement, and linear-static behavior. - Responsibility-based splits of domain mapping, result recovery, and HDF5 writing. - Full MSVC/CTest and existing B33/MITC4 external reference verification. ### Excluded and non-goals - New physics, input keywords, output datasets, tolerances, reference artifacts, or runtime performance optimization. - A common root base shared by unrelated element, load, material, and analysis types. - A giant material interface containing density, plasticity, and anisotropy options. - Registry/plugin frameworks, global static registration, speculative `Clone()`, or unnecessary shared ownership. ## 4. Refactoring Requirements | ID | Requirement | | --- | --- | | `R-PRESERVE-001` | Current B33/MITC4/linear-static numerical and external results shall remain unchanged within their approved contracts. | | `R-STYLE-001` | Production and test C++ shall use approved Google-style naming and formatting; production headers shall use `.h` and header guards. | | `R-DOC-001` | Production functions and classes shall carry useful Doxygen contracts; tests shall not require Doxygen comments. | | `R-DUP-001` | Repeated fixed-size 3D vector operations shall be implemented once by `Vector3`. | | `R-DUP-002` | Repeated dense-BLAS conversion/copy, ASCII/source resolution, and DOF invariant logic shall have one owner. | | `R-MODEL-001` | Material, element-property, and element-definition semantic objects shall have independent abstractions and Domain-owned stable lifetime. | | `R-ELEMENT-001` | Semantic `ElementDefinition` and runtime numerical `Element` shall remain separate and be connected by a fail-closed factory. | | `R-PIPELINE-001` | DofManager, SparseAssembler, and ResultRecovery shall consume runtime `Element` interfaces without scattered B33/MITC4 type branches. | | `R-LOAD-001` | A `Load` shall emit ordered contributions and only `LoadAssembler` shall accumulate the global vector. | | `R-BC-001` | A `BoundaryCondition` shall emit definitions and an essential-constraint policy shall enforce prescribed displacement. | | `R-ANALYSIS-001` | `Analysis` shall expose only `Run()` and `LinearStaticAnalysis` shall own its approved lifecycle. | | `R-MODULE-001` | Domain mapping, recovery, and HDF5 writing shall be split by their approved responsibilities. | | `R-AGENT-001` | Implementation Agent shall read `/docs/CODINGSTYLE.md` as a mandatory global input. | | `R-SCOPE-001` | No excluded future feature or runtime-performance change shall be introduced. | ## 5. Work Breakdown | Task | Name | Depends on | Deliverable | | --- | --- | --- | --- | | `T00` | coding-style-agent-contract | none | Agent profile and Python contract enforce `CODINGSTYLE.md`. | | `T01` | cpp-style-tooling | `T00` | clang-format/tidy configuration and deferred Doxygen configuration. | | `T02` | architecture-boundaries | `T00` | Architecture and ADR record the approved responsibility graph. | | `T03` | foundation-google-style | `T01` | Core/math/linear-solver APIs use the approved style. | | `T04` | model-element-google-style | `T03` | Model and current element APIs use the approved style. | | `T05` | solver-workflow-google-style | `T04` | FEM/assembly/constraint/analysis/result APIs use the approved style. | | `T06` | io-application-google-style | `T05` | I/O, application, and test helper APIs use the approved style. | | `T07` | vector3-value-type | `T03` | Tested fixed-size vector value type. | | `T08` | element-geometry-vector3 | `T04`, `T07` | Element/model geometry duplicate helpers removed. | | `T09` | result-io-vector3 | `T06`, `T08` | Result/I/O vector duplicate helpers removed. | | `T10` | dense-blas-adapter | `T03` | Matrix/Vector share private MKL conversion and copy helpers. | | `T11` | source-target-resolver | `T06` | Shared ASCII and source-target resolution module. | | `T12` | material-property-hierarchy | `T04` | Independent semantic material and property abstractions. | | `T13` | element-definition-domain | `T11`, `T12` | Domain-owned polymorphic semantic element definitions. | | `T14` | runtime-element-factory | `T08`, `T13` | Runtime element abstraction and fail-closed factory. | | `T15` | generic-dof-manager | `T14` | DofManager consumes element DOF layouts and owns invariant checks. | | `T16` | generic-sparse-assembler | `T15` | SparseAssembler consumes element stiffness contributions. | | `T17` | generic-result-recovery | `T16` | ResultRecovery consumes element result bundles. | | `T18` | load-hierarchy | `T11`, `T15` | Ordered load contribution hierarchy. | | `T19` | boundary-condition-policy | `T15` | Constraint definition hierarchy and essential policy. | | `T20` | analysis-hierarchy | `T17`, `T18`, `T19` | Minimal Analysis base and unchanged linear-static lifecycle. | | `T21` | domain-mapper-modules | `T11`, `T13`, `T18`, `T19` | Mapper split by semantic responsibility. | | `T22` | result-recovery-modules | `T17` | Recovery split into global, beam, shell, and commit responsibilities. | | `T23` | hdf5-writer-modules | `T17`, `T22` | HDF5 writer split without schema changes. | | `T24` | final-quality-reference-gate | all prior tasks | Full style, build/test, HDF5, determinism, and reference evidence. | Each task maps one-to-one to `/phases/cpp-object-oriented-modular-refactoring/stepN.md`. ## 6. TDD Test Plan | Test ID | First failing evidence | GREEN evidence | | --- | --- | --- | | `P-AGENT-001` | Python contract reports missing mandatory `CODINGSTYLE.md` input. | Agent workflow contract passes. | | `P-STYLE-001` | Policy test reports missing or incorrect clang/Doxygen configuration. | Policy and full Harness Python tests pass. | | `C-STYLE-001..004` | Test includes/calls use `.h` and PascalCase before production conversion, causing a compile failure. | Focused module suites and full CTest pass. | | `C-VEC3-001` | `vector3_test.cpp` cannot compile because `Vector3` is absent. | Arithmetic, finite, and normalization-boundary tests pass. | | `C-DUP-001..004` | Tests reference the new shared seam before it exists. | Shared seam passes and old duplicate helper definitions are absent by `rg` checks. | | `C-MODEL-001..002` | Polymorphic ownership and const stable-index tests fail before semantic bases exist. | Material/property/definition tests and Domain mapping tests pass. | | `C-ELEMENT-001` | Base-interface creation and incompatibility tests fail before `ElementFactory`. | B33/MITC4 creation, rejection, stiffness, and recovery tests pass. | | `C-DOF-001` | Fake runtime element layout is not accepted by DofManager. | Stable scatter/pattern and invariant tests pass. | | `C-ASSEMBLY-001` | Fake runtime contribution is not assembled. | Serial/TBB/repeated CSR outputs remain byte-identical. | | `C-RECOVERY-001` | Fake result bundle cannot flow through recovery. | Beam/shell identities, signs, energy, and atomic rollback pass. | | `C-LOAD-001` | A fake Load cannot emit ordered full-DOF contributions. | Source-order accumulation and current load validation pass. | | `C-BC-001` | A fake BoundaryCondition cannot resolve constraint definitions. | Nonzero prescribed displacement and reconstruction pass. | | `C-ANALYSIS-001` | LinearStaticAnalysis cannot be invoked through `Analysis`. | Approved factorization/load/solve/recovery lifecycle passes. | | `C-MODULE-001..003` | Tests reference extracted mapper/recovery/HDF5 responsibilities before their seams exist. | Existing public behavior and atomicity suites pass after extraction. | | `C-REF-B33-001` | No new intentional failure; final gate reuses the approved external comparison. | B33 comparison passes under its existing component-scale tolerance. | | `C-REF-MITC4-001` | No new intentional failure; final gate reuses the approved external comparison. | MITC4 translations pass at fixed `1.0e-5`; rotations remain warning-only. | RED and GREEN evidence, command, exit code, duration, output tail, and failed test names must be recorded during execution in the Implementation-owned reports. A final reference gate does not manufacture an artificial RED because it verifies an unchanged approved external contract after all refactoring tasks. ## 7. CMake/CTest Plan - Keep the existing `fesa_solver`, `fesa_cli`, `fesa_unit_tests`, `fesa_integration_tests`, `fesa_reference_tests`, and `fesa_tests` targets. - Register new production/test files in `/src/fesa/CMakeLists.txt` and `/tests/CMakeLists.txt` in their owning task. - Do not create a new test executable or change existing test labels. - `.harness/config.json` is absent, so use `.harness/build`, MSVC x64, Debug, and the explicit local dependency paths recorded in each Step. - Every C++ task runs a focused CTest regular expression and the full CTest discovery and execution sequence. - Step `T24` performs a fresh configure and the final B33/MITC4 reference tests. ## 8. Candidate Files and Ownership | Responsibility | Candidate files | | --- | --- | | Policy/tooling | `.codex/agents/implementation-agent.toml`, `.clang-format`, `.clang-tidy`, `Doxyfile`, `tests/test_agent_skill_workflow_contract.py`, `tests/test_cpp_policy_contract.py` | | Fixed/dynamic math | `include/fesa/math/vector3.h`, `include/fesa/math/vector.h`, `include/fesa/math/matrix.h`, `src/fesa/math/dense_blas_internal.h`, matching `.cpp` and unit tests | | Semantic material/property | `include/fesa/materials/*.h`, `include/fesa/properties/*.h`, `src/fesa/materials/*.cpp`, `src/fesa/properties/*.cpp`, matching unit tests | | Semantic element definitions | `include/fesa/elements/element_definition.h`, concrete definition headers, `include/fesa/model/domain.h`, `src/fesa/model/domain.cpp` | | Runtime elements | `include/fesa/elements/element.h`, `element_factory.h`, existing B33/MITC4 kernels and new factory implementation/tests | | Source resolution | `include/fesa/model/source_target_resolver.h`, `src/fesa/model/source_target_resolver.cpp`, focused tests | | Solver consumers | DofManager, SparseAssembler, ResultRecovery headers/sources/tests | | Loads | `include/fesa/loads/load.h`, `concentrated_nodal_load.h`, sources, LoadAssembler and tests | | Constraints | `boundary_condition.h`, `prescribed_displacement.h`, `essential_constraint_policy.h`, sources and tests | | Analysis | `analysis.h`, `linear_static_analysis.h`, sources and integration tests | | Mapper split | focused private mapper modules under `src/fesa/io/abaqus/` with one public `domain_mapper.h` facade | | Recovery split | focused modules under `src/fesa/results/` with one public `result_recovery.h` facade | | HDF5 split | private modules under `src/fesa/io/hdf5/` with one public `hdf5_results_writer.h` facade | These are implementation candidates, not permission to introduce extra public API. Each Step must choose the minimum files consistent with the approved boundaries. ## 9. Candidate Interface Contracts The implementation may refine parameter carrier names while preserving these semantic contracts: ```cpp struct AnalysisRequest { std::filesystem::path input_path; std::filesystem::path output_path; }; class Analysis { public: virtual ~Analysis() = default; virtual Status Run(const AnalysisRequest& request) = 0; }; class ElementDefinition { public: virtual ~ElementDefinition() = default; virtual ElementDefinitionKind Kind() const noexcept = 0; virtual const SourceEntityId& SourceId() const noexcept = 0; virtual const std::vector& NodeIndices() const noexcept = 0; virtual EntityIndex PropertyIndex() const noexcept = 0; }; class Element { public: virtual ~Element() = default; virtual const ElementDofLayout& DofLayout() const noexcept = 0; virtual Result ComputeStiffness() const = 0; virtual Result Recover( const Vector& full_displacement) const = 0; }; class Load { public: virtual ~Load() = default; virtual Result> ComputeContributions( const LoadContext& context) const = 0; }; class BoundaryCondition { public: virtual ~BoundaryCondition() = default; virtual Result> ResolveConstraints( const BoundaryConditionContext& context) const = 0; }; ``` Do not add future-only methods to these bases. Factory compatibility may use a centralized, explicit kind discriminator followed by a checked concrete access; consumers must not scatter `dynamic_cast` or B33/MITC4 switches. ## 10. Data Flow Contract ```text existing Abaqus .inp -> syntax reader -> responsibility-split semantic mappers -> immutable Domain-owned definitions -> AnalysisModel non-owning active view -> ElementFactory runtime elements -> DofManager / deterministic assembly / constraints -> LinearStaticAnalysis -> result recovery candidate and validation -> authoritative results.h5 atomic commit -> test-only deterministic projection -> existing Abaqus CSV comparison by source identity and component ``` - B33 input and CSVs remain under `/reference/cantilever beam/` with their current names and component-scale tolerance. - Blocking MITC4 S4 input/displacement CSV remains under `/reference/shell/` with fixed absolute tolerance `1.0e-5` for U1/U2/U3 and warning-only UR1/UR2/UR3. - `/reference/shellR/` is not promoted into a blocking comparison. - No reference artifact is renamed, rewritten, regenerated, or normalized. ## 11. Acceptance Traceability Matrix | Requirement | Tasks | Tests/evidence | Acceptance | | --- | --- | --- | --- | | `R-PRESERVE-001` | `T03..T24` | all current suites, `C-REF-B33-001`, `C-REF-MITC4-001` | Full CTest and blocking references pass. | | `R-STYLE-001` | `T01`, `T03..T06`, `T24` | `P-STYLE-001`, clang-format, clang-tidy config, legacy-header scan | Style commands and full build pass. | | `R-DOC-001` | `T03..T24` | policy scan and configured warning-strict Doxyfile | Production comments exist; tests are excluded. | | `R-DUP-001` | `T07..T09` | `C-VEC3-001`, element/result/I/O suites, duplicate scan | One Vector3 implementation remains. | | `R-DUP-002` | `T10`, `T11`, `T15` | `C-DUP-001..004` | Shared owners pass focused tests. | | `R-MODEL-001` | `T12`, `T13` | `C-MODEL-001..002` | Polymorphic stable ownership passes. | | `R-ELEMENT-001` | `T13`, `T14` | `C-ELEMENT-001` | Factory creates current kinds and rejects incompatible combinations. | | `R-PIPELINE-001` | `T15..T17` | `C-DOF-001`, `C-ASSEMBLY-001`, `C-RECOVERY-001` | Generic consumer and deterministic tests pass. | | `R-LOAD-001` | `T18` | `C-LOAD-001` | Ordered accumulation and current validations pass. | | `R-BC-001` | `T19` | `C-BC-001` | Prescribed displacement partition/reconstruction passes. | | `R-ANALYSIS-001` | `T20` | `C-ANALYSIS-001` | Lifecycle and factorization count pass. | | `R-MODULE-001` | `T21..T23` | `C-MODULE-001..003` | Facade behavior and atomicity suites pass. | | `R-AGENT-001` | `T00` | `P-AGENT-001` | Python workflow contract passes. | | `R-SCOPE-001` | every task | diff review and final reference/artifact checks | No excluded behavior or artifact change appears. | ## 12. Validation Commands Harness Python and policy validation: ```powershell uv run --with pytest python -m pytest -v -rs & "C:/Program Files/LLVM/bin/clang-format.exe" --version & "C:/Program Files/LLVM/bin/clang-tidy.exe" --version & "C:/Program Files/LLVM/bin/clang-tidy.exe" --verify-config ``` MSVC clean configure and full verification: ```powershell $requiredBuildPaths = @( "C:/git/googletest", "C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl", "C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb", "C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" ) foreach ($requiredBuildPath in $requiredBuildPaths) { if (-not (Test-Path -LiteralPath $requiredBuildPath)) { throw "Missing $requiredBuildPath" } } cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 ` "-DFESA_GTEST_SOURCE_DIR=C:/git/googletest" ` "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" cmake --build .harness/build --config Debug --target fesa_tests ctest --test-dir .harness/build -C Debug --show-only=json-v1 ctest --test-dir .harness/build -C Debug --output-on-failure ctest --test-dir .harness/build -C Debug ` -R "B33ReferenceComparison|Mitc4S4Reference" --output-on-failure ``` Repository style and artifact checks: ```powershell $cppFiles = @(rg --files include src tests -g "*.h" -g "*.cpp") & "C:/Program Files/LLVM/bin/clang-format.exe" --dry-run --Werror $cppFiles $publicHeaders = @(rg --files include/fesa -g "*.h") foreach ($publicHeader in $publicHeaders) { & "C:/Program Files/LLVM/bin/clang-tidy.exe" --config-file=.clang-tidy ` $publicHeader -- -x c++ -std=c++17 -Iinclude if ($LASTEXITCODE -ne 0) { throw "clang-tidy failed for $publicHeader" } } $legacyHeaders = @(rg --files include tests -g "*.hpp") if ($legacyHeaders.Count -ne 0) { $legacyHeaders throw "Legacy .hpp headers remain" } git diff --exit-code 1e5758f -- reference ``` Doxygen generation is deliberately absent from the blocking commands. When the user requests documentation generation later, execute `doxygen Doxyfile` and treat warnings as failures without committing generated HTML. ## 13. Risks and Downstream Handoff - Global API/header renaming has a wide compile blast radius. Mechanical style Steps are isolated from semantic restructuring to keep failures attributable. - Domain polymorphism can accidentally destabilize vector indices or lifetimes. Tests must prove insertion order, const access, and AnalysisModel non-owning lifetime. - Virtual element recovery can tempt a giant result record. Preserve distinct beam and shell rows in a backend-neutral bundle rather than adding meaningless common fields. - Moving vector helpers can change floating-point operation order. Preserve each formulation expression order and use exact regression where no approved tolerance applies. - File splits can leak vendor dependencies through public headers. Keep all HDF5/MKL/TBB types in private implementation modules. Downstream handoff is one bounded handoff to `implementation-agent` through the Coordinator: execute only the Executor-selected `stepN.md`, read `/docs/CODINGSTYLE.md` before C++ work, record RED/GREEN/VERIFY evidence, and do not advance another Step. ## 14. Harness Step Draft - Task name: `cpp-object-oriented-modular-refactoring` - Steps: `step0.md` through `step24.md` in dependency order shown in Work Breakdown. - Every Step contains its own prerequisite files, test-first failure, candidate interfaces, exact focused/full commands, and prohibitions. - Stop conditions are an upstream contract conflict, a missing declared artifact at final comparison, an unresolved environment dependency, or repeated build/test failure. In each case only the current Step status payload is changed. - Planning approval materializes these files but does not authorize `python scripts/execute.py cpp-object-oriented-modular-refactoring`. ## 15. Open Issues - No blocking architecture, formulation, I/O, reference, or tolerance issue remains. - Doxygen executable use and generated documentation are deferred by explicit user decision; this does not waive production Doxygen comments or `Doxyfile` configuration.