Skip to content

Numeric policy is documented as blanket float-only, but the real policy is tiered #263

Description

@gabrielfrasantos

Severity: medium
Domain: docs / policy
Status: VERIFIED — read + measured against a210d34 on 2026-08-10
Suggested labels: documentation, policy

Summary

AGENTS.md states a flat rule — "New algorithms are float-only … Do NOT
implement Q15/Q31 now"
— but that is not the policy actually in force. Fixed-point is
accepted for simple algorithms; it is only disallowed for large/complex operations, where it
inflates implementation complexity for little gain.

Because the canonical file states the strict version, and ~18 downstream files (agent definitions,
Copilot/Claude instructions, review checklists) copy it verbatim, review tooling actively flags
correct code as a violation
— and the real boundary between "simple enough for Q" and "too large
for Q" is written down nowhere.

Evidence

The canonical rule is unconditional

AGENTS.md:

## Numeric policy — FLOAT-ONLY (current)

- New algorithms are **float-only**. Write generic `template<typename T>`, add
  `static_assert(std::is_floating_point_v<T>, "...")`, and **instantiate/test `float` only**.
- Do **NOT** implement `Q15`/`Q31` now.

But the ROADMAP already encodes the tiered rule correctly

ROADMAP.md:

Numeric-type note. DSP filters and fixed-gain trackers should template all three
types (float, Q15, Q31). Items marked (float-first) involve dynamic range or
iterative conditioning that make fixed-point impractical initially — implement and
validate in float.

This is much closer to the real policy than AGENTS.md is.

And an agent definition already carves out a second exception

.claude/agents/algo-modernizer.md:

Preserve fixed-point. Rows tagged Q/Q* support Q15/Q31. NEVER recommend stripping
is_qnumber, renaming QNumberTypeT where it drops fixed-point, or forcing float-only — that
policy is for NEW algorithms only. QNumberType is not, by itself, a defect.

So there are already two unstated dimensions: new vs legacy, and simple vs complex.

The code follows the tiered rule, not the flat one

$ grep -rl 'Q15\|Q31' numerical --include=*.cpp --include=*.hpp | wc -l
41

numerical/math/Statistics.hpp gates on a Q-aware trait:

static_assert(detail::is_supported_type_v<T>,
    "Statistical functions only support float or QNumber types");

The actual gap

Not "the ROADMAP is wrong" — the ROADMAP is closer to right. The gap is that AGENTS.md
overstates the rule
, and no file defines the simple/complex boundary in reviewable terms.
"Too large" is currently a judgement call that two reviewers will apply differently.

Suggested fix

1. Replace the AGENTS.md numeric policy section with a tiered rule

Draft for editing:

Numeric policy — tiered

Write generic template<typename T>. Which types you instantiate depends on the algorithm:

Tier A — float, Q15, Q31. Bounded dynamic range, no iteration to a tolerance, no
matrix factorisation. Examples: FIR/IIR/biquad/comb/moving-average, fixed-gain trackers
(alpha-beta, complementary), windowing, unit conversions.

Tier B — float only. Add static_assert(std::is_floating_point_v<T>). Any algorithm that
divides by a data-dependent quantity, accumulates products of unbounded magnitude, iterates to a
tolerance, or factorises/inverts a matrix. Examples: Kalman family, DARE/Riccati,
SVD/QR/Cholesky/eigen, optimisation, adaptive filters, ODE solvers.

Legacy algorithms keep the types they already support. Removing Q15/Q31 from an existing
algorithm is a breaking change, not a cleanup.

Adjust the tier boundary to taste — the important part is that it is written down and testable.

2. Propagate to the derived files

The flat rule is replicated in roughly 18 places; all must move together or the contradiction
persists:

Review checklists should ask "is the tier correct for this algorithm?" rather than
"is it float-only?".

3. Tag each algorithm with its tier

Add the tier to each doc/<domain>/<Name>.md so the expected instantiation set is reviewable, and
so the TYPED_TEST question (issue 019) has a definitive answer per algorithm.

Related

  • Issue 019 — TYPED_TEST/Q-number test drift; its resolution depends on this decision.
  • Issue 024 — ROADMAP master list is empty (split out of this issue).

Incidental finding

.claude/agents/algo-modernizer.md references
REVIEW_BACKLOG.md, which does not exist in the repository. The agent cannot run as written.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions