# Quantity Specialist **specialist_id:** `quantity` **trigger_gates:** `has_quantity`, `is_math` --- ## Responsibility The quantity specialist extracts numeric values, attaches QuantityFacets to quantity objects, and emits arithmetic and comparison constraints. When arithmetic can be resolved deterministically, it resolves it. When resolution requires a solver, it emits a structured constraint for the resolver. --- ## Manifest ``` declared_facet_kinds: - quantity declared_constraint_types: - quantity_equals - quantity_sum - quantity_difference - quantity_product - quantity_quotient - quantity_greater - quantity_less - quantity_at_least - quantity_at_most - quantity_bound budget_caps: max_objects_proposed: 6 max_facets_emitted: 6 max_constraints_emitted: 10 max_merges: 0 max_splits: 0 ``` --- ## Output: QuantityFacet Attach to any object of kind `quantity`. ``` QuantityFacet fields used: - value: number or symbolic expression - unit: string (apples, dollars, meters, etc.) - is_exact: true/false - derived_from_refs: quantity object IDs this was computed from ``` --- ## Output: Constraints ### `quantity_equals(Q_result, expression)` Emit when a quantity is defined as equal to an expression. ``` { "constraint_type": "quantity_equals", "argument_refs": ["Q_alice_final", "Q_expr_5_minus_2"], "expression": "quantity(Q_alice_final) = quantity(Q1) - quantity(Q2)", "strength": "hard" } ``` ### `quantity_difference(Q_result, Q_minuend, Q_subtrahend)` Preferred form when the specific operation is subtraction. ``` argument_refs order: [result, minuend, subtrahend] ``` ### `quantity_sum(Q_result, Q_addend1, Q_addend2, ...)` Result equals the sum of all argument quantities. ### `quantity_greater(Q_a, Q_b)` Q_a > Q_b. ### `quantity_less(Q_a, Q_b)` Q_a < Q_b. --- ## Arithmetic resolution When all inputs to an arithmetic constraint are exact numeric values, the quantity specialist SHOULD resolve the arithmetic inline and set the result quantity's `value` directly. ``` if quantity_difference(Q_result, Q1, Q2): if Q1.value is exact numeric AND Q2.value is exact numeric: Q_result.value = Q1.value - Q2.value Q_result.is_exact = true mark constraint as resolved else: emit constraint with status = unresolved resolver handles it ``` This avoids unnecessary round-trips through the resolver for simple arithmetic. --- ## Unit tracking Units must be tracked and propagated. Emitting a `quantity_difference` constraint without units is not sufficient — the result unit must be declared or inferred. Rules: - Same unit on both operands: result inherits unit - Different units on operands: emit a `quantity_bound` constraint marking the result as unit-ambiguous until a converter is applied - Unitless operands: result is unitless --- ## Contract test requirements - Given `Alice had 5 apples. She gave Bob 2 apples.`: - Must emit Q1 with value=5, unit="apples" - Must emit Q2 with value=2, unit="apples" - Must emit `quantity_difference(Q_alice_final, Q1, Q2)` or `quantity_equals(Q_alice_final, "5-2")` - Must set Q_alice_final.value = 3 (inline resolution) - Must not emit temporal or entity constraints - All quantity facets must have `unit` set or explicitly `"unitless"` - All emitted constraints must have `source_module: quantity`