Skip to content
Skip to main content
Novel Systems home
Decision log
D-049August 5, 2026

There are two margin floors, and no figure may be published without saying which

Decided

No margin-floor percentage may be written as a literal outside lib/cpq-engine.ts and lib/trade-quoting.ts. A tenth claim rule, margin-floor-figure, fails the build on any that appears, and every surface that names a floor must interpolate one of the two constants and say which business it describes.

Affects: scripts/check-claim-consistency.mjs, app/page.tsx, app/platform/cpq/page.tsx, app/sandbox/page.tsx, lib/constants.ts

What was live and wrong. The homepage metric tile read "50.0% — Margin floor per line — enforced by the engine at the line, the quote, and the approval workflow", stated flatly as a fact about the platform. Three sections below it the CPQ calculator renders the floor for whichever trade is selected, and five of the six profiles carry 28.0%, because commercial bid work against other contractors is not priced like goods manufactured on a bench. A reader who clicked a second tab disproved the headline without leaving the page. Confirmed live by switching to "Commercial Electrical & Assemblies" and watching the lock control change to "Margin floor 28.0%".

Why both numbers are correct. CPQ_CONSTANTS.MARGIN_FLOOR is 0.5 and governs manufactured lines, where wholesale-to-retail is the business model. TRADE_CONSTANTS.MARGIN_FLOOR is 0.28 and governs commercial bid work, where 50% does not win tenders and quoting it costs you the invitation to the next one. The defect was never the numbers. It was a headline asserting one of them universally.

Why the slider was left alone. The backlog described this as "margin locked versus adjustable slider", and that framing is wrong. The sandbox control is coherent: the slider *requests* a target margin between 5% and 60%, the lock toggle *enforces* the price book's floor, and the copy reports held-at-floor, above-floor, or floor-released with the shortfall still named. Fixing a control that works would have left the actual contradiction shipping.

Fixed at the class level, and it paid immediately. The rule found three more instances I had missed reading by hand — the CPQ page metadata, the sandbox page metadata, and the navigation dropdown description in lib/constants.ts. The first two now interpolate the constant and say "manufactured-goods". The third dropped the figure entirely: that string renders in the nav on every route, so a floor named in it is asserted over the whole site, including the pages where it is false.

Why the owner is `CPQ_CONSTANTS` and not `MARGIN_FLOOR`. The canary regex matches export const <owner>, so an object property cannot be an owner — the rule aborted with "MARGIN_FLOOR is not declared" until the containing object was named. A rule that cannot find its owner fails loudly rather than passing blind, which is the behaviour we want.

What would make this wrong: a third price book with a third floor would not change the rule, only widen the allow-list. A single global floor would retire it, and that is a business change, not a copy change.