Files
FESADev/docs/linear-static-3d-euler-beam/implementation-plan.md
T
2026-08-15 03:14:34 +09:00

1139 lines
78 KiB
Markdown

# Linear Static 3D Euler Beam Implementation Plan
> **For agentic workers:** REQUIRED SKILL: use `fesa-cpp-msvc-tdd` for every Step 7-24 task and execute each task as one `RED -> GREEN -> VERIFY` cycle. The Harness executor, not the worker, owns commits and timestamps.
**Goal:** Build the approved single-step Abaqus `TYPE=B33` linear-static pipeline from `.inp` parsing through deterministic sparse solution, result recovery, atomic HDF5 output, CLI execution, and a reusable read-only B33 reference-comparison test.
**Architecture:** `Domain` owns the immutable semantic model; `AnalysisModel`, `DofManager`, and `AnalysisState` separate active views, equation ownership, and mutable solution state. Dense math, CSR storage, oneTBB, oneMKL PARDISO, and HDF5 remain behind focused adapter boundaries, while `Analysis::run()` fixes factorization-before-load orchestration.
**Tech Stack:** C++17, MSVC x64 Debug, CMake, CTest, GoogleTest, Intel oneMKL, Intel oneTBB, and HDF5.
## Metadata
- feature_id: `linear-static-3d-euler-beam`
- source_requirement: `docs/linear-static-3d-euler-beam/requirements.md`
- source_research: `docs/linear-static-3d-euler-beam/research.md`
- source_formulation: `docs/linear-static-3d-euler-beam/formulation.md`
- source_numerical_review: `docs/linear-static-3d-euler-beam/numerical-review.md`
- source_io_definition: `docs/linear-static-3d-euler-beam/io.md`
- source_reference_models: `docs/linear-static-3d-euler-beam/reference-model.md`
- approved_design: `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
- phase_steps: `phases/linear-static-3d-euler-beam/step7.md` through `step24.md`
- status: `ready-for-implementation`
- owner_agent: `implementation-planning-agent`
- date: `2026-08-09`
## Global Constraints
- Implement only one `*STEP, *STATIC` and two-node `TYPE=B33`; reject B31, a second step, instance transforms, nested assembly, `I12!=0`, and `*DLOAD`.
- Preserve the exact lifecycle: stiffness assembly and partition, `Kff` factorization, load assembly, effective RHS, substitution, reconstruction, recovery, HDF5 write.
- Treat `reference/cantilever beam/` as a read-only four-file legacy baseline. Do not create, rename, rewrite, repair, restore, round, or clamp its files.
- Use C++17 and MSVC x64 Debug. Apply `/W4 /WX` only to FESA targets and add no new warnings.
- Keep each owned file focused on its listed responsibility and add reviewer-facing comments for the approved formula/sign, deterministic ordering, backend lifetime, and atomic-finalization decisions implemented there.
- Write and run the related GoogleTest first, observe the planned RED cause, implement the minimum production behavior, then run the targeted GREEN and full VERIFY in the same Step.
- Keep MKL, oneTBB, HDF5, and Windows file-replacement types out of public headers.
- Do not change requirements, formulation, numerical review, I/O contract, reference contract, or tolerance policy during implementation or correction.
- Do not execute Abaqus, Nastran, or another reference solver.
- Do not commit directly; `scripts/execute.py` owns commits and timestamps.
## Readiness Check
| input | required status | observed status | decision |
| --- | --- | --- | --- |
| requirements | approved | `approved`; 44 consecutive must requirements | proceed |
| research | sufficient evidence with implementation gaps identified | `ready-for-formulation`; PARDISO and deterministic reduction gaps explicitly handed off | proceed with the resolutions below |
| formulation | ready for independent numerical review | `ready-for-numerical-review`; no unresolved mathematical input | proceed |
| numerical review | pass for implementation planning | `pass-for-implementation-planning`; no confirmed defect | proceed |
| I/O definition | ready for implementation planning | `ready-for-implementation-planning`; `NR-O03` station normalization resolved | proceed |
| reference models | ready for implementation planning or planned analytical fixtures | `ready-for-implementation-planning`; legacy bundle inventory-ready and analytical fixtures planned | proceed |
| approved design and Step 7-24 | approved and mutually implementable | design `approved`; all 18 module steps present | proceed with the precedence notes below |
### Readiness resolutions
1. `NR-O01-PARDISO-CONTRACT` is closed for planning by Intel's official oneMKL C reference: real symmetric positive definite matrices use `mtype=2`; analysis, numerical factorization, solve, and release are phases `11`, `22`, `33`, and `-1`; `iparm[34]=1` selects zero-based CSR; a retained factorization can serve repeated right-hand sides; and zero/negative SPD pivots stop with error `-4`. Sources: [Intel oneMKL PARDISO](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2025-0/pardiso.html) and [PARDISO iparm parameters](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2025-0/pardiso-iparm-parameter.html).
2. `NR-O02-DETERMINISTIC-REDUCTION` is fixed as a project algorithm: produce one index-addressed local contribution buffer per stable active-element order; enumerate each 12x12 local matrix in row-major `localOrder`; stable-sort COO by `(row,column,elementOrder,localOrder)`; sum duplicates in that order; emit the exact sorted-unique `SparsePattern`; and retain exact zero values for every structural pattern slot. Serial, TBB, and repeated runs must produce byte-identical CSR arrays.
3. `NR-O03-STATION-NORMALIZATION` is already resolved by the I/O/reference contracts: only unloaded, consistently oriented, two-endpoint interior stations are eligible; compare endpoints before choosing the smaller stable element ID; never average.
4. Approved upstream contracts take precedence over broader wording in Step 12. `*STATIC` has exactly one row of four finite positive fields, and material acceptance requires exactly `E,nu`, `E>0`, and derived `G=E/(2*(1+nu))>0`; do not add an unapproved `nu<0.5` rejection.
No readiness item requires a user decision, an upstream edit, or a new reference artifact.
## Implementation Scope
### Included behavior
- Single small-displacement, small-rotation, linear-elastic static analysis.
- Straight prismatic two-node 3D Euler-Bernoulli beam mapped only from Abaqus `TYPE=B33`.
- Global nodal order `[UX,UY,UZ,URX,URY,URZ]`; axial, two-plane bending, and Saint-Venant torsion.
- Approved Abaqus keyword subset, identity instances, stable source/internal identity, warning no-op output allowlist, nodal `*CLOAD`, and zero/nonzero prescribed displacement.
- Formulation-only constant local line-load equivalent nodal vector; no parser or CLI distributed load.
- Contiguous `Vector`, row-major contiguous `Matrix`, deterministic 0-based CSR `SparseMatrix`, element-local oneTBB work, SPD PARDISO factorization/substitution, and residual reactions.
- Mandatory HDF5 displacement, reaction, equilibrium end action, endpoint section resultant, two-Gauss generalized strain/resultant, axial `S11`, metadata, and diagnostics.
- `fesa.exe` CLI and a test-only HDF5-to-legacy-CSV comparison executable/test that Step 26 reruns unchanged.
### Non-goals
- Abaqus full compatibility, B31/Timoshenko behavior, multiple steps, instance transforms, nested assembly, dependent/independent mesh semantics.
- `I12!=0`, taper, offset, release, curved beams, warping, geometric/material nonlinearity, dynamics, contact, or thermal effects.
- `*DLOAD` parsing, a Domain distributed-load object, transverse/torsional shear stress, nodal stress averaging, or Abaqus beam-stress comparison.
- Automatic slenderness acceptance/rejection, arbitrary regularization of singular systems, expression templates, alternate sparse solvers, packaging, release approval, or reference generation.
## Interface and Data-Flow Ledger
The signatures below are the cross-task contract. A task may add private helpers in its owned `.cpp`, but later tasks must consume these names, ownership rules, and types without substituting parallel APIs.
```cpp
// core
struct SourceLocation { std::filesystem::path file; std::size_t line; };
struct SourceEntityId {
std::string instanceName;
std::int64_t sourceLabel;
std::string sourceLabelText;
};
enum class Severity { warning, error };
enum class FailureCategory { input, model, solver, output };
struct Diagnostic {
Severity severity;
std::string code;
SourceLocation location;
std::string keyword;
std::string entityIdentity;
std::string message;
};
class Status {
public:
static Status ok();
static Status failure(std::vector<Diagnostic> diagnostics);
static Status failure(FailureCategory category, std::vector<Diagnostic> diagnostics);
bool isOk() const noexcept;
std::optional<FailureCategory> failureCategory() const noexcept;
const std::vector<Diagnostic>& diagnostics() const noexcept;
};
template<class T> class Result {
public:
static Result success(T value);
static Result failure(Status status);
bool hasValue() const noexcept;
T& value();
const T& value() const;
const Status& status() const noexcept;
};
// dense math
class Vector {
public:
explicit Vector(std::size_t size, double value = 0.0);
std::size_t size() const noexcept;
double* data() noexcept;
const double* data() const noexcept;
double& operator[](std::size_t index);
const double& operator[](std::size_t index) const;
double dot(const Vector& rhs) const;
double norm() const;
void scale(double alpha);
void axpy(double alpha, const Vector& x);
};
class Matrix {
public:
Matrix(std::size_t rows, std::size_t columns, double value = 0.0);
std::size_t rows() const noexcept;
std::size_t columns() const noexcept;
double& operator()(std::size_t row, std::size_t column);
const double& operator()(std::size_t row, std::size_t column) const;
Vector multiply(const Vector& rhs) const;
Matrix multiply(const Matrix& rhs) const;
};
// immutable semantic model
using EntityIndex = std::uint32_t;
struct Node {
SourceEntityId sourceId; std::array<double, 3> coordinates; SourceLocation location;
};
struct LinearElasticMaterial {
std::string name; double youngsModulus; double poissonRatio; SourceLocation location;
};
struct GeneralBeamSection {
std::string name; double area; double i11; double i12; double i22;
double torsionalConstant; std::array<double, 3> firstAxis;
std::vector<std::array<double, 2>> sectionPoints; SourceLocation location;
};
struct EulerBeam3DDefinition {
SourceEntityId sourceId; std::array<EntityIndex, 2> nodeIndices;
EntityIndex materialIndex; EntityIndex sectionIndex; SourceLocation location;
};
struct BoundaryCondition {
std::string target; int firstDof; int lastDof; double value; SourceLocation location;
};
struct NodalLoad {
std::string target; int dof; double magnitude; SourceLocation location;
};
struct StaticStepDefinition {
std::string name; std::vector<BoundaryCondition> boundaries;
std::vector<NodalLoad> loads;
double initialIncrement;
double timePeriod;
double minimumIncrement;
double maximumIncrement;
SourceLocation location;
};
struct NodeSet {
std::string name;
std::optional<std::string> instanceName;
std::vector<EntityIndex> nodeIndices;
SourceLocation location;
};
struct ElementSet {
std::string name;
std::optional<std::string> instanceName;
std::vector<EntityIndex> elementIndices;
SourceLocation location;
};
struct PartDefinition {
std::string name;
std::vector<std::int64_t> nodeSourceLabels;
std::vector<std::int64_t> elementSourceLabels;
std::vector<std::string> nodeSetNames;
std::vector<std::string> elementSetNames;
SourceLocation location;
};
struct SourceIndexMapping {
std::int64_t sourceLabel;
EntityIndex internalIndex;
};
struct InstanceDefinition {
std::string name;
std::string partName;
std::vector<SourceIndexMapping> nodeMappings;
std::vector<SourceIndexMapping> elementMappings;
SourceLocation location;
};
struct ModelDefinition {
std::filesystem::path sourcePath;
std::string sourceContentIdentity;
std::string heading;
std::vector<Node> nodes;
std::vector<EulerBeam3DDefinition> elements;
std::vector<LinearElasticMaterial> materials;
std::vector<GeneralBeamSection> sections;
std::vector<NodeSet> nodeSets;
std::vector<ElementSet> elementSets;
std::vector<PartDefinition> parts;
std::vector<InstanceDefinition> instances;
std::vector<StaticStepDefinition> steps;
std::vector<Diagnostic> warnings;
};
class Domain {
public:
static Result<Domain> create(ModelDefinition definition);
const std::vector<Node>& nodes() const noexcept;
const std::vector<EulerBeam3DDefinition>& elements() const noexcept;
const std::vector<LinearElasticMaterial>& materials() const noexcept;
const std::vector<GeneralBeamSection>& sections() const noexcept;
const std::vector<NodeSet>& nodeSets() const noexcept;
const std::vector<ElementSet>& elementSets() const noexcept;
const std::vector<StaticStepDefinition>& steps() const noexcept;
const std::vector<Diagnostic>& warnings() const noexcept;
const std::filesystem::path& sourcePath() const noexcept;
const std::string& sourceContentIdentity() const noexcept;
};
// parser and active analysis view
struct KeywordParameter { std::string name; std::optional<std::string> value; };
struct DataLine { std::vector<std::string> fields; SourceLocation location; };
struct KeywordBlock {
std::string canonicalName;
std::string originalLine;
std::vector<KeywordParameter> parameters;
std::vector<DataLine> data;
SourceLocation location;
};
struct ParsedInput {
std::filesystem::path sourcePath;
std::string sourceContentIdentity;
std::vector<KeywordBlock> blocks;
};
class AbaqusInputReader {
public:
Result<ParsedInput> read(const std::filesystem::path& inputPath) const;
};
class AbaqusDomainMapper {
public:
Result<Domain> map(const ParsedInput& input) const;
};
class AnalysisModel {
public:
static Result<AnalysisModel> create(const Domain& domain);
const Domain& domain() const noexcept;
const StaticStepDefinition& step() const noexcept;
const std::vector<EntityIndex>& activeElements() const noexcept;
const std::vector<EntityIndex>& activeMaterials() const noexcept;
const std::vector<EntityIndex>& activeSections() const noexcept;
const std::vector<EntityIndex>& activeBoundaryConditions() const noexcept;
const std::vector<EntityIndex>& activeLoads() const noexcept;
};
// equation and state ownership
enum class DofComponent : std::uint8_t { ux, uy, uz, urx, ury, urz };
struct SparsePattern {
std::vector<std::size_t> rowOffsets;
std::vector<std::size_t> columnIndices;
};
class DofManager {
public:
static Result<DofManager> create(const AnalysisModel& model);
std::size_t fullDofCount() const noexcept;
std::size_t freeDofCount() const noexcept;
std::size_t constrainedDofCount() const noexcept;
std::size_t fullDof(EntityIndex node, DofComponent component) const;
std::optional<std::size_t> freeEquation(std::size_t fullDof) const;
const std::array<std::size_t, 12>& elementScatter(EntityIndex element) const;
const std::vector<std::size_t>& freeDofs() const noexcept;
const std::vector<std::size_t>& constrainedDofs() const noexcept;
const Vector& prescribedValues() const noexcept;
const SparsePattern& sparsePattern() const noexcept;
};
struct StepFrameIdentity { std::string stepName; std::size_t frameIndex; };
struct EndpointResultRow {
EntityIndex element; int endpoint; SourceEntityId node;
std::array<double, 6> endAction;
std::array<double, 4> sectionResultant;
};
struct GaussResultRow {
EntityIndex element; int gaussPoint;
std::array<double, 4> generalizedStrain;
std::array<double, 4> generalizedResultant;
};
struct StressS11Row {
EntityIndex element; int gaussPoint; std::size_t sectionPoint;
double x1; double x2; double s11; std::string source;
};
class AnalysisState {
public:
static AnalysisState create(const DofManager& dofs, StepFrameIdentity identity);
Vector& displacement() noexcept; const Vector& displacement() const noexcept;
Vector& externalForce() noexcept; const Vector& externalForce() const noexcept;
Vector& internalForce() noexcept; const Vector& internalForce() const noexcept;
Vector& residual() noexcept; const Vector& residual() const noexcept;
Vector& reaction() noexcept; const Vector& reaction() const noexcept;
const StepFrameIdentity& identity() const noexcept;
std::vector<EndpointResultRow>& endpointResults() noexcept;
const std::vector<EndpointResultRow>& endpointResults() const noexcept;
std::vector<GaussResultRow>& gaussResults() noexcept;
const std::vector<GaussResultRow>& gaussResults() const noexcept;
std::vector<StressS11Row>& stressResults() noexcept;
const std::vector<StressS11Row>& stressResults() const noexcept;
};
// element, parallelism, and sparse assembly
struct ConstantLocalLineLoad { double px; double py; double pz; double mx; };
struct BeamStressPoint {
int gaussPoint; std::size_t sectionPoint; double x1; double x2;
double s11; std::string source;
};
struct BeamRecovery {
std::array<std::array<double, 6>, 2> equilibriumEndActions;
std::array<std::array<double, 4>, 2> endpointSectionResultants;
std::array<std::array<double, 4>, 2> gaussGeneralizedStrains;
std::array<std::array<double, 4>, 2> gaussGeneralizedResultants;
std::vector<BeamStressPoint> stressPoints;
};
class EulerBeam3D {
public:
static Result<EulerBeam3D> create(const Node& firstNode, const Node& secondNode,
const GeneralBeamSection& section,
const LinearElasticMaterial& material);
Matrix localStiffness() const;
Matrix globalStiffness() const;
Vector localEquivalentLoad(const ConstantLocalLineLoad& load) const;
BeamRecovery recover(const Vector& globalElementDisplacement) const;
};
class ParallelFor {
public:
virtual ~ParallelFor() = default;
virtual void execute(std::size_t count,
const std::function<void(std::size_t)>& body) const = 0;
};
class SerialParallelFor final : public ParallelFor {
public:
void execute(std::size_t count,
const std::function<void(std::size_t)>& body) const override;
};
class TbbParallelFor final : public ParallelFor {
public:
void execute(std::size_t count,
const std::function<void(std::size_t)>& body) const override;
};
struct CooContribution {
std::size_t row;
std::size_t column;
double value;
std::size_t elementOrder;
std::size_t localOrder;
};
class SparseMatrix {
public:
static Result<SparseMatrix> fromCoo(std::size_t rows, std::size_t columns,
std::vector<CooContribution> contributions,
const SparsePattern& expectedPattern);
std::size_t rows() const noexcept;
std::size_t columns() const noexcept;
const std::vector<std::size_t>& rowOffsets() const noexcept;
const std::vector<std::size_t>& columnIndices() const noexcept;
const std::vector<double>& values() const noexcept;
Vector multiply(const Vector& rhs) const;
Status validate() const;
};
class SparseAssembler {
public:
static Result<SparseMatrix> assembleStiffness(const AnalysisModel& model,
const DofManager& dofs,
const ParallelFor& parallelFor);
};
// constraints, solver, load, recovery, and output
struct PartitionedStiffness {
SparseMatrix kff;
SparseMatrix kfc;
SparseMatrix kcf;
SparseMatrix kcc;
};
class EssentialConstraints {
public:
static Result<PartitionedStiffness> partition(const SparseMatrix& full,
const DofManager& dofs);
static Vector gatherFree(const Vector& full, const DofManager& dofs);
static Vector gatherConstrained(const Vector& full, const DofManager& dofs);
static Vector reconstructFull(const Vector& freeValues,
const Vector& constrainedValues,
const DofManager& dofs);
};
class LinearSolver {
public:
virtual ~LinearSolver() = default;
virtual Status factorize(const SparseMatrix& matrix) = 0;
virtual Status solve(const Vector& rhs, Vector& solution) const = 0;
};
class MklPardisoSolver final : public LinearSolver {
public:
MklPardisoSolver();
~MklPardisoSolver() override;
Status factorize(const SparseMatrix& matrix) override;
Status solve(const Vector& rhs, Vector& solution) const override;
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
class LoadAssembler {
public:
static Result<Vector> assembleFullNodalLoad(const AnalysisModel& model,
const DofManager& dofs);
static Result<Vector> effectiveFreeRhs(const Vector& fullLoad,
const SparseMatrix& kfc,
const Vector& prescribedValues,
const DofManager& dofs);
};
struct NodeStationResultRow {
SourceEntityId node;
EntityIndex representativeElement;
std::array<double, 4> sectionResultant;
};
class ResultRecovery {
public:
static Status recover(const AnalysisModel& model,
const DofManager& dofs,
const SparseMatrix& fullStiffness,
AnalysisState& state);
static Result<std::vector<NodeStationResultRow>> normalizeSectionResultantsToNodeStations(
const AnalysisModel& model,
const std::vector<EndpointResultRow>& endpointRows,
const std::array<double, 4>& componentTolerances); // [N,T,My,Mz]
};
class ResultsWriter {
public:
virtual ~ResultsWriter() = default;
virtual Status write(const std::filesystem::path& outputPath,
const Domain& domain,
const AnalysisState& state,
const std::vector<Diagnostic>& diagnostics) = 0;
};
class Hdf5ResultsWriter final : public ResultsWriter {
public:
Status write(const std::filesystem::path& outputPath,
const Domain& domain,
const AnalysisState& state,
const std::vector<Diagnostic>& diagnostics) override;
};
// orchestration
struct AnalysisRequest { std::filesystem::path inputPath; std::filesystem::path outputPath; };
class Analysis {
public:
virtual ~Analysis() = default;
Status run(const AnalysisRequest& request);
protected:
virtual Status initialize(const AnalysisRequest& request) = 0;
virtual Status buildAnalysisModel() = 0;
virtual Status buildDofMapAndSparsePattern() = 0;
virtual Status assembleAndPartitionStiffness() = 0;
virtual Status factorize() = 0;
virtual Status assembleLoadsAndEffectiveRhs() = 0;
virtual Status substituteAndReconstruct() = 0;
virtual Status recoverAndWriteResults() = 0;
};
class LinearStaticAnalysis final : public Analysis {
public:
LinearStaticAnalysis(const ParallelFor& parallelFor,
LinearSolver& linearSolver,
ResultsWriter& resultsWriter);
protected:
Status initialize(const AnalysisRequest& request) override;
Status buildAnalysisModel() override;
Status buildDofMapAndSparsePattern() override;
Status assembleAndPartitionStiffness() override;
Status factorize() override;
Status assembleLoadsAndEffectiveRhs() override;
Status substituteAndReconstruct() override;
Status recoverAndWriteResults() override;
};
class FesaApplication {
public:
int run(const std::vector<std::string>& arguments);
};
```
These records preserve raw names/source-label lexemes and stable declaration order but contain no equation IDs or analysis vectors. Step 12 rejects transforms before creating `InstanceDefinition`, so the record deliberately has no transform field.
## Work Breakdown
Every task below is one Harness Step and one independent review gate. Each task begins by registering the named GoogleTests in `tests/CMakeLists.txt`, observes the stated RED, adds only its owned production files, reaches the targeted GREEN, appends evidence to the implementation report, and runs its full VERIFY.
### TASK-07: `cmake-test-foundation`
**Files and single responsibilities**
| action | file | responsibility |
| --- | --- | --- |
| create | `CMakeLists.txt` | C++17 project root, dependency entry, testing enablement, subdirectories |
| create | `cmake/FesaDependencies.cmake` | validate `FESA_GTEST_SOURCE_DIR`; normalize oneMKL, oneTBB, HDF5 imported targets |
| create | `include/fesa/build_info.hpp` | declare `std::string_view solverVersion() noexcept` only |
| create | `src/fesa/build_info.cpp` | define stable solver version string |
| create | `src/fesa/CMakeLists.txt` | `fesa_solver`, warning isolation, and later production source registration |
| create | `tests/CMakeLists.txt` | GoogleTest targets/discovery, common feature label, test meta-target |
| create | `tests/unit/build_info_test.cpp` | compile/runtime contract for solver version |
| create | `docs/linear-static-3d-euler-beam/implementation-report.md` | cumulative Step 7-24 evidence ledger |
- Consumes: repository toolchain and approved dependency locations; no solver module.
- Produces: normalized dependency aliases `Fesa::MKL`, `Fesa::TBB`, and `Fesa::HDF5`; `fesa_solver`; `fesa_unit_tests`; custom target `fesa_tests`; common CTest label `linear-static-3d-euler-beam`; and `solverVersion()`.
- Tests: `T07-BUILD-001 = BuildInfo.VersionIsStableAndNonEmpty`; `T07-BUILD-002 = BuildInfo.PublicHeaderHasNoBackendDependency`.
- RED: configure the test target with `build_info_test.cpp` registered but before creating `build_info.hpp/.cpp`; the build must fail for the missing header or symbol.
- GREEN: `BuildInfo` CTest passes and GoogleTest revision equals `04ee1b4f2aefdffb0135d7cf2a2c519fe50dabe4`.
- Targeted command:
```powershell
cmake --build .harness/build --config Debug --target fesa_tests
ctest --test-dir .harness/build -C Debug -R BuildInfo --output-on-failure
```
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R BuildInfo --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-08: `core-diagnostics`
**Files:** create `include/fesa/core/source_identity.hpp` (identity/location values), `include/fesa/core/diagnostic.hpp` (diagnostic fields/order declaration), `include/fesa/core/status.hpp` (`Status`, `FailureCategory`, `Result<T>`), `src/fesa/core/diagnostic.cpp` (stable ordering/formatting), `src/fesa/core/status.cpp` (status state); create `tests/unit/core/source_identity_test.cpp`, `diagnostic_test.cpp`, `status_test.cpp`; modify both CMake lists only for these sources/tests.
- Consumes: `solverVersion()` and C++ standard library only.
- Produces: the core signatures in the ledger; stable sort tuple `(file,line,keyword,entityIdentity,code,discoveryOrder)`; backend-free success/failure transport.
- Tests: `T08-CORE-001 = CoreDiagnostics.SourceIdentityPreservesRawIdentity`; `T08-CORE-002 = CoreDiagnostics.DiagnosticsSortDeterministically`; `T08-CORE-003 = CoreDiagnostics.ResultEnforcesValueErrorExclusivity`.
- RED/GREEN: registered tests fail to compile for missing core headers, then pass value/error, copy/move, failed access, exact fields, category, and ordering cases.
- Targeted command: `cmake --build .harness/build --config Debug --target fesa_tests` then `ctest --test-dir .harness/build -C Debug -R CoreDiagnostics --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R CoreDiagnostics --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-09: `dense-math-adapters`
**Files:** create `include/fesa/math/vector.hpp` and `matrix.hpp` for owning public types; create `src/fesa/math/vector.cpp` and `matrix.cpp` for MKL CBLAS calls; create `tests/unit/math/vector_test.cpp` and `matrix_test.cpp`; modify both CMake lists only for dense math.
- Consumes: core exceptions/status conventions and normalized oneMKL target.
- Produces: the exact `Vector`/`Matrix` ledger signatures with deep copy, safe move, checked access, dimension checks, and row-major GEMV/GEMM.
- Tests: `T09-DENSE-001 = DenseMath.VectorOwnsAndChecksContiguousStorage`; `T09-DENSE-002 = DenseMath.RowMajorMatrixMatchesKnownGemvGemm`.
- RED/GREEN: missing headers/symbols produce RED; GREEN covers zero size, copy/move, bounds, mismatch, nonsquare operations, and known BLAS values.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R DenseMath --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R DenseMath --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-10: `domain-model`
**Files:** create `include/fesa/model/model_types.hpp` for semantic records and `include/fesa/model/domain.hpp` for immutable ownership/lookups; create `src/fesa/model/domain.cpp` for construction/finalization; create `tests/unit/model/model_types_test.cpp` and `domain_test.cpp`; modify CMake lists only for the model.
- Consumes: `SourceEntityId`, `Diagnostic`, `Result<T>`.
- Produces: `EntityIndex`, all model records, `ModelDefinition`, and immutable `Domain`; stable indices follow declaration/instance/entity order; nodes/elements have no equation IDs.
- Tests: `T10-DOM-001 = DomainModel.SourceAndInternalIdentityRemainDistinct`; `T10-DOM-002 = DomainModel.ImmutableOwnershipPreservesStableOrder`; `T10-DOM-003 = DomainModel.MultipleIdentityInstancesDoNotMerge`.
- RED/GREEN: missing model types produce compile RED; GREEN proves raw identity, stable lookup/index, deep ownership, const access, one step storage, and absence of equation state.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R DomainModel --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R DomainModel --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-11: `inp-syntax-parser`
**Files:** create `include/fesa/io/abaqus/input_syntax.hpp` for syntax records, `input_reader.hpp` for the reader boundary, `src/fesa/io/abaqus/input_reader.cpp` for lexical/syntax parsing; create `tests/unit/io/abaqus/input_syntax_test.cpp` and `input_reader_test.cpp`; modify CMake lists only for syntax parsing.
- Consumes: `SourceLocation`, `Diagnostic`, `Result<T>`.
- Produces: `KeywordParameter`, `DataLine`, `KeywordBlock`, `ParsedInput`, and `AbaqusInputReader::read`; it records normalized source path plus a deterministic `fnv1a64:` prefix followed by exactly 16 lowercase hexadecimal digits computed from the exact input bytes, and makes no B33 or keyword-policy decisions.
- Tests: `T11-SYN-001 = InpSyntax.CanonicalizesKeywordAndParameterNamesOnly`; `T11-SYN-002 = InpSyntax.PreservesDataAndSourceLocations`; `T11-SYN-003 = InpSyntax.RejectsMalformedOrOrphanData`; `T11-SYN-004 = InpSyntax.ReadsLegacyCantileverWithoutMutation`.
- RED/GREEN: registered parser tests fail for missing reader; GREEN covers mixed case, comments, blanks/trailing fields, valueless parameters, unreadable files, malformed syntax, and legacy syntax.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R InpSyntax --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R InpSyntax --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-12: `inp-domain-mapping`
**Files:** create `include/fesa/io/abaqus/domain_mapper.hpp`, `src/fesa/io/abaqus/domain_mapper.cpp`, and `tests/unit/io/abaqus/domain_mapper_test.cpp`; modify CMake lists only for semantic mapping.
- Consumes: `ParsedInput`, `ModelDefinition`, and `Domain::create`.
- Produces: `AbaqusDomainMapper::map` returning a complete immutable `Domain` or ordered diagnostics; maps only the approved keyword grammar, exact four-field `*STATIC`, B33, identity instances, exact section/material rules, warning no-ops, and stable expansions.
- Tests: `T12-MAP-001 = InpDomainMapping.MapsEverySupportedKeywordAndLegacyDeck`; `T12-MAP-002 = InpDomainMapping.ExpandsSetsAndMultipleIdentityInstancesDeterministically`; `T12-MAP-003 = InpDomainMapping.NoOpAllowlistWarnsWithoutSemanticEffect`; `T12-MAP-004 = InpDomainMapping.RejectsUnsupportedAndInvalidPortfolio`; `T12-MAP-005 = InpDomainMapping.RejectsDloadWithoutDistributedLoadObject`.
- RED/GREEN: positive and table-driven negative tests are registered before the mapper and fail RED; GREEN includes B31, second step, transform, nested assembly, coupled section, invalid geometry/property, duplicate, dangling, nonfinite, malformed arity, NLGEOM, unknown keyword, and `*DLOAD` diagnostics.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R InpDomainMapping --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R InpDomainMapping --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-13: `analysis-model`
**Files:** create `include/fesa/analysis/analysis_model.hpp`, `src/fesa/analysis/analysis_model.cpp`, and `tests/unit/analysis/analysis_model_test.cpp`; modify CMake lists only for the active view.
- Consumes: immutable `Domain` and its sole `StaticStepDefinition`.
- Produces: `AnalysisModel::create` and the exact active-ID/reference accessors in the ledger; reachable material/section IDs are deduplicated in stable internal-index order.
- Tests: `T13-MODEL-001 = AnalysisModel.ClassifiesActiveEntitiesInStableOrder`; `T13-MODEL-002 = AnalysisModel.ReferencesWithoutCopyingOrMutatingDomain`; `T13-MODEL-003 = AnalysisModel.RejectsMissingOrMultipleStep`.
- RED/GREEN: missing class gives RED; GREEN proves address identity, stable deduplication, immutability, and cardinality diagnostics.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R AnalysisModel --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R AnalysisModel --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-14: `dof-manager`
**Files:** create `include/fesa/fem/dof_manager.hpp`, `src/fesa/fem/dof_manager.cpp`, and `tests/unit/fem/dof_manager_test.cpp`; modify CMake lists only for DOF ownership.
- Consumes: `AnalysisModel`, `Vector`, expanded boundary targets, active element connectivity.
- Produces: exact `DofManager`, `DofComponent`, and `SparsePattern` ledger contracts; `prescribedValues()` is ordered exactly like `constrainedDofs()`.
- Tests: `T14-DOF-001 = DofManager.NumbersSixDofsAndFreeEquationsStably`; `T14-DOF-002 = DofManager.ExpandsAndValidatesPrescribedValues`; `T14-DOF-003 = DofManager.BuildsTwelveDofScatterAndSortedUniquePattern`; `T14-DOF-004 = DofManager.ReconstructsFullReducedRoundTrip`.
- RED/GREEN: numbering/constraint/pattern tests fail before production; GREEN covers zero/nonzero prescriptions, equal overlap, conflicting overlap, element scatter, sorted-unique pattern, and no Node/Element equation ID.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R DofManager --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R DofManager --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-15: `analysis-state`
**Files:** create `include/fesa/results/result_records.hpp` for row identities, `include/fesa/analysis/analysis_state.hpp` for state ownership, `src/fesa/analysis/analysis_state.cpp` for allocation/access; create `tests/unit/results/result_records_test.cpp` and `tests/unit/analysis/analysis_state_test.cpp`; modify CMake lists only for result records/state.
- Consumes: `DofManager`, `Vector`, model identities.
- Produces: `StepFrameIdentity`, endpoint/Gauss/stress records, and exact `AnalysisState` accessors; every full vector is independently owned, full-size, and zero-initialized.
- Tests: `T15-STATE-001 = AnalysisState.AllocatesOnlyV0FullVectors`; `T15-STATE-002 = AnalysisState.PreservesStepFrameAndStableRowOrder`; `T15-STATE-003 = AnalysisState.CopiesOrMovesWithoutAliasing`.
- RED/GREEN: missing records/state produce RED; GREEN proves allocation, ownership, identity/order, reaction full-space semantics, and absence of velocity, acceleration, temperature, and nonlinear state APIs.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R AnalysisState --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R AnalysisState --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-16: `euler-beam-element`
**Files:** create `include/fesa/elements/euler_beam_3d.hpp` for `ConstantLocalLineLoad`, stress/recovery records, and kernel API; create `src/fesa/elements/euler_beam_3d.cpp` for geometry, Gauss stiffness, transform, load, and recovery; create `tests/unit/elements/euler_beam_3d_test.cpp`; modify CMake lists only for the element.
- Consumes: `Node`, `GeneralBeamSection`, `LinearElasticMaterial`, `Vector`, `Matrix`, formulation signs and tolerances.
- Produces: exact `EulerBeam3D` ledger contract and `BeamRecovery`; local order is `[u1,v1,w1,rx1,ry1,rz1,u2,v2,w2,rx2,ry2,rz2]`; `dl=T*dg`, `Kg=T^T*Kl*T`.
- Tests: `T16-BEAM-001 = EulerBeam3D.HermiteAndBMatrixMatchReviewedSigns`; `T16-BEAM-002 = EulerBeam3D.TwoPointGaussMatchesClosedStiffness`; `T16-BEAM-003 = EulerBeam3D.HasSixRigidModesRankSixAndPositiveDeformationEnergy`; `T16-BEAM-004 = EulerBeam3D.RotatedTransformPreservesWorkAndEnergy`; `T16-BEAM-005 = EulerBeam3D.ConstantLineLoadMatchesAllSignedComponents`; `T16-BEAM-006 = EulerBeam3D.AnalyticalAxialTorsionAndTwoPlaneBendingRecover`; `T16-BEAM-007 = EulerBeam3D.RejectsInvalidGeometryAndProperties`; `T16-BEAM-008 = EulerBeam3D.RecoversSectionPointAndDefaultCentroidS11`; `T16-BEAM-009 = EulerBeam3D.ReproducesConstantStrainTwistAndCurvaturePatches`; `T16-BEAM-010 = EulerBeam3D.OnePointNegativeControlHasRankFour`.
- RED/GREEN: all invariant/analytical tests are written before the kernel; GREEN enforces normalized `1e-12` matrices/transforms/end signs, `1e-10` rigid residual, relative `1e-9` analytical results, the length-scaled `Q^-T*K*Q^-1` six/six singular-value split, exact axial/twist/two-curvature patches, production rank 6, test-only one-point rank 4, two production Gauss points, exact geometry thresholds, and no fallback axis.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R EulerBeam3D --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R EulerBeam3D --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-17: `parallel-for-tbb`
**Files:** create `include/fesa/assembly/parallel_for.hpp` for backend-free interface/serial/TBB classes, `src/fesa/assembly/parallel_for.cpp` for implementations, and `tests/unit/assembly/parallel_for_test.cpp`; modify CMake lists only for the adapter.
- Consumes: `std::function` and normalized oneTBB target; it does not consume sparse storage.
- Produces: exact `ParallelFor`, `SerialParallelFor`, and `TbbParallelFor` contracts; each index executes exactly once and writes only its caller-owned indexed slot.
- Tests: `T17-PFOR-001 = ParallelFor.ZeroOneManyExecuteExactlyOnce`; `T17-PFOR-002 = ParallelFor.SerialAndTbbProduceStableIndexedOutput`; `T17-PFOR-003 = ParallelFor.PropagatesBodyExceptionByContract`.
- RED/GREEN: missing adapter gives RED; GREEN proves no-op zero count, exact-once semantics, stable output, and exception propagation without process-wide thread changes.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R ParallelFor --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R ParallelFor --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-18: `sparse-assembly`
**Files:** create `include/fesa/math/sparse_matrix.hpp` and `src/fesa/math/sparse_matrix.cpp` for owning 0-based CSR; create `include/fesa/assembly/sparse_assembler.hpp` and `src/fesa/assembly/sparse_assembler.cpp` for element buffers and deterministic reduction; create `tests/unit/math/sparse_matrix_test.cpp` and `tests/unit/assembly/sparse_assembler_test.cpp`; modify CMake lists only for sparse math/assembly.
- Consumes: `AnalysisModel`, `DofManager`, `EulerBeam3D`, `ParallelFor`, `SparsePattern`, `Vector`.
- Produces: exact `CooContribution`, `SparseMatrix`, and `SparseAssembler` ledger contracts; expected structural zero slots are retained; `SparseMatrix` is unrelated by inheritance to `Matrix`.
- Tests: `T18-SPARSE-001 = SparseAssembly.ValidatesKnownCsrAndMultiply`; `T18-SPARSE-002 = SparseAssembly.ReducesDuplicatesInFixedTupleOrder`; `T18-SPARSE-003 = SparseAssembly.RejectsInvalidIndexPatternAndShape`; `T18-SPARSE-004 = SparseAssembly.SerialTbbAndRepeatedRunsAreByteIdentical`; `T18-SPARSE-005 = SparseAssembly.PreservesExpectedStructuralZeros`.
- RED/GREEN: CSR/determinism tests fail before implementation; GREEN produces sorted unique columns, valid offsets, fixed duplicate sums, empty rows when expected, symmetry, and byte-identical arrays across schedulers/runs.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R SparseAssembly --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R SparseAssembly --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-19: `essential-constraints`
**Files:** create `include/fesa/constraints/essential_constraints.hpp`, `src/fesa/constraints/essential_constraints.cpp`, and `tests/unit/constraints/essential_constraints_test.cpp`; modify CMake lists only for partition/mapping.
- Consumes: full `SparseMatrix`, `DofManager` order, full/reduced `Vector` values.
- Produces: `PartitionedStiffness {kff,kfc,kcf,kcc}` and exact `EssentialConstraints` ledger functions without assembling loads or RHS.
- Tests: `T19-CONSTRAINT-001 = EssentialConstraints.ExtractsHandComputedBlocksInStableOrder`; `T19-CONSTRAINT-002 = EssentialConstraints.HandlesNoAllAndMixedConstraints`; `T19-CONSTRAINT-003 = EssentialConstraints.ReconstructsNonzeroPrescribedValues`; `T19-CONSTRAINT-004 = EssentialConstraints.RejectsDimensionOrOrderMismatch`.
- RED/GREEN: block/round-trip tests fail before production; GREEN preserves numeric/order/CSR invariants and never assumes `dc=0`.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R EssentialConstraints --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R EssentialConstraints --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-20: `mkl-pardiso-solver`
**Files:** create `include/fesa/solvers/linear/linear_solver.hpp` for the backend boundary, `include/fesa/solvers/linear/mkl_pardiso_solver.hpp` for the PImpl class, `src/fesa/solvers/linear/mkl_pardiso_solver.cpp` for all MKL calls/workspace lifetime; create `tests/unit/solvers/linear/linear_solver_test.cpp` and `mkl_pardiso_solver_test.cpp`; modify CMake lists only for the solver.
- Consumes: validated square `SparseMatrix`, `Vector`, `Status`, `Diagnostic`, official PARDISO contract.
- Produces: exact `LinearSolver` and `MklPardisoSolver` signatures; `factorize()` validates the full public CSR, copies its upper triangle into private MKL CSR with every diagonal slot retained, then runs PARDISO phase `11` and `22` with `mtype=2`, `iparm[34]=1`, and matrix checking enabled; `solve()` runs phase `33`; re-factorization and destruction release with phase `-1` through RAII.
- Tests: `T20-PARDISO-001 = MklPardisoSolver.SolvesKnownSpdWithNormalizedResidual`; `T20-PARDISO-002 = MklPardisoSolver.ReusesOneFactorizationForRepeatedRhs`; `T20-PARDISO-003 = MklPardisoSolver.RefactorizesWithoutLeakingState`; `T20-PARDISO-004 = MklPardisoSolver.RejectsInvalidCsrStateAndDimensions`; `T20-PARDISO-005 = MklPardisoSolver.ClassifiesSingularIndefiniteAndNonfiniteFailures`; `T20-PARDISO-006 = MklPardisoSolver.ConditioningSweepPassesResolvedCasesAndFailsUnresolvedCasesExplicitly`.
- RED/GREEN: adapter tests fail before implementation; GREEN meets residual `1e-10`, repeated RHS, solve-before-factorize, dimension, invalid CSR, zero/negative pivot, singular, and indefinite diagnostics without regularization. The documented valid-scale sweep requires residual `1e-10` and analytical error `1e-9` for resolved cases and a structured solver failure for numerically unresolved cases; it introduces no new conditioning threshold.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R MklPardisoSolver --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R MklPardisoSolver --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-21: `load-assembly`
**Files:** create `include/fesa/assembly/load_assembler.hpp`, `src/fesa/assembly/load_assembler.cpp`, and `tests/unit/assembly/load_assembler_test.cpp`; modify CMake lists only for nodal load/RHS assembly.
- Consumes: `AnalysisModel`, `DofManager`, `SparseMatrix kfc`, and prescribed `dc`.
- Produces: exact `LoadAssembler` ledger functions; multiple loads sum in source order; effective RHS is exactly `Ff-kfc*dc`.
- Tests: `T21-LOAD-001 = LoadAssembly.AssemblesNodeSetAndSixComponentLoads`; `T21-LOAD-002 = LoadAssembly.AccumulatesSignedLoadsInSourceOrder`; `T21-LOAD-003 = LoadAssembly.FormsNonzeroPrescribedEffectiveRhs`; `T21-LOAD-004 = LoadAssembly.RejectsNonfiniteOrDimensionMismatch`; `T21-LOAD-005 = LoadAssembly.ZeroLoadsRemainZero`.
- RED/GREEN: registered load/RHS tests fail before implementation; GREEN handles constrained loads and nonzero `dc` without factorization calls or distributed-load objects.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R LoadAssembly --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R LoadAssembly --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-22: `result-recovery`
**Files:** create `include/fesa/results/result_recovery.hpp`, `src/fesa/results/result_recovery.cpp`, and `tests/unit/results/result_recovery_test.cpp`; modify CMake lists only for recovery and station normalization.
- Consumes: `AnalysisModel`, `DofManager`, full `SparseMatrix`, solved `AnalysisState`, and `EulerBeam3D::recover`.
- Produces: exact `ResultRecovery::recover`; `internalForce=K*d`, `residual=internalForce-externalForce`, constrained reaction from residual, stable endpoint/Gauss/stress rows, and test-only reusable node-station projection semantics.
- Tests: `T22-RECOVERY-001 = ResultRecovery.ComputesResidualReactionForNonzeroPrescription`; `T22-RECOVERY-002 = ResultRecovery.EnforcesNormalizedFreeResidual`; `T22-RECOVERY-003 = ResultRecovery.KeepsEndActionSectionAndGaussResultsDistinct`; `T22-RECOVERY-004 = ResultRecovery.MatchesAxialTorsionAndTwoPlaneEndSigns`; `T22-RECOVERY-005 = ResultRecovery.OrdersStressPointsAndDefaultCentroid`; `T22-RECOVERY-006 = ResultRecovery.RequiresInteriorEndpointConsistencyWithoutAveraging`.
- RED/GREEN: reaction/sign/station tests fail before implementation; GREEN enforces free residual `1e-10`, nonfinite failure, source/stable order, and smaller-element representative only after endpoint agreement.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R ResultRecovery --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R ResultRecovery --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-23: `hdf5-results-writer`
**Files:** create `include/fesa/results/results_writer.hpp` for the backend-free interface, `include/fesa/io/hdf5/hdf5_results_writer.hpp` for the concrete class, `src/fesa/io/hdf5/hdf5_results_writer.cpp` for HDF5 RAII/schema/temp-final replacement; create `tests/unit/results/results_writer_test.cpp` and `tests/unit/io/hdf5/hdf5_results_writer_test.cpp`; modify CMake lists only for output.
- Consumes: immutable `Domain`, solved `AnalysisState`, diagnostics, `solverVersion()`.
- Produces: exact `ResultsWriter`/`Hdf5ResultsWriter` signatures; schema v0 at literal `Step-1/frame 0`, including the required `generalized_resultant` sibling; same-directory temporary write, flush/close/self-check, then a private `.cpp` finalizer that uses `ReplaceFileW` for an existing final and `MoveFileExW(..., MOVEFILE_WRITE_THROUGH)` for a new final, preserving the previous final and removing the temporary file when replacement fails. Win32 types never enter either public header.
- Tests: `T23-HDF5-001 = Hdf5ResultsWriter.WritesExactSchemaShapesAttributesAndIdentity`; `T23-HDF5-002 = Hdf5ResultsWriter.WritesMandatoryOutputsDespiteOutputRequests`; `T23-HDF5-003 = Hdf5ResultsWriter.WritesWarningsAndDefaultCentroid`; `T23-HDF5-004 = Hdf5ResultsWriter.FailureLeavesNoPartialAndPreservesExistingFinal`; `T23-HDF5-005 = Hdf5ResultsWriter.SuccessfullyReplacesExistingFinal`.
- RED/GREEN: schema/atomicity tests fail before the writer; GREEN verifies every exact path/component/location, UTF-8 identity, unit label, finite values, RAII closure, temporary cleanup, and replacement behavior.
- Targeted command: build `fesa_tests`, then `ctest --test-dir .harness/build -C Debug -R Hdf5ResultsWriter --output-on-failure`.
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R Hdf5ResultsWriter --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
### TASK-24: `linear-static-cli`
**Files and single responsibilities**
| action | file | responsibility |
| --- | --- | --- |
| create | `include/fesa/analysis/linear_static_analysis.hpp` | Template Method and injected linear-static API |
| create | `src/fesa/analysis/linear_static_analysis.cpp` | exact stage order and state handoff |
| create | `include/fesa/app/fesa_application.hpp` | argument/exit-code application boundary |
| create | `src/fesa/app/fesa_application.cpp` | CLI parsing, default adapters, diagnostic output |
| create | `src/fesa/app/main.cpp` | minimal process entry point only |
| create | `tests/integration/analysis/linear_static_analysis_test.cpp` | spy/fake lifecycle and real analytical integration |
| create | `tests/integration/app/fesa_application_test.cpp` | CLI paths, exit codes, output-request no-op |
| create | `tests/reference/reference_comparison.hpp` | test-only row/metric contract without HDF5 types |
| create | `tests/reference/reference_comparison.cpp` | read-only CSV/HDF5 projection, precheck, compare, deterministic JSON |
| create | `tests/reference/reference_comparison_test.cpp` | comparison-policy positive/negative tests |
| create | `tests/reference/b33_reference_comparison_test.cpp` | approved B33 end-to-end run and artifact generation |
| modify | `src/fesa/CMakeLists.txt` | add `fesa` executable with `OUTPUT_NAME fesa` |
| modify | `tests/CMakeLists.txt` | add integration/reference executables, labels, and `fesa_tests` dependencies |
- Consumes: every ledger interface from Tasks 08-23 and the exact four read-only files under `reference/cantilever beam/`.
- Produces: exact `Analysis`, `LinearStaticAnalysis`, `AnalysisRequest`, and `FesaApplication` ledger contracts; production defaults are `TbbParallelFor`, `MklPardisoSolver`, and `Hdf5ResultsWriter`; generated evidence is `.harness/build/reference/cantilever-beam-b33/results.h5` plus `comparison.json`.
The test-only `reference_comparison.hpp` contract is:
```cpp
namespace fesa::test {
enum class ComparisonQuantity { displacement, reaction, sectionResultant };
struct CanonicalComparisonRow {
std::string modelId;
std::string stepName;
std::size_t frameIndex;
std::string instanceName;
std::int64_t sourceNodeLabel;
ComparisonQuantity quantity;
std::string component;
double value;
std::string unitDimension;
std::string coordinateSystem;
std::string hdf5DatasetPath;
};
struct RowDecision {
CanonicalComparisonRow fesa;
CanonicalComparisonRow reference;
double absoluteError;
double tolerance;
bool passed;
};
struct ComponentMetrics {
ComparisonQuantity quantity;
std::string component;
double referenceScale;
double maximumAbsoluteError;
double maximumNormalizedError;
double rmsError;
double normError;
std::size_t worstRow;
};
struct PhysicsEvidence {
double freeResidualNorm;
std::array<double, 3> appliedForce;
std::array<double, 3> reactionForce;
std::array<double, 3> appliedMomentAboutOrigin;
std::array<double, 3> reactionMomentAboutOrigin;
bool endpointConsistencyPassed;
};
struct ComparisonReport {
std::vector<RowDecision> rows;
std::vector<ComponentMetrics> metrics;
PhysicsEvidence physicsEvidence;
bool stressComparisonApplicable;
std::string stressComparisonReason;
bool passed;
};
class ReferenceComparison {
public:
static Result<ComparisonReport> compare(
const std::filesystem::path& resultsHdf5,
const std::filesystem::path& legacyReferenceDirectory);
static Status writeDeterministicJson(
const ComparisonReport& report,
const std::filesystem::path& outputJson);
};
} // namespace fesa::test
```
`stressComparisonApplicable` is always `false` for this approved bundle and is serialized with the reason that analytical/unit and HDF5 schema tests provide stress evidence. The comparator accepts only the literal legacy directory and exact filenames; it has no write operation for that directory.
All malformed-reference negative cases operate on copies created under `.harness/build/reference/contract-fixtures/`; no test opens a legacy reference path for writing.
- Tests: `T24-ORCH-001 = LinearStaticCli.FactorizesBeforeLoadAndSolvesWithoutRefactorization`; `T24-ORCH-002 = LinearStaticCli.RealPipelineHandlesAnalyticalAndNonzeroPrescription`; `T24-CLI-001 = LinearStaticCli.DefaultAndExplicitOutputProduceFesaHdf5`; `T24-CLI-002 = LinearStaticCli.ReturnsEveryExactExitCodeAndOrderedDiagnostic`; `T24-CLI-003 = LinearStaticCli.OutputRequestsDoNotFilterMandatoryResults`; `T24-REF-001 = ReferenceComparisonContract.PrecheckRejectsMissingSchemaDuplicateAndNonfiniteRows`; `T24-REF-002 = ReferenceComparisonContract.AppliesAbaqusOnlyComponentScaleWithoutClampOrDrop`; `T24-REF-003 = ReferenceComparisonContract.ReportsEveryRowAndAggregateMetricDeterministically`; `T24-REF-004 = ReferenceComparisonContract.NormalizesEligibleStationsWithoutAveraging`; `T24-B33-001 = B33ReferenceComparison.GeneratesAuthoritativeHdf5AndComparisonEvidence`.
- RED/GREEN: orchestration/CLI/reference tests are registered first and fail for missing APIs; GREEN fixes the exact event trace, all CLI forms/codes, artifact precheck, exact row sets, header/component/frame/station normalization, zero/near-zero/failure tolerance cases, and deterministic metrics/physics evidence.
- Step 26 handoff: `B33ReferenceComparison` is a completed test-only executable/test at the end of this task. Step 26 runs it and reads `comparison.json` without modifying source, tests, CMake, tolerances, or reference artifacts. Stress is recorded as N/A for Abaqus comparison while HDF5 `stress_s11` remains required.
- Targeted command:
```powershell
cmake --build .harness/build --config Debug --target fesa_tests
ctest --test-dir .harness/build -C Debug -R "LinearStaticCli|ReferenceComparisonContract|B33ReferenceComparison" --output-on-failure
```
- Full VERIFY:
```powershell
cmake -S . -B .harness/build -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
ctest --test-dir .harness/build -C Debug -R "LinearStaticCli|ReferenceComparisonContract|B33ReferenceComparison" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
git diff --exit-code -- reference/
```
## TDD Test Plan
| test group | test type | required RED condition | required GREEN condition | task | targeted regex |
| --- | --- | --- | --- | --- | --- |
| `T07-BUILD-*` | foundation | test target sees missing build-info API | version API, discovery, warning isolation pass | TASK-07 | `BuildInfo` |
| `T08-CORE-*` | unit | core type/header or behavior absent | identity, status/result, fields/order pass | TASK-08 | `CoreDiagnostics` |
| `T09-DENSE-*` | unit/backend | dense types absent | storage, checking, BLAS values pass | TASK-09 | `DenseMath` |
| `T10-DOM-*` | unit/model | semantic ownership types absent | immutable stable Domain passes | TASK-10 | `DomainModel` |
| `T11-SYN-*` | parser syntax | reader absent | lexical/syntax/source-location cases pass | TASK-11 | `InpSyntax` |
| `T12-MAP-*` | parser semantic | mapper absent | complete positive/negative inventory passes | TASK-12 | `InpDomainMapping` |
| `T13-MODEL-*` | unit/analysis | active view absent | stable non-copy view passes | TASK-13 | `AnalysisModel` |
| `T14-DOF-*` | unit/FEM | numbering/maps absent | DOF, constraint, scatter, pattern pass | TASK-14 | `DofManager` |
| `T15-STATE-*` | unit/state | records/state absent | exact V0 ownership/allocation passes | TASK-15 | `AnalysisState` |
| `T16-BEAM-*` | formulation/analytical | kernel absent or reviewed invariant fails | all NR-T01 through NR-T08 element criteria pass | TASK-16 | `EulerBeam3D` |
| `T17-PFOR-*` | adapter | parallel boundary absent | serial/TBB semantic equivalence passes | TASK-17 | `ParallelFor` |
| `T18-SPARSE-*` | unit/assembly | CSR/reducer absent | canonical byte-identical CSR passes | TASK-18 | `SparseAssembly` |
| `T19-CONSTRAINT-*` | unit/constraints | partition absent | exact blocks and nonzero reconstruction pass | TASK-19 | `EssentialConstraints` |
| `T20-PARDISO-*` | backend/solver | solver absent | SPD, repeated RHS, failure diagnostics pass | TASK-20 | `MklPardisoSolver` |
| `T21-LOAD-*` | unit/assembly | load/RHS assembler absent | nodal load and `Ff-Kfc*dc` pass | TASK-21 | `LoadAssembly` |
| `T22-RECOVERY-*` | unit/results | recovery absent | residual/end/Gauss/stress/station rules pass | TASK-22 | `ResultRecovery` |
| `T23-HDF5-*` | I/O | writer/schema absent | exact schema and atomicity pass | TASK-23 | `Hdf5ResultsWriter` |
| `T24-ORCH-*`, `T24-CLI-*` | integration | lifecycle/app absent | exact stage/CLI/HDF5 path passes | TASK-24 | `LinearStaticCli` |
| `T24-REF-*` | reference-contract | comparator absent | fail-fast row policy/tolerance/report pass | TASK-24 | `ReferenceComparisonContract` |
| `T24-B33-*` | end-to-end reference | approved run/comparison absent | HDF5 and deterministic JSON are generated, all rows pass | TASK-24 | `B33ReferenceComparison` |
Every implementation report RED entry must show a nonzero exit and the expected missing API or failed behavior. A configure/environment failure is not acceptable RED evidence. Every GREEN entry must show the same targeted regex at exit 0 after the minimum implementation.
## CMake and CTest Plan
- Root project: C++17 required, extensions off, `enable_testing()`, dependencies loaded from `cmake/FesaDependencies.cmake`.
- Production library: `fesa_solver` static library. Apply `/W4 /WX` only when `MSVC`; never propagate it to GoogleTest, oneMKL, oneTBB, or HDF5 targets.
- Application: target may be internally named `fesa_app`, but `OUTPUT_NAME fesa` is mandatory so Debug emits `fesa.exe`.
- Tests: `fesa_unit_tests`, `fesa_integration_tests`, and `fesa_reference_tests` are GoogleTest executables. Custom target `fesa_tests` depends on all currently defined test executables so every Step's prescribed build command remains stable.
- Discovery: use `gtest_discover_tests`; every discovered test carries `linear-static-3d-euler-beam` plus one of `unit`, `parser`, `io`, `integration`, or `reference` as appropriate. The exact suite names in the TDD plan preserve targeted CTest regexes.
- Reference working directory: repository root so legacy relative paths remain exact; generated files go only under `.harness/build/reference/cantilever-beam-b33/`.
- Dependency configuration is explicit and local; do not fetch or vendor dependencies and do not hardcode `C:/git/googletest` as a CMake default.
- Harness auto-detection is used because `.harness/config.json` is absent.
Baseline commands required by the project contract are:
```powershell
cmake -S . -B .harness/build -A x64
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
The executable phase commands add the approved local dependency cache variables exactly as shown in each task. At least one test must be present in CTest JSON at every completed implementation Step.
Public dependency scans are additional Step evidence:
```powershell
$denseLeaks = rg -n "mkl\.h|MKL_INT|CBLAS_" include/fesa
if ($LASTEXITCODE -eq 0) { throw "MKL API leaked into public headers:`n$denseLeaks" }
$pardisoLeaks = rg -n "mkl\.h|MKL_INT|pardiso" include/fesa
if ($LASTEXITCODE -eq 0) { throw "PARDISO API leaked into public headers:`n$pardisoLeaks" }
$tbbLeaks = rg -n "oneapi/tbb|tbb/" include/fesa
if ($LASTEXITCODE -eq 0) { throw "oneTBB API leaked into public headers:`n$tbbLeaks" }
$hdf5Leaks = rg -n "H5[A-Z_a-z0-9]*|hid_t" include/fesa
if ($LASTEXITCODE -eq 0) { throw "HDF5 API leaked into public headers:`n$hdf5Leaks" }
```
## Acceptance Traceability Matrix
| requirement | implementation task | GoogleTest evidence | reference/acceptance evidence |
| --- | --- | --- | --- |
| `FESA-REQ-LS3DEB-001` | TASK-12, TASK-13, TASK-24 | `T12-MAP-004`, `T13-MODEL-003`, `T24-CLI-002` | single step runs; second step structured failure |
| `FESA-REQ-LS3DEB-002` | TASK-12, TASK-16, TASK-24 | `T12-MAP-004`, `T16-BEAM-006`, `T24-ORCH-002` | only straight prismatic small-linear B33 reaches solve |
| `FESA-REQ-LS3DEB-003` | TASK-14, TASK-15, TASK-23 | `T14-DOF-001`, `T15-STATE-001`, `T23-HDF5-001` | exact six-component nodal order |
| `FESA-REQ-LS3DEB-004` | TASK-16, TASK-22 | `T16-BEAM-006`, `T22-RECOVERY-004` | four analytical modes at relative `1e-9` |
| `FESA-REQ-LS3DEB-005` | TASK-12, TASK-24 | `T12-MAP-001`, `T24-B33-001` | B33 semantic object and artifact input precheck |
| `FESA-REQ-LS3DEB-006` | TASK-12 | `T12-MAP-004` | exact `unsupported-element-formulation` |
| `FESA-REQ-LS3DEB-007` | TASK-12, TASK-14, TASK-19, TASK-21 | `T12-MAP-001`, `T14-DOF-002`, `T19-CONSTRAINT-003`, `T21-LOAD-003` | DOF 1..6 and nonzero `dc` residual `1e-10` |
| `FESA-REQ-LS3DEB-008` | TASK-12, TASK-16 | `T12-MAP-005`, `T16-BEAM-005` | normalized `1e-12` kernel; `*DLOAD` rejected |
| `FESA-REQ-LS3DEB-009` | TASK-12 | `T12-MAP-001` | positive coverage for exact keyword inventory |
| `FESA-REQ-LS3DEB-010` | TASK-11, TASK-12 | `T11-SYN-001`, `T11-SYN-002`, `T12-MAP-001` | case-insensitive names/comments and raw identity |
| `FESA-REQ-LS3DEB-011` | TASK-12, TASK-14, TASK-21 | `T12-MAP-001`, `T12-MAP-004`, `T14-DOF-002`, `T21-LOAD-001` | exact row grammar and deterministic target expansion |
| `FESA-REQ-LS3DEB-012` | TASK-12, TASK-16 | `T12-MAP-001`, `T16-BEAM-004`, `T16-BEAM-007` | exact section/axis map, transform `1e-12` |
| `FESA-REQ-LS3DEB-013` | TASK-12, TASK-16 | `T12-MAP-004`, `T16-BEAM-007` | exact `E,nu`, derived positive `G`, positive properties |
| `FESA-REQ-LS3DEB-014` | TASK-12, TASK-16 | `T12-MAP-004`, `T16-BEAM-007` | both exact scale-aware thresholds |
| `FESA-REQ-LS3DEB-015` | TASK-10, TASK-12, TASK-23 | `T10-DOM-001`, `T12-MAP-002`, `T23-HDF5-001` | source/internal identity round-trip |
| `FESA-REQ-LS3DEB-016` | TASK-10, TASK-12 | `T10-DOM-003`, `T12-MAP-002` | same-part instances remain distinct |
| `FESA-REQ-LS3DEB-017` | TASK-12 | `T12-MAP-004` | exact `unsupported-instance-transform` |
| `FESA-REQ-LS3DEB-018` | TASK-12 | `T12-MAP-004` | nested/dependent semantics rejected |
| `FESA-REQ-LS3DEB-019` | TASK-12, TASK-23 | `T12-MAP-003`, `T23-HDF5-003` | exact warning no-op allowlist retained in diagnostics |
| `FESA-REQ-LS3DEB-020` | TASK-12, TASK-23, TASK-24 | `T12-MAP-004`, `T23-HDF5-002`, `T24-CLI-003` | unknown model keyword fails; mandatory output unchanged |
| `FESA-REQ-LS3DEB-021` | TASK-10, TASK-13 | `T10-DOM-002`, `T13-MODEL-002` | immutable Domain, non-copy active view |
| `FESA-REQ-LS3DEB-022` | TASK-14 | `T14-DOF-001`, `T14-DOF-003`, `T14-DOF-004` | sole equation/scatter/pattern ownership |
| `FESA-REQ-LS3DEB-023` | TASK-15, TASK-23 | `T15-STATE-001`, `T15-STATE-002`, `T23-HDF5-001` | exact required state connected to output; excluded state absent |
| `FESA-REQ-LS3DEB-024` | TASK-17, TASK-18 | `T17-PFOR-002`, `T18-SPARSE-004` | stable element-local work and deterministic CSR `1e-12` |
| `FESA-REQ-LS3DEB-025` | TASK-09, TASK-17, TASK-18, TASK-20, TASK-23 | `T09-DENSE-001`, `T09-DENSE-002`, `T17-PFOR-002`, `T18-SPARSE-001`, `T20-PARDISO-001`, `T23-HDF5-001` | storage contracts plus no-leak scans |
| `FESA-REQ-LS3DEB-026` | TASK-20, TASK-24 | `T20-PARDISO-002`, `T24-ORCH-001` | exact factorize-before-load event trace |
| `FESA-REQ-LS3DEB-027` | TASK-19, TASK-21, TASK-22 | `T19-CONSTRAINT-003`, `T21-LOAD-003`, `T22-RECOVERY-001` | exact RHS, full reconstruction, residual reaction |
| `FESA-REQ-LS3DEB-028` | TASK-23, TASK-24 | `T23-HDF5-004`, `T23-HDF5-005`, `T24-CLI-001` | authoritative HDF5 and atomic failure/success |
| `FESA-REQ-LS3DEB-029` | TASK-23 | `T23-HDF5-001` | every exact schema-v0 path; generalized-resultant sibling included |
| `FESA-REQ-LS3DEB-030` | TASK-07, TASK-10, TASK-23, TASK-24 | `T07-BUILD-001`, `T10-DOM-001`, `T23-HDF5-001`, `T24-B33-001` | metadata, stable identity, ordinary label, external SI provenance |
| `FESA-REQ-LS3DEB-031` | TASK-15, TASK-16, TASK-22, TASK-23 | `T15-STATE-002`, `T16-BEAM-006`, `T22-RECOVERY-003`, `T23-HDF5-001` | exact components/locations independent of requests |
| `FESA-REQ-LS3DEB-032` | TASK-16, TASK-22, TASK-23, TASK-24 | `T16-BEAM-008`, `T22-RECOVERY-005`, `T23-HDF5-003`, `T24-B33-001` | axial `S11`; no shear; reference stress explicit N/A |
| `FESA-REQ-LS3DEB-033` | TASK-08, TASK-24 | `T08-CORE-002`, `T24-CLI-001`, `T24-CLI-002` | exact CLI forms/codes/ordered diagnostic fields |
| `FESA-REQ-LS3DEB-034` | TASK-07 through TASK-24 | every `T07-*` through `T24-*` group | per-Step report RED/GREEN/VERIFY; discovery nonzero; `/W4 /WX` |
| `FESA-REQ-LS3DEB-035` | TASK-16, TASK-18, TASK-19, TASK-20, TASK-22 | `T16-BEAM-001` through `010`, `T18-SPARSE-004`, `T19-CONSTRAINT-003`, `T20-PARDISO-001`, `T20-PARDISO-006`, `T22-RECOVERY-002` | exact `1e-12`, `1e-10`, `1e-9` criteria and NR-T01..T11 coverage |
| `FESA-REQ-LS3DEB-036` | TASK-24 | `T24-REF-002`, `T24-B33-001` | Abaqus-only component scale and exact mixed formula |
| `FESA-REQ-LS3DEB-037` | TASK-24 | `T24-REF-002`, `T24-B33-001` | exact SI floors and zero-scale case |
| `FESA-REQ-LS3DEB-038` | TASK-24 | `T24-REF-001`, `T24-REF-002` | missing/extra/duplicate/nonfinite/schema/identity fail first; no clamp/drop |
| `FESA-REQ-LS3DEB-039` | TASK-24 | `T24-REF-003`, `T24-B33-001` | every row plus max absolute/normalized/RMS/norm/worst metrics |
| `FESA-REQ-LS3DEB-040` | TASK-11, TASK-24 | `T11-SYN-004`, `T24-REF-001`, `T24-B33-001` | exact four paths and `git diff --exit-code -- reference/` |
| `FESA-REQ-LS3DEB-041` | TASK-24 | `T24-REF-001`, `T24-B33-001` | four files, B33, exact headers, unique finite rows before compare |
| `FESA-REQ-LS3DEB-042` | TASK-22, TASK-24 | `T22-RECOVERY-006`, `T24-REF-004`, `T24-B33-001` | exact component mapping/station eligibility/no-average |
| `FESA-REQ-LS3DEB-043` | TASK-24 and Steps 25-28 gates | `T24-ORCH-001`, `T24-REF-003`, `T24-B33-001` | Step 25 build pass precedes Step 26 rerun; JSON carries Step 27 physics evidence |
| `FESA-REQ-LS3DEB-044` | TASK-12, TASK-16, TASK-24 | `T12-MAP-005`, `T16-BEAM-005`, `T24-REF-001` | no reference solver/artifact mutation and no out-of-scope support claim |
## Implementation Report Evidence Contract
`docs/linear-static-3d-euler-beam/implementation-report.md` is created in TASK-07 and appended in TASK-08 through TASK-24. It must use this fixed structure for every Step:
```markdown
## Step 16 — euler-beam-element
- task_id: TASK-16
- status: completed
- changed_files: exact repository-relative list
- requirement_ids: exact linked requirement IDs
- test_ids: exact linked test IDs
| stage | exact command | exit_code | expected_or_observed_result | evidence_tail |
| --- | --- | ---: | --- | --- |
| RED | targeted build/test command | nonzero | missing API or named behavior failure | concise compiler/test tail |
| GREEN | targeted build/test command | 0 | named regex passes | passed test/count tail |
| VERIFY-configure | exact CMake configure | 0 | MSVC x64 Debug generated | generator/compiler tail |
| VERIFY-build | exact build command | 0 | no warning under FESA `/W4 /WX` | build tail |
| VERIFY-discovery | CTest JSON discovery | 0 | discovered count at least one | count/regex tail |
| VERIFY-full | full CTest command | 0 | zero failed tests | summary tail |
- contract_checks: public dependency scan, numerical tolerance, ordering, or artifact check used by this Step
- generated_evidence: exact build-relative artifact paths or N/A
- reference_diff: unchanged or N/A; TASK-24 records `git diff --exit-code -- reference/` exit 0
- handoff: exact types/files/tests available to the next Step
```
The actual report repeats this section with each real Step number/name; it must not copy the example values when they do not apply. RED is invalid if failure is caused by a missing dependency, bad generator, stale build cache, or unrelated regression. TASK-24 additionally records `results.h5`, `comparison.json`, matched-row counts, physics-evidence keys, and the unchanged reference diff. Build/Test Executor Step 25 independently records command, exit code, duration, output tail, and failure classification in its own report.
## Correction and Failure Boundaries
- Classify failures as `configure | compile | link | test | reference-comparison | harness | environment | upstream-contract` before editing.
- Correction may change only the source/header/test/CMake files owned by the failing task and must rerun that task's targeted command before full VERIFY.
- Do not correct a failure by changing a requirement, formula/sign, I/O grammar/schema, reference artifact, row identity, component mapping, tolerance coefficient/floor, or gate order.
- Do not regularize a singular PARDISO system, reinterpret B31, ignore transforms, add a fallback beam axis, clamp reference values, drop rows, average endpoint mismatch, or synthesize absent stress/`SF2`/`SF3` reference rows.
- Repeated environment failure is handed to the user; repeated implementation-owned failure is handed to the Correction Agent; any upstream contradiction is handed through the Coordinator Agent without contract edits.
## Downstream Handoff
### Implementation Agent
- Execute TASK-07 through TASK-24 in order; do not pre-create later modules.
- Read this plan and the task's Step file completely, but use approved upstream contract precedence recorded in Readiness resolutions.
- End every Step green with implementation-report evidence and its exact phase-index summary.
### Build/Test Executor Agent
- Re-run the explicit dependency configure, Debug build, feature-label/regex tests, JSON discovery, and full CTest without source changes.
- Confirm MSVC, x64, Debug, nonzero tests, no warnings, and `reference/` unchanged.
### Correction Agent
- Use the failure classification and the task/test trace in the implementation report.
- Apply only a minimal implementation-owned repair; upstream contracts, reference artifacts, and tolerances are immutable.
### Reference Verification Agent
- After Step 25 passes, run the already-built `B33ReferenceComparison` CTest and inspect its existing deterministic `comparison.json`.
- Write the Step 26 report without modifying source, tests, CMake, reference files, matching rules, or tolerances.
### Physics Evaluation Agent
- Consume `comparison.json.physics_evidence` only after Step 26 passes; independently review force/moment equilibrium, reaction sign, displacement direction, symmetry, endpoint consistency, and residual.
## Open Issues
- No issue blocks implementation. The only permitted later escalation is a newly observed environment failure or an actual contradiction between implemented behavior and an approved upstream contract.