quantities Module — Formula Reconciliation¶
§1 Purpose¶
This document is an independent reconciliation of the quantities module spec
(quantities-spec.md). It was produced in a separate sub-chat from the spec itself, with
access to the spec output but not to the source workbook during the initial pass. Its
purpose is to:
- Apply the two-axis verdict scheme (see PROJECT.md decision #23) to every formula in
the spec, assigning each a
VALIDATEDorCORRECTEDverdict. - Identify discrepancies between the spec's transcription and what a correct implementation of the stated engineering intent would produce.
- Assign provenance status (
SOURCED/EXPERT-JUDGEMENT/BLOCKED) to every parameter. - Produce the divergence fixtures used by the Python test suite to assert that corrected formulas diverge from the spec by the documented amount.
The spec (quantities-spec.md) is the requirements artifact — it records what the
Excel does, bugs included. This document is the judgment layer — it records what the
Python module should do, and why.
§2 Method¶
- The spec was read in full, including the Errors & inconsistencies section (E1–E22) and the Parity fixtures.
- Each formula was assessed against: (a) internal consistency with sibling formulas in the same sheet; (b) the stated engineering intent in the description column; (c) normal practice for the construction technique described.
- Where the spec's transcription was internally consistent with the rest of the sheet,
even if the underlying value was unsourced, the verdict is
VALIDATED— parity is enforced at 0.1%. - Where the formula structure is demonstrably wrong (wrong-row reference, missing
parentheses, decimal-point slip, missing formula, transposed values, wrong geometric
calculation), the verdict is
CORRECTED— the Python module must diverge, a divergence test asserts the expected difference, and the normative basis for the correction is cited. - Findings not captured in the spec's E1–E22 list were flagged for GitHub issues.
- Every parameter was assessed for provenance.
BLOCKEDparameters receive no default and the module raisesValueError— the gap must be audible in the code.
§3 Formula verdicts¶
VALIDATED formulas (parity enforced at 0.1%)¶
These formulas are internally consistent with their stated intent and with sibling rows. The Python implementation must reproduce the Excel output to within 0.1%.
| Row | Item | Formula verified against | Note |
|---|---|---|---|
| 5 | A.III.1 (layer 1) | Internal consistency; D5 formula matches stated layer fractions | E2 (0.21 vs 0.20) reproduced as-is |
| 6 | A.III.1 (layer 2) — materials other than H6/I6 | See §4.2 for transposition verdict | L6, K6, G6 are VALIDATED; H6/I6 are CORRECTED |
| 7 | A.III.2 | Consistent 150 kg/m³ blinding concrete recipe | ✓ |
| 8 | A.III.3 | ml × 1 conversion documented and correct | ✓ |
| 9 | A.III.4 | Canonical 350 kg/m³ recipe with rebar | ✓ |
| 11 | A.IV.1 | Same 350 kg/m³ recipe as row 9 | ✓ |
| 12 | A.IV.2 | Same 350 kg/m³ recipe as row 9 | ✓ |
| 14 | A.V.1 | Adobe wall formula internally consistent | ✓ |
| 15 | A.V.2 | BBSC header row; rock-only model preserved | ✓ parity; but see §4.5 on BBSC |
| 16 | K16 | E3 (wrong-row reference) — reproduce E3 as written | K16 = D15 × ... |
| 17 | A.V.4 | 38 cm wall with BBSC | ✓ |
| 18 | A.V.5 | 38 cm wall, no BBSC | ✓ |
| 19 | A.V.6 | 20 cm wall | ✓ |
| 21 | A.VI.1 | Arch, correct parentheses | ✓ |
| 22 | A.VI.2 | Arch, correct parentheses | ✓ |
| 23 | A.VI.3 | Arch with gravel footing term | ✓ |
| 24 | J24, K24 | E4 (missing outer parentheses) — reproduce E4 as written | |
| 25 | A.VI.4 (row 25) | Correctly parenthesised | ✓ |
| 26 | A.VI.5 | Correctly parenthesised | ✓ |
| 27 | A.VI.6 | Large opening, same pattern | ✓ |
| 32 | K32 | E6 (0.043 vs 0.0043) — reproduce E6 as written | 7.6× water overstatement; preserved |
| 33 | A.VIII.2 | Correct coefficient | ✓ |
| 35 | A.IX.1 | Roof waterproofing slope | ✓ |
| 36 | U36 | E9 (hardcoded 289.15) — reproduce E9 as written | Negligible drift |
| 38 | J38, K38 | E5 (J38 missing outer parens, K38 correct) — reproduce E5 as written | |
| 41 | B.I.1 | 16 mm cement plaster; complete formula | ✓ |
| 42 | B.I.2 | Earth-sand-gravel-tar roof coating (E14: gravel silently absent) — reproduce E14 | |
| 43 | B.I.3 | 16 mm cement plaster; complete | ✓ |
| 44 | B.I.4 | Earth-sand plaster on vaults | ✓ |
| 45 | B.I.5 | E13 (missing cement) — reproduce E13 as written | L45 formula absent |
| 46 | B.I.6 | E13 same — reproduce E13 | L46 absent |
| 47 | B.I.7 | E13 same — reproduce E13 | L47 absent |
| 50 | B.II.1.a | Compacted earth fill, correct | ✓ |
| 53 | H53 | E10 (width 0.45 vs 0.35) — reproduce E10 as written | |
| 53 | I53, K53, L53 | Correct width 0.35 | ✓ |
| 55 | B.II.3.a | 250 kg/m³ window-sill concrete; correct | ✓ |
| 57 | B.II.4.a | Slope earth, correct | ✓ |
| 60 | N60, O60 | E11 (0.2×0.9 perimeter) — reproduce E11 as written | |
| 61 | B.III.1.b | Single-leaf louvered window; correct | ✓ |
| 63 | N63, O63 | E20 (3.2 vs 3.12 m) — reproduce E20 | |
| 64 | N64 | E12 (2.7 and 2.3 factors) — reproduce E12 as written | |
| 64 | O64 | Uses correct 2.79 | ✓ |
| 65 | B.III.2.c | Metal partition door; correct | ✓ |
| 67 | B.III.3.a | Metal gutter; correct | ✓ |
| 69 | B.IV.1 | Wall paint coverage correct | ✓ |
| 70 | B.IV.2 | Vault paint coverage correct | ✓ |
| 71 | B.IV.3 | Antirust paint; flat-rate per unit | ✓ |
| 72 | B.IV.4 | Tyrolean plaster; density-conversion formula correct | ✓ |
| 74 | B.V.1 | Floor tiling + 10% waste | ✓ |
| 75 | B.V.2 | Tile skirting | ✓ |
| 76 | B.V.3 | Faience tiling | ✓ |
CORRECTED formulas (Python must diverge; divergence tests in backend/tests/fixtures/quantities_divergence.py)¶
| ID | Row / col | Correction | Normative basis | Divergence from spec |
|---|---|---|---|---|
| C1 | H6, I6 | Sand and gravel columns are transposed: H6 should be sand (= D6 × 0.53 × 0.21), I6 should be gravel (= D6 × 0.75 × 0.21). See §4.2. | Normal concrete-mix practice: gravel > sand by volume in any standard mix design. Marco confirmed: H6 cached value = 4.34 m³ (labelled gravel), I6 = 6.15 m³ (labelled sand) — sand exceeds gravel, which is not physically possible in a w/c-ratio-consistent mix. | Gravel total ↑ by (D6 × (0.75−0.53) × 0.21) = 1.804 m³; Sand total ↓ by same |
| C2 | J29, J30 | Vault arc length formula uses π × span (full circumference for a circle of radius = span). Correct half-arc is π × span/2. See §4.3. |
Geometry: a Nubian vault is a semicylinder; its wall cross-section brick arc is a half-circle of radius = span/2. Arc length = π × r = π × span/2, not π × span. | Earth total ↓ by ~78.9 m³ (−9.5% of project total 830.5 m³) |
| C3 | M51 | Rebar formula entirely absent from row 51 ("Reinforced concrete slab, 300 kg/m³"). See §4.1. | EN 15804+A2 §6.3.3: "all significant materials and components shall be included." A 100 mm RC slab without rebar is structurally incomplete. Normative rebar density requires Chiwara attribution — see §6, BLOCKED parameter. | Steel Rebars total understated. Magnitude depends on BLOCKED mesh spec. |
| C4 | T60, T63, T64 | Glass not multiplied by window count D. See §4.4. |
Quantity principle: a formula applying to N identical units must be scaled by N. The current formulas compute glass for one window type, regardless of count. |
Glass total understated by factor ≈ (Σ D_i - 1) across three glass rows. See §4.4 for exact values. |
| C5 | U36 | Anti-termite treatment quantified off roof area (D35 = 289.15 m²). See §4.5. | EN 15804+A2 scope: treatment refers to foundation zone. Correct metric is foundation contact area or treated perimeter, not roof area. Requires Chiwara attribution for the correct reference area — see §6, EXPERT-JUDGEMENT. | Direction: treatment volume overstated if foundation area < roof area; understated if foundation perimeter × penetration depth > 5 L/m² × roof. |
§4 Correction detail¶
§4.1 — Row 51: Missing rebar formula (+163% project steel rebar, BLOCKED)¶
Finding: B.II.1.b (row 51) is a 100 mm reinforced concrete slab at 300 kg/m³. The spec
transcribes formulas for Gravel, Sand, Water, and Cement but no Steel Rebars formula (column M).
The project total for Steel Rebars (1330.6 kg) derives entirely from rows 9, 11, and 12
(350 kg/m³ isolated footings and RC columns/beams).
Engineering assessment: A 100 mm structural slab without reinforcement is not compliant with any standard structural concrete design. Rebar (or mesh) is always present. The omission is a missing formula, not a deliberate choice — the spec's Errors table (E13) already identifies the analogous omission of cement for plastering rows 45/46/47 as an error of the same type.
Magnitude: If the same rebar density as the 350 kg/m³ recipe (100 kg/m³) were applied
naively: 21.702 m³ × 100 kg/m³ = 2170.2 kg. That would increase total Steel Rebars from
1330.6 kg to 3500.8 kg, an increase of 163%. However, mesh for a 100 mm slab is
specified differently from structural rebar — the correct density is a BLOCKED parameter
requiring Chiwara team attribution. See §6.
Verdict: CORRECTED. The Python module must include a rebar/mesh formula for row 51.
The parameter is BLOCKED pending §6 attribution. The module raises ValueError until the
mesh spec is supplied.
Divergence test: See backend/tests/fixtures/quantities_divergence.py::test_c1_slab_rebar_blocked.
§4.2 — Row 6: Sand/gravel transposition (confirmed by Marco)¶
Finding: Row 6 (A.III.1, second layer — 250 kg/m³ cyclopean concrete) has:
- H6 = D6 × 0.53 × 0.21 (column H = Gravel, factor 0.53)
- I6 = D6 × 0.75 × 0.21 (column I = Sand, factor 0.75)
Marco confirmed the cached cell values: H6 = 4.34 m³ (gravel), I6 = 6.15 m³ (sand). Sand (6.15 m³) exceeds gravel (4.34 m³), which is anomalous: in any standard concrete mix (including the other two mix designs in this sheet — 350 kg/m³ rows 9/11/12 and 300 kg/m³ row 51), gravel volume exceeds sand volume. The 250 kg/m³ mix design in rows 55 (window sills) uses H=0.75 and I=0.53 — the opposite assignment from row 6. This confirms that columns H and I are transposed in row 6.
Correct formulas:
- H6 = D6 × 0.75 × 0.21 (gravel at the larger 250 kg/m³ proportion)
- I6 = D6 × 0.53 × 0.21 (sand at the smaller proportion)
Magnitude:
- Gravel change: D6 × (0.75 − 0.53) × 0.21 = 39.037 × 0.0462 = 1.804 m³ (increase)
- Sand change: same magnitude, decrease
- Project-level impact: Gravel total 31.06 → 32.86 m³ (+5.8%), Sand total 56.05 → 54.25 m³ (−3.2%)
Normative basis: Internal consistency (sibling row 55 uses 0.75 gravel / 0.53 sand for the same 250 kg/m³ design); confirmed by Marco.
Divergence test: test_c2_row6_sand_gravel_transposition.
§4.3 — Nubian vault arc: π × span vs π × span/2 (−9.5% project earth)¶
Finding: Row 29 (A.VII.1): J29 = 18.6 × (3.14 × 3.3) × 0.25.
Row 30 (A.VII.2): J30 = D30 × (2.6 × 3.14) × 0.25.
The spec annotates this as "semicircle arc length for a 3.3 m-radius vault (π·r)". But:
- A Nubian vault with span
sis a semicylinder. The brick course arc is a half-circle whose diameter = span. Radius = span/2. Arc length = π × (span/2). - The formulas use
π × span(i.e. π × diameter), which equals the full circumference of the semicircle's circle — twice the half-arc.
This doubles the earth volume computed for both vault rows compared to the physically correct half-arc.
Correct formulas:
- J29 = D29 × (3.14 × 3.3/2) × 0.25 = D29 × 5.181 × 0.25
- J30 = D30 × (3.14 × 2.6/2) × 0.25 = D30 × 4.082 × 0.25
Magnitude (using spec quantities D29 = 18.6 ml, D30 = 53.4 ml):
- Row 29 spec: 18.6 × 10.362 × 0.25 = 48.18 m³. Corrected: 18.6 × 5.181 × 0.25 = 24.09 m³. Difference: −24.09 m³.
- Row 30 spec: 53.4 × 8.164 × 0.25 = 108.99 m³. Corrected: 53.4 × 4.082 × 0.25 = 54.50 m³. Difference: −54.49 m³.
- Total earth decrease: −78.58 m³ out of spec total 830.49 m³ = −9.5%.
Note: K29 (J29 × 0.2585) and K30 (as written: D30 × 0.2585, which is E8) also change.
K29 is derived from J29 so it follows automatically. K30's E8 bug is preserved separately.
Normative basis: Geometry. A half-circle of span s has radius s/2; the arc subtended
by a semicircle is π × r = π × s/2.
Divergence test: test_c3_vault_arc_half_circle.
§4.4 — Glass not multiplied by window count¶
Finding: Rows 60, 63, 64 each have a glass formula (T60, T63, T64) that computes
the glass volume for a single rounded fanlight — not scaled by the line's unit count D.
T60 = 1/2 × 0.45² × π × 2 × 0.004(hardcoded constant, not scaled by D60 = 17)T63 = 1/2 × 0.6² × π × 2 × 0.004(not scaled by D63 = 2)T64 = 1/2 × 0.45² × π × 2 × 0.004(not scaled by D64 = 2)
The spec classifies this under Open Questions (OQ6) and notes "glass is being counted per distinct opening type, not per unit count D". The reconciliation verdict is unambiguous: a BoQ line for 17 windows must contribute 17 windows' worth of material, not 1.
Correct formulas:
- T60 = D60 × (1/2 × 0.45² × π × 2 × 0.004) = 17 × 0.001272 = 0.021634 m³
- T63 = D63 × (1/2 × 0.60² × π × 2 × 0.004) = 2 × 0.002262 = 0.004524 m³
- T64 = D64 × (1/2 × 0.45² × π × 2 × 0.004) = 2 × 0.001272 = 0.002544 m³
Magnitude:
- Spec Glass total = 0.0096084 m³ (3 hardcoded values summed)
- Corrected Glass total = 0.021634 + 0.004524 + 0.002544 = 0.028702 m³
- Difference: +199% (≈ 3×)
Normative basis: Basic quantity principle — a formula for N identical items is scaled by N.
Divergence test: test_c4_glass_scaled_by_count.
§4.5 — Anti-termite treatment referenced to roof area¶
Finding: U36 = 1 × 5 × 289.15, where 289.15 is a rounded copy of D35 (roof
waterproofing area). The rate 5 L/m² is stated in the sheet. But anti-termite treatment
is applied to the foundation zone (soil under and around the slab), not to the roof.
Using roof area as the proxy for foundation area is methodologically unsound.
Verdict: CORRECTED. Requires Chiwara team attribution for the correct reference area
(foundation plan area, foundation perimeter × treatment depth, or a project-specific
survey). Until attributed, the parameter is EXPERT-JUDGEMENT (pending) — see §6.
Divergence: Direction and magnitude depend on the ratio of foundation contact area to roof area (289.15 m²). If foundation plan area ≈ roof area (common in compact school layouts), the numeric divergence may be small. The correction is methodological, not primarily numeric.
Divergence test: test_c5_anti_termite_area_attribution (flagged XFAIL pending §6
resolution — the test exists but cannot pass until the reference area is attributed).
§5 Summary verdict table¶
| Axis | Status | Count | Action |
|---|---|---|---|
| VALIDATED | Parity ≤ 0.1% enforced | ~50 formula cells | Regression test against spec Fixture 4 |
| CORRECTED | Python diverges; divergence test asserts expected Δ | 5 corrections (C1–C5) | quantities_divergence.py |
| SOURCED (parameter) | Normative citation available | 0 in workbook (all are UNKNOWN in the source) | Phase 1 Step 2: attribution sprint |
| EXPERT-JUDGEMENT (parameter) | Chiwara practitioner data, permitted with attribution | Multiple (anti-termite area, steel density for carpentry, OMPU source, sand density scope) | See §6 |
| BLOCKED (parameter) | Neither normative source nor attributed data | 2: slab mesh spec; BBSC composition | Module raises ValueError — no placeholder |
§6 Attribution stubs (extracted to chiwara-attribution-requests.md)¶
The full text of the attribution requests is in
docs/methodology/chiwara-attribution-requests.md. Summary:
| Parameter | Status | Owner | Blocker? |
|---|---|---|---|
| Slab mesh spec (row 51 rebar density for 300 kg/m³ slab) | BLOCKED |
Chiwara / site engineer | Yes — module raises until resolved |
| BBSC composition (binder silently missing from LCA) | BLOCKED |
Chiwara / material supplier | Yes — BBSC contributes only rock in current model; LCA is incomplete |
| OMPU reference document identity | EXPERT-JUDGEMENT (pending) |
Chiwara / Adama | No — model runs with PROVENANCE UNKNOWN, but not defensible for ISO 14071 review |
| Anti-termite reference area | EXPERT-JUDGEMENT (pending) |
Chiwara / site engineer | No — model runs with roof area proxy; divergence test XFAIL |
| Steel density for fenestration (columns N, O) | EXPERT-JUDGEMENT (pending) |
Chiwara / structural engineer | No — volume-basis only until attributed |
| Sand density 1600 kg/m³ scope | EXPERT-JUDGEMENT (pending) |
Chiwara / Adama | No — used only in row 72; question is whether it applies elsewhere |
| OMPU provenance for K29 water:earth ratio (0.2585) | EXPERT-JUDGEMENT (pending) |
Chiwara | No |
§7 Divergence fixture location¶
backend/tests/fixtures/quantities_divergence.py
This file contains:
- SPEC_PROJECT_TOTALS — the spec-faithful aggregate (Fixture 4 from the spec, as Excel
computes it, bugs preserved).
- CORRECTED_PROJECT_TOTALS — the corrected aggregate (after applying C1–C4; C5 deferred).
- Five pytest functions (test_c1_* through test_c5_*) asserting the expected divergence.
These tests do not run the Python quantities module (which does not exist yet). They
assert the expected relationship between spec and corrected values, so the implementation
team knows exactly what to target. Once the module is implemented, the regression tests
in backend/tests/regression/ will use the corrected values.