From the 2026-08-02 full-repo review (finding F-16).
Evidence: OutputDecl::expr holds only scalar or tensor expressions (recipe.h:275-278); the only tensor_to_scalar entry points are residual equations (recipe.h:554-566). Yet the t2s emitter exists and is fully wired (tensor_to_scalar_code_emit.h, LeafCollector handles t2s leaves), and roles::Dissipation (recipe.h:107, expected_rank=0) advertises exactly the use case the output API cannot carry.
Impact: physically common outputs — von Mises stress, dissipation, damage indicators = f(σ, εᵖ) — cannot be declared; users must promote to rank-2 workarounds or post-process outside the material.
Proposal: add_output(std::string, cas::expression_holder<cas::tensor_to_scalar_expression>, Role) mapping to a scalar OutputDecl; CodeEmitPass already owns a t2s pipeline arm. If deliberately out of scope for now, document the restriction on add_output.
From the 2026-08-02 full-repo review (finding F-16).
Evidence:
OutputDecl::exprholds only scalar or tensor expressions (recipe.h:275-278); the only tensor_to_scalar entry points are residual equations (recipe.h:554-566). Yet the t2s emitter exists and is fully wired (tensor_to_scalar_code_emit.h,LeafCollectorhandles t2s leaves), androles::Dissipation(recipe.h:107, expected_rank=0) advertises exactly the use case the output API cannot carry.Impact: physically common outputs — von Mises stress, dissipation, damage indicators = f(σ, εᵖ) — cannot be declared; users must promote to rank-2 workarounds or post-process outside the material.
Proposal:
add_output(std::string, cas::expression_holder<cas::tensor_to_scalar_expression>, Role)mapping to a scalar OutputDecl; CodeEmitPass already owns a t2s pipeline arm. If deliberately out of scope for now, document the restriction onadd_output.