cometric 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cometric-0.3.0/.hypothesis/constants/1a54c0e5b66b34fa +4 -0
- cometric-0.3.0/.hypothesis/constants/2616f13a910320c7 +4 -0
- cometric-0.3.0/.hypothesis/constants/284cdb085a69e559 +4 -0
- cometric-0.3.0/.hypothesis/constants/52563cc61b61afeb +4 -0
- cometric-0.3.0/.hypothesis/constants/8291cdcd8414a40b +4 -0
- cometric-0.3.0/.hypothesis/constants/8408e47180d8b9c1 +4 -0
- cometric-0.3.0/.hypothesis/constants/85a66397c5e4b867 +4 -0
- cometric-0.3.0/.hypothesis/constants/a402bbad3ba0ac69 +4 -0
- cometric-0.3.0/.hypothesis/constants/e275ad1f9cb17aaf +4 -0
- cometric-0.3.0/.hypothesis/constants/ed391256aab33efd +4 -0
- {cometric-0.2.0 → cometric-0.3.0}/CHANGELOG.md +29 -0
- {cometric-0.2.0 → cometric-0.3.0}/PKG-INFO +4 -3
- {cometric-0.2.0 → cometric-0.3.0}/README.md +3 -2
- {cometric-0.2.0 → cometric-0.3.0}/docs/COMETRIC_SPEC_v0.3.md +38 -9
- cometric-0.3.0/docs/PATTERNS.md +56 -0
- {cometric-0.2.0 → cometric-0.3.0}/docs/STATUS.md +1 -1
- {cometric-0.2.0 → cometric-0.3.0}/pyproject.toml +1 -1
- cometric-0.3.0/scripts/build_alsp.py +414 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/api.py +554 -73
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/engine.py +315 -44
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/enums.py +11 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/issues.py +6 -2
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/models.py +45 -7
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/predicates.py +44 -5
- cometric-0.3.0/src/cometric/core/present.py +81 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/quantities.py +11 -2
- cometric-0.3.0/src/cometric/core/quickstart.py +174 -0
- cometric-0.3.0/src/cometric/core/schema.py +201 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/validation.py +59 -1
- cometric-0.3.0/src/cometric/examples/pattern_partial_and_hours.json +169 -0
- cometric-0.3.0/src/cometric/examples/pattern_termination.json +297 -0
- cometric-0.3.0/src/cometric/examples/pattern_tiered_minimum.json +295 -0
- cometric-0.3.0/src/cometric/examples/pattern_transition_credit.json +310 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/mcp/server.py +97 -23
- cometric-0.3.0/src/cometric/packs/alsp/templates/tiered_units_annual_minimum.json +298 -0
- cometric-0.3.0/tests/test_llm_feedback.py +210 -0
- cometric-0.3.0/tests/test_patterns.py +46 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/test_reproducibility_and_search.py +3 -1
- cometric-0.3.0/tests/test_search_and_context.py +171 -0
- cometric-0.3.0/tests/test_termination.py +142 -0
- {cometric-0.2.0 → cometric-0.3.0}/uv.lock +1 -1
- cometric-0.2.0/.hypothesis/constants/1b52f94ff1d6e987 +0 -4
- cometric-0.2.0/.hypothesis/constants/37d175425d95aff7 +0 -4
- cometric-0.2.0/.hypothesis/constants/6f3f7dda3bd02709 +0 -4
- cometric-0.2.0/.hypothesis/constants/78ed34a18774f2d3 +0 -4
- cometric-0.2.0/.hypothesis/constants/8263d258dca94122 +0 -4
- cometric-0.2.0/.hypothesis/constants/e3a40f74a8e72704 +0 -4
- cometric-0.2.0/.hypothesis/constants/f33d5940d4c83207 +0 -4
- cometric-0.2.0/.hypothesis/constants/fbe7b640dc5ad53e +0 -4
- cometric-0.2.0/src/cometric/core/schema.py +0 -97
- {cometric-0.2.0 → cometric-0.3.0}/.github/workflows/ci.yml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.github/workflows/publish.yml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.gitignore +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/.gitignore +0 -0
- /cometric-0.2.0/.hypothesis/constants/4145014522d2ff1a → /cometric-0.3.0/.hypothesis/constants/02af8a95fc854af3 +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/052e28aa39cf014b +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/0a08468b27ab0e2b +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/31846ac0f55db7cc +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/3570e270a2e92983 +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/3faf924fe60f71dc +0 -0
- /cometric-0.2.0/.hypothesis/constants/457af5fc346a4d40 → /cometric-0.3.0/.hypothesis/constants/52445b4e87bec631 +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/64a2c31fcab5443b +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/6ab7a80f708d05c3 +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/b428358d86c25f38 +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/bddcf7e0e0af1f28 +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/.hypothesis/constants/da39a3ee5e6b4b0d +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/LICENSE +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/docs/ALSP_COMMERCIAL_ONTOLOGY_SPEC_v0.1.pdf +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/docs/COMETRIC_SPEC_v0.2.md +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/docs/RECONCILIATION.md +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/scripts/build_consulting.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/scripts/build_fixtures.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/__init__.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/cli.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/__init__.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/fingerprint.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/ledger.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/money.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/packs.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/periods.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/templates.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/core/tiers.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/examples/case_a.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/examples/case_b.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/examples/case_c.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/examples/case_d.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/examples/case_e.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/examples/case_f.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/examples/case_g.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/examples/case_h.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/examples/spec_example.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/mcp/__init__.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/mcp/__main__.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/concepts/provider_types.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/concepts/service_categories.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/concepts/unit_templates.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/coverage.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/evidence/claims.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/evidence/sources.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/overlays/levers.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/overlays/mechanisms.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/overlays/metrics.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/overlays/pricing_models.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/pack.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/alsp/rules/rules.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/automation_structures.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/billing_bases.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/cost_categories.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/dimensions.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/fee_components.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/layers.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/levers.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/mechanisms.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/metrics.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/negotiation_exchanges.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/offers.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/pricing_models.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/schema_map.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/selection_framework.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/concepts/selection_heuristics.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/coverage.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/evidence/claims.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/evidence/sources.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/excluded.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/pack.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/base/rules/rules.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/concepts/consulting_concepts.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/concepts/provider_types.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/concepts/service_categories.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/concepts/unit_templates.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/coverage.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/overlays/pricing_models.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/pack.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/rules/rules.yaml +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/templates/capped_tm.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/templates/fixed_fee_plus_success.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/templates/phased_fixed_fee.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/templates/retainer_hours_drawdown.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/packs/consulting/templates/role_based_tm.json +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/src/cometric/py.typed +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/builders.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/conftest.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/test_casebook.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/test_engine_review_fixes.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/test_mcp.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/test_outcome_and_realization.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/test_packs_and_templates.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/test_pricing.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/test_properties.py +0 -0
- {cometric-0.2.0 → cometric-0.3.0}/tests/test_reconcile.py +0 -0
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/cometric/cometric/src/cometric/core/present.py
|
|
2
|
+
# hypothesis_version: 6.170.14
|
|
3
|
+
|
|
4
|
+
['.', '0', '^-?\\d+\\.\\d+$', 'base_client_price', 'capacity_utilization', 'client_downside', 'client_price', 'commitment_shortfall', 'contractual_fee', 'contribution_margin', 'contribution_profit', 'cost_per_unit', 'display', 'f', 'gross_margin', 'overage_fee', 'realization', 'relative_difference', 'target_margin', 'unit_contribution', 'unit_floor']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/cometric/cometric/src/cometric/core/quickstart.py
|
|
2
|
+
# hypothesis_version: 6.170.14
|
|
3
|
+
|
|
4
|
+
['0.10', '0.20', '100000', '110', '12000', '1200000', '130', '140.00', '15000', '2027-01', '40', '40000', '9000', '90000', 'DEDICATED_LABOR', 'ESTIMATED', 'EX-ALT', 'FIXED', 'MEAN', 'MONTHLY', 'POOLED_LABOR', 'TERM', 'VARIABLE', 'WORST', 'accepted_units', 'actuals', 'aggregation', 'amount', 'arguments', 'arrangement_versions', 'assumptions', 'base', 'base_fee', 'behavior', 'break_even', 'by_reference', 'calculate_periods', 'candidates', 'category', 'compare_arrangements', 'components', 'constraints', 'contractual_fee', 'contribution_profit', 'conventions', 'cost_components', 'cost_policy', 'current', 'decimals', 'delivery_plan', 'derive_risk_exposure', 'detail', 'detail_and_precision', 'driver', 'engagement', 'engagement_id', 'errors', 'examples', 'explain_fee', 'fixed_amount', 'get_template', 'high', 'how', 'id', 'lookup_concept', 'low', 'lower_base', 'lt', 'max', 'metric', 'name', 'next', 'no_arithmetic', 'not', 'notes', 'objective', 'origin', 'overage_rate', 'parameters', 'path', 'patterns', 'per_review', 'period', 'periods', 'pointer', 'price_floor', 'quantities', 'rate', 'rate_schedules', 'reconcile', 'reference', 'references', 'results', 'scenario', 'scenarios', 'search_dry_run', 'search_spec', 'search_structures', 'sense', 'spec_example.json', 'summary', 'target_margin', 'team', 'term', 'termination', 'tie_breakers', 'tiers', 'time_period', 'tool', 'tools_with_examples', 'unit', 'validate_engagement', 'value', 'values']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/cometric/cometric/src/cometric/core/predicates.py
|
|
2
|
+
# hypothesis_version: 6.170.14
|
|
3
|
+
|
|
4
|
+
['*', ', ', '.', '<', '<=', '=', '==', '>', '>=', '\\[(\\*|\\d+)\\]', 'all', 'any', 'contains', 'eq', 'equals', 'exists', 'gt', 'gte', 'in', 'lt', 'lte', 'not', 'op', 'path', 'value']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/cometric/cometric/src/cometric/core/enums.py
|
|
2
|
+
# hypothesis_version: 6.170.14
|
|
3
|
+
|
|
4
|
+
['AI_INFERENCE', 'ALLOWANCE_OVERAGE', 'ALL_ELIGIBLE', 'ALL_UNITS', 'AMORTIZED', 'ANNUAL', 'APPROVAL_REQUIRED', 'AVOIDABLE', 'A_DIRECT', 'BACKLOG', 'BONUS', 'B_CORROBORATED', 'CALENDAR_DAYS', 'CAP', 'CAPACITY', 'CLIENT', 'COLLAR', 'COMPONENT', 'CONTRACTED', 'CONTRACT_YEAR', 'CORPORATE_OVERHEAD', 'COST', 'COST_PLUS', 'COUNT', 'CUMULATIVE', 'C_INFERENCE', 'DEDICATED', 'DEDICATED_LABOR', 'DEDICATED_RESOURCE', 'DELIVERY_MANAGEMENT', 'DIRECT_DELIVERY', 'DISCOUNT', 'D_PROPOSED', 'EMERGING', 'ENGAGEMENT', 'ENGAGEMENT_AVOIDABLE', 'ENGAGEMENT_OVERHEAD', 'ENTIRE_SUBTOTAL', 'ERROR', 'ESTABLISHED_COMMON', 'ESTIMATED', 'EVENT', 'EXCESS_ONLY', 'FIXED', 'FIXED_PROJECT', 'FIXED_RECURRING', 'FLAT', 'FTE_MONTHS', 'FULL_MONTH_FROM_NEXT', 'GRADUATED_BLOCK', 'GROSS', 'HALF_EVEN', 'HALF_UP', 'HIGHER_IS_BETTER', 'HOLDBACK', 'HOURS', 'HYBRID', 'IDLE_POOLED_CAPACITY', 'ILLUSTRATIVE', 'INCURRED', 'INDEXATION', 'INFEASIBLE', 'INFO', 'INTERNAL_POLICY', 'JOINT', 'LINE_ITEM', 'LOWER_IS_BETTER', 'MARGINAL', 'METER', 'MINIMUM_SPEND', 'MINIMUM_VOLUME', 'MONTH', 'MONTHLY', 'NET_OF_CREDITS', 'NET_OF_DISCOUNTS', 'NEXT_PERIOD', 'NONE', 'NONE_ADVERSE', 'OBSERVED', 'ONE_TIME', 'OUTCOME', 'OUTCOME_ADJUSTMENT', 'OUTPUT', 'OVERFLOW_COST', 'PERCENT_OF_OUTCOME', 'PERIOD_END', 'PERIOD_END_TRUE_UP', 'PERIOD_TOTAL', 'PER_SEGMENT', 'PLATFORM_OPERATIONS', 'POOLED', 'POOLED_LABOR', 'PORTFOLIO_SHARED', 'PREPAID_CREDIT', 'PROFILE', 'PRORATE', 'PROVIDER', 'QA_REWORK', 'QUARTER', 'QUARTERLY', 'REBATE', 'REMAINDER_DUE', 'RESERVED_CAPACITY', 'RESOURCE', 'REUSABLE_ENGINEERING', 'SERVICE', 'SHARE', 'SHARED', 'SLA_CREDIT', 'STEP', 'SUBCONTRACTOR', 'SUCCESS', 'TERM', 'THIRD_PARTY', 'TIERED_VARIABLE', 'TIME', 'TRANSITION', 'UNAVOIDABLE', 'UNIT_OUTPUT', 'UNKNOWN', 'UNVERIFIED', 'USAGE', 'USAGE_TRIGGERED', 'VARIABLE', 'WAIVED', 'WARNING', 'WEIGHTED', 'WEIGHTED_UNIT_OUTPUT', 'YEAR']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/cometric/cometric/src/cometric/core/api.py
|
|
2
|
+
# hypothesis_version: 6.170.14
|
|
3
|
+
|
|
4
|
+
[10000, '...', '/', '/...', '/actuals', '/actuals/term', '/candidates', '/constraints', '/cost_policy', '/detail', '/driver', '/name', '/objective', '/objective/sense', '/parameters', '/pointer', '/pointers', '/precision', '/results', '/risk_premium', '/scenarios', '/search_spec', '/target_margin', '/tolerance_absolute', '/tolerance_relative', '/transform', '/values', '0', '0.01', '0.15', '0.2', '100', '100000', '140', '20', '90000', '; ', '?', 'BAD_CONSTRAINT', 'BAD_POINTER', 'BASE', 'BEST_AT_GRID_EDGE', 'COSTS_NOT_EVALUATED', 'COST_POLICY_REQUIRED', 'DUPLICATE_ID', 'ERROR', 'INTERNAL_POLICY', 'MEAN', 'NO_RESULTS', 'PARAMETER_SPEC', 'PENDING_HUMAN_REVIEW', 'RANGE', 'RISK_MISMATCH', 'RISK_PREMIUM_RANGE', 'SCENARIO_INFEASIBLE', 'SCHEMA', 'TARGET_MARGIN_RANGE', 'TERM', 'UNKNOWN_DRIVER', 'UNKNOWN_METRIC', 'WORST', '_doc', 'absolute', 'accumulation_period', 'actual', 'actuals', 'add', 'aggregation', 'allowances', 'approval_state', 'assumptions', 'base', 'base_client_price', 'base_contribution', 'base_fee', 'base_scenario', 'base_scenario_id', 'baseline', 'best', 'best_under_objective', 'binding_constraints', 'calculate_periods', 'calculated', 'calculations', 'candidates', 'capacity', 'client_downside', 'client_price', 'closest_value_slack', 'code', 'cometric_higher', 'cometric_lower', 'commitment_shortfall', 'compared', 'component', 'computed', 'constraints', 'contract_facts', 'contractual_fee', 'contribution_margin', 'contribution_profit', 'cost_per_unit', 'cost_policy', 'costs', 'costs_by_category', 'costs_evaluated', 'costs_in_floor', 'counts', 'currency', 'current', 'current_fee', 'declared_bearer', 'decreasing', 'definitions', 'derived_bearer', 'description', 'detail', 'deviations', 'difference', 'direct_delivery_cost', 'direction', 'discrepancies', 'display', 'distribution', 'dominated_by', 'driver', 'dry_run', 'edge', 'engagement', 'engagement_id', 'engine_version', 'entitlement', 'enumerated', 'errors', 'estimated_seconds', 'evaluated', 'exact', 'explanation', 'failing_constraints', 'feasible', 'fee_change', 'fee_line_items', 'fee_total', 'fees', 'fingerprints', 'flat', 'floors', 'formula', 'from', 'frontier', 'frontier_metrics', 'frontier_truncated', 'full', 'full_cost_profit', 'grid_edges', 'grid_size', 'gross_margin', 'gross_profit', 'gt', 'gte', 'headroom', 'horizon', 'id', 'include_baseline', 'increasing', 'infeasible', 'input_fingerprint', 'invalid', 'invalid_reasons', 'issues', 'kind', 'labels', 'leaf_true', 'ledger', 'line_items', 'lower', 'lt', 'lte', 'max', 'max_candidates', 'max_returned', 'measured', 'mechanisms_priced', 'message', 'metric', 'metrics', 'min', 'minimums', 'money_policy', 'month', 'must not be negative', 'name', 'non_dominated', 'not', 'note', 'nothing_compared', 'objective', 'objective_values', 'ok', 'on_frontier', 'op', 'operation', 'origin', 'outcome_fee', 'overage_fee', 'overage_recognition', 'packs', 'parameter', 'parameters', 'path', 'percent', 'period', 'periods', 'pointer', 'pointers', 'precision', 'price_floor', 'profile', 'provider_downside', 'publishable_summary', 'quantity_spreading', 'range', 'ranking', 'rate', 'reason', 'reconcile', 'reconciled', 'record_type', 'reference', 'rejected', 'relative', 'relative_difference', 'results', 'risk', 'risk_exposure', 'risk_premium', 'rollover', 'rows', 'rules_fired', 'scale', 'scenario', 'scenario_id', 'scenarios', 'schema_version', 'scope', 'sense', 'set', 'severity', 'shortfall_rule', 'standard', 'standard_value', 'status', 'step', 'summary', 'target_margin', 'term', 'termination', 'tested_against', 'threshold', 'thresholds', 'tie_breakers', 'time_period', 'to', 'tolerance', 'transform', 'type', 'unit_contribution', 'unit_floor', 'upper', 'valid', 'value', 'values', 'values_per_parameter', 'volume', 'volume_quantity', 'vs_baseline', 'warnings', 'whole', 'within_limit', 'within_tolerance', 'worked_hours', 'years', '~', '~0', '~1']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/cometric/cometric/src/cometric/core/engine.py
|
|
2
|
+
# hypothesis_version: 6.170.14
|
|
3
|
+
|
|
4
|
+
[')', '+', ', ', '-', '/calculation_method', '/driver', '/outcome/metric', '/quantity_source', '/scenario/horizon', '0.3.0', ':', 'AMBIGUOUS_UNIT_PRICE', 'BACKLOG', 'CAPACITY_BREACH', 'DRIVER_REQUIRED', 'FTE', 'LEDGER_INVARIANT', 'METHOD_NOT_SUPPORTED', 'MISSING_ASSUMPTION', 'MIXED_UNITS_IN_PRICE', 'OVERFLOW_COST', 'SEGMENTED_MONTH', 'UNKNOWN_WEIGHT_TABLE', 'adjustments', 'allowance_consumed', 'allowance_granted', 'amortized', 'amount', 'amount_unrounded', 'arrangement_versions', 'backlog_end', 'by_category', 'cap', 'cap_use', 'capacity', 'capacity_utilization', 'category', 'collar', 'commitment_shortfall', 'commitments', 'component', 'components', 'contractual_fee', 'contribution_margin', 'contribution_profit', 'cost_components', 'cost_per_unit', 'costs_by_category', 'ctier', 'date', 'delivery_plan', 'demand', 'demand_hours', 'direct_delivery_cost', 'discount', 'driver_quantity', 'elig', 'engagement', 'fixed', 'formula', 'full_cost_profit', 'gross_margin', 'gross_profit', 'hours', 'id', 'incurred', 'incurred_adjustment', 'indexation', 'infeasible', 'kind', 'layer', 'layers', 'margin_note', 'min', 'minimum', 'minimum_charges', 'minimum_shortfall', 'months', 'months_not_run', 'months_run', 'ok', 'one-time fee', 'one_time', 'original_end_date', 'outcome', 'outcome_fee', 'overage', 'overage_fee', 'overflow', 'overflow_cost_rate', 'performance', 'period', 'periods', 'price', 'productive_hours', 'project_payment', 'quantity', 'rate', 'realization', 'rebate', 'ref', 'resource', 'safe_capacity_hours', 'scenario.', 'segment', 'served', 'stage', 'standard_value', 'step', 'term', 'termination', 'termination_fee', 'termination_rule', 'tier', 'time', 'trigger', 'unit', 'unit_contribution', 'version', 'weighted:', 'worked_hours', 'worked_hours_source', 'write_down', 'years']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/cometric/cometric/src/cometric/core/schema.py
|
|
2
|
+
# hypothesis_version: 6.170.14
|
|
3
|
+
|
|
4
|
+
[10000, '$schema', ', ', '.', '0', '0.15', '110', 'A bare engagement', 'Actuals (reconcile)', 'BASE', 'Default display', 'Default summary', 'MEAN', 'SearchSpec', 'WORST', 'actuals', 'add', 'adjustment', 'aggregation', 'all', 'arrangement_version', 'array', 'assumption', 'base_scenario', 'boolean', 'by_reference', 'candidate', 'commitment', 'commitment_shortfall', 'constraint', 'constraint_paths', 'constraints', 'contractual_fee', 'contribution_margin', 'contribution_profit', 'cost_component', 'cost_policy', 'delivery_plan', 'description', 'detail', 'direct_delivery_cost', 'display', 'dry_run', 'engagement', 'entitlement', 'enum', 'error_paths', 'exact', 'examples', 'fee_component', 'from', 'frontier_metrics', 'full', 'gross_margin', 'gross_profit', 'gt', 'id', 'include_baseline', 'integer', 'items', 'lt', 'lte', 'max', 'max_candidates', 'max_returned', 'maximum', 'metric', 'min', 'name', 'not', 'object', 'objective', 'oneOf', 'outcome_fee', 'overage_fee', 'parameters', 'path', 'paths', 'periods', 'pointer', 'pointers', 'precision', 'properties', 'quantity_source', 'range', 'rate_schedule', 'required', 'rule_paths', 'scale', 'scenario', 'scenarios', 'schema_version', 'search_parameters', 'search_spec', 'sense', 'set', 'standard', 'step', 'string', 'summary', 'term', 'tie_breakers', 'title', 'to', 'tolerance_policy', 'transform', 'type', 'values', '{metric: "amount"}']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/cometric/cometric/src/cometric/core/validation.py
|
|
2
|
+
# hypothesis_version: 6.170.14
|
|
3
|
+
|
|
4
|
+
['/', '/cost_policy', '/engagement', '/horizon', '/mapping', '/scenario', '/termination_date', '0.10', '2500000', '; ', '<required>', 'ADJUSTMENT_FIELDS', 'APPROVAL_REQUIRED', 'ATTRIBUTION_METHOD', 'ATTRIBUTION_REQUIRED', 'BASELINE_REQUIRED', 'CAP needs amount', 'COMMITMENT_SCOPE', 'CONTRACT_YEAR', 'COST_FIELDS', 'CURRENCY_MISMATCH', 'DANGLING_DEPENDENCY', 'DATE_ORDER', 'DEPENDENCY_CYCLE', 'DEPENDENCY_MISSING', 'DISCOUNT', 'DUPLICATE_ID', 'EMPTY_VERSION', 'ERROR', 'EXCESS_ONLY', 'FIELD_NOT_USED', 'HORIZON_OUTSIDE_TERM', 'INFO', 'METHOD_FIELDS', 'METHOD_NOT_SUPPORTED', 'OUTCOME_FEE_APPROVAL', 'RANGE', 'RECOGNITION_PERIOD', 'REQUIRED_FIELD', 'SCHEMA', 'TIER_CLIFF', 'TIER_INVALID', 'UNCAPPED_OUTCOME_FEE', 'UNIT_MISMATCH', 'UNKNOWN_COMPONENT', 'UNKNOWN_COST_POLICY', 'UNKNOWN_ENTITLEMENT', 'UNKNOWN_SERVICE', 'UNKNOWN_UNIT', 'UNKNOWN_VERSION', 'UNKNOWN_WEIGHT_TABLE', 'VERSION_OVERLAP', 'WARNING', 'accumulation_period', 'adjustments', 'amount', 'applies_to', 'approval_reference', 'approvals_required', 'arrangement_versions', 'attribution_method', 'attribution_percent', 'band_lower', 'band_lower_inclusive', 'band_upper_exclusive', 'baseline', 'billing_basis', 'calculation_method', 'cap_amount', 'cap_percent', 'capacity', 'category', 'charge_cadence', 'commitments', 'component_id', 'component_ids', 'components', 'cost_components', 'currency', 'delivery_plan', 'depends_on', 'driver', 'effective_from', 'engagement', 'entitlement_id', 'entitlements', 'errors', 'fixed_amount', 'granted_by', 'info', 'invalid', 'kind', 'loc', 'lower', 'lower_inclusive', 'mapping', 'msg', 'ok', 'outcome', 'overage_recognition', 'overflow_replaces', 'parties', 'payment_schedule', 'percent', 'proration_policy', 'provider_type', 'quantity_source', 'rate_schedule_id', 'rate_schedules', 'raw_unit', 'recognition', 'resources', 'role_rates', 'roles', 'service_category', 'service_id', 'services', 'share_percent', 'shortfall_rule', 'start_date', 'status', 'step_size', 'supersedes_id', 'target', 'threshold', 'threshold_scope', 'tier_method', 'tiers', 'trigger', 'type', 'unit', 'unit_definition_id', 'unit_definitions', 'upper_exclusive', 'valid', 'warnings', 'weight_table_id', 'weight_tables']
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# file: /home/runner/work/cometric/cometric/src/cometric/mcp/server.py
|
|
2
|
+
# hypothesis_version: 6.170.14
|
|
3
|
+
|
|
4
|
+
[b'Method Not Allowed', b'POST', b'Unauthorized', b'allow', b'authorization', b'content-type', b'text/plain', 401, 405, 8765, ',', '.yaml', '.yml', '/', '/mcp', '0', '0.01', '127.0.0.1', '127.0.0.1:*', 'COMETRIC_MCP_TOKEN', 'Cometric', 'DELETE', 'ERROR', 'GET', 'INTERNAL_ERROR', 'INVALID_INPUT', 'UNKNOWN_NAME', 'accumulation_period', 'application/json', 'approvals_required', 'areas', 'body', 'claims', 'code', 'cometric', 'cometric://glossary', 'concept', 'concept-scheme', 'contractual_fee', 'contribution_profit', 'cost_policy', 'coverage', 'derived_bearer', 'display', 'dominance', 'engagement', 'engine_version', 'error', 'errors', 'evidence_class', 'example', 'examples', 'glossary', 'gross_profit', 'headers', 'hint', 'http', 'http.response.body', 'http.response.start', 'id', 'info', 'invalid', 'issues', 'label', 'localhost', 'localhost:*', 'margin', 'margin_layer', 'message', 'method', 'name', 'origin', 'outcome_fee', 'overlays', 'pack', 'pack-template', 'packs', 'path', 'prevalence', 'price_floor', 'query', 'quickstart', 'realization', 'recognition', 'reference', 'results', 'rules', 'schema', 'schema_version', 'search_structures', 'severity', 'source_records', 'sources', 'status', 'stdio', 'summary', 'template', 'templates', 'terms', 'type', 'validate_engagement', 'values', 'warnings']
|
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 (2026-11-05)
|
|
4
|
+
|
|
5
|
+
### Breaking changes
|
|
6
|
+
|
|
7
|
+
- A `DISCOUNT` or `REBATE` with a `threshold` now requires `threshold_scope` (`EXCESS_ONLY` or `ENTIRE_SUBTOTAL`). `DISCOUNT` previously ignored its threshold.
|
|
8
|
+
- `CAP`, `REBATE`, and threshold `DISCOUNT` require `accumulation_period`; it previously defaulted to `MONTH` silently.
|
|
9
|
+
- Effective client unit price, cost per unit, and unit contribution are null, with `AMBIGUOUS_UNIT_PRICE`, when several quantities are priced and `client_value_unit` is not set. Previously they used the first quantity.
|
|
10
|
+
- `search_structures` output is restructured: best results first with full figures; the frontier is parameter sets only at the default `summary` detail.
|
|
11
|
+
- `compare_arrangements` and `search_structures` default to `detail: summary` and `precision: display`; the MCP `calculate_periods` tool defaults to `precision: display`. Use `exact` for unrounded figures.
|
|
12
|
+
- `ENGINE_VERSION` is 0.3.0, so fingerprints of existing inputs change.
|
|
13
|
+
|
|
14
|
+
### Added and fixed
|
|
15
|
+
|
|
16
|
+
- Termination scenarios: `termination_date` on a scenario; `termination_rule` (PRORATE, REMAINDER_DUE, WAIVED) on minimum-spend commitments; `termination_fee` on an arrangement version; allowances expire, unamortized one-time costs are written off, and a `termination` block reports the cost of exiting early.
|
|
17
|
+
- ALSP template `tiered_units_annual_minimum` and five worked patterns with hand-computed figures (`docs/PATTERNS.md`).
|
|
18
|
+
- "Pending human review" defined in the spec: a label for the user's own approval process, not a workflow.
|
|
19
|
+
|
|
20
|
+
From an LLM-driven pricing analysis:
|
|
21
|
+
|
|
22
|
+
- Search: best results first, with full figures per scenario, objective values, constraint results, grid-edge flags (`BEST_AT_GRID_EDGE`), difference from the baseline (the engagement as given), downside per deviation, and fingerprints; `objective.tie_breakers`; `dry_run`; parameters that write several pointers with `set`, `scale`, or `add`.
|
|
23
|
+
- `detail` (summary, standard, full) and `precision` (display, exact) on search and compare, defaulting to summary and display; `precision` on calculate_periods (the MCP tool defaults to display). A typical search answer is about 14% of its full size.
|
|
24
|
+
- The server stays stateless: engagements are passed by reference as file paths; results reproduce from their fingerprints.
|
|
25
|
+
|
|
26
|
+
- Threshold discounts and rebates take a required `threshold_scope`: `EXCESS_ONLY` ("10% off charges above the minimum") or `ENTIRE_SUBTOTAL`. `DISCOUNT` previously ignored `threshold` entirely. `CAP`, `REBATE`, and threshold `DISCOUNT` now require `accumulation_period` (it silently defaulted to `MONTH`).
|
|
27
|
+
- Effective client unit price (and cost per unit, unit contribution) is null with an `AMBIGUOUS_UNIT_PRICE` warning when more than one quantity is priced and `client_value_unit` is not set; `client_value_unit` accepts `a+b` to sum commensurable units.
|
|
28
|
+
- Every calculation result has a `definitions` block: unit-price basis, quantity spreading, thresholds, allowance recognition, minimums.
|
|
29
|
+
- `quickstart` tool and resource with a runnable argument object for every tool; `describe_schema` covers candidates, constraints, reference paths, and actuals.
|
|
30
|
+
- No unstructured MCP errors: every tool returns a code, message, and hint. Candidates may be bare engagements; constraint leaves accept `{path, op, value}`; search specs are validated up front with field paths; clearer message for fractional counts.
|
|
31
|
+
|
|
3
32
|
## 0.2.0 (2026-11-05)
|
|
4
33
|
|
|
5
34
|
- `reconcile`: compare computed figures with recorded actuals by month and term, with a publishable summary that carries no amounts, dates, or names (API, CLI, MCP tool). Guide in `docs/RECONCILIATION.md`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: cometric
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Commercial Intelligence Engine: model, simulate, and optimize the economics of service engagements.
|
|
5
5
|
Project-URL: Homepage, https://github.com/mfbaig35r/cometric
|
|
6
6
|
Project-URL: Repository, https://github.com/mfbaig35r/cometric
|
|
@@ -69,6 +69,7 @@ cometric break-even src/cometric/examples/case_b.json --driver contracts --scena
|
|
|
69
69
|
cometric floor src/cometric/examples/case_b.json --cost-policy reference --target-margin 0.20
|
|
70
70
|
cometric template base_plus_overage
|
|
71
71
|
cometric template phased_fixed_fee --pack consulting
|
|
72
|
+
cometric template tiered_units_annual_minimum --pack alsp
|
|
72
73
|
cometric reconcile engagement.json --scenarios actual-quantities.json --actuals actuals.json --cost-policy reference --summary-only
|
|
73
74
|
cometric lookup PM-023
|
|
74
75
|
```
|
|
@@ -85,7 +86,7 @@ print(result["term"]["contribution_margin"], result["input_fingerprint"])
|
|
|
85
86
|
|
|
86
87
|
## MCP server
|
|
87
88
|
|
|
88
|
-
Cometric ships a read-only, stateless MCP server:
|
|
89
|
+
Cometric ships a read-only, stateless MCP server: 19 tools (start with `quickstart`), schema and template discovery, resources for the glossary, schemas, concept schemes, rules, coverage, templates, and worked examples, and six guided prompts.
|
|
89
90
|
|
|
90
91
|
```bash
|
|
91
92
|
cometric mcp # stdio
|
|
@@ -134,7 +135,7 @@ uv run ruff check src tests scripts && uv run ruff format --check src tests scri
|
|
|
134
135
|
uv run python scripts/build_fixtures.py # regenerate casebook fixtures
|
|
135
136
|
```
|
|
136
137
|
|
|
137
|
-
The specification is `docs/COMETRIC_SPEC_v0.3.md` (normative for 0.1.0). Implementation status is in `docs/STATUS.md`; reconciling a real engagement is described in `docs/RECONCILIATION.md`.
|
|
138
|
+
The specification is `docs/COMETRIC_SPEC_v0.3.md` (normative for 0.1.0). Implementation status is in `docs/STATUS.md`; worked commercial patterns (tiered minimums, transition credits, partial billing, cost from hours, early termination) are in `docs/PATTERNS.md`; reconciling a real engagement is described in `docs/RECONCILIATION.md`.
|
|
138
139
|
|
|
139
140
|
## License
|
|
140
141
|
|
|
@@ -39,6 +39,7 @@ cometric break-even src/cometric/examples/case_b.json --driver contracts --scena
|
|
|
39
39
|
cometric floor src/cometric/examples/case_b.json --cost-policy reference --target-margin 0.20
|
|
40
40
|
cometric template base_plus_overage
|
|
41
41
|
cometric template phased_fixed_fee --pack consulting
|
|
42
|
+
cometric template tiered_units_annual_minimum --pack alsp
|
|
42
43
|
cometric reconcile engagement.json --scenarios actual-quantities.json --actuals actuals.json --cost-policy reference --summary-only
|
|
43
44
|
cometric lookup PM-023
|
|
44
45
|
```
|
|
@@ -55,7 +56,7 @@ print(result["term"]["contribution_margin"], result["input_fingerprint"])
|
|
|
55
56
|
|
|
56
57
|
## MCP server
|
|
57
58
|
|
|
58
|
-
Cometric ships a read-only, stateless MCP server:
|
|
59
|
+
Cometric ships a read-only, stateless MCP server: 19 tools (start with `quickstart`), schema and template discovery, resources for the glossary, schemas, concept schemes, rules, coverage, templates, and worked examples, and six guided prompts.
|
|
59
60
|
|
|
60
61
|
```bash
|
|
61
62
|
cometric mcp # stdio
|
|
@@ -104,7 +105,7 @@ uv run ruff check src tests scripts && uv run ruff format --check src tests scri
|
|
|
104
105
|
uv run python scripts/build_fixtures.py # regenerate casebook fixtures
|
|
105
106
|
```
|
|
106
107
|
|
|
107
|
-
The specification is `docs/COMETRIC_SPEC_v0.3.md` (normative for 0.1.0). Implementation status is in `docs/STATUS.md`; reconciling a real engagement is described in `docs/RECONCILIATION.md`.
|
|
108
|
+
The specification is `docs/COMETRIC_SPEC_v0.3.md` (normative for 0.1.0). Implementation status is in `docs/STATUS.md`; worked commercial patterns (tiered minimums, transition credits, partial billing, cost from hours, early termination) are in `docs/PATTERNS.md`; reconciling a real engagement is described in `docs/RECONCILIATION.md`.
|
|
108
109
|
|
|
109
110
|
## License
|
|
110
111
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cometric | Commercial Intelligence Engine
|
|
2
2
|
|
|
3
|
-
**Engineering Requirements v0.3 (as built for 0.
|
|
3
|
+
**Engineering Requirements v0.3 (as built for 0.3.0)**
|
|
4
4
|
|
|
5
5
|
Cometric does three things:
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ It is built for any service relationship priced through a composite arrangement:
|
|
|
13
13
|
| | |
|
|
14
14
|
|---|---|
|
|
15
15
|
| Project | Cometric (`cometric` on PyPI; CLI and MCP server `cometric`) |
|
|
16
|
-
| Status | Normative for `cometric` 0.
|
|
16
|
+
| Status | Normative for `cometric` 0.3.0 (0.1.0 released 2026-11-04; 0.2.0 and 0.3.0 on 2026-11-05). Open-source project. Where this document and the code disagree, the code's tests are the tiebreaker and the disagreement is a defect in one of them. |
|
|
17
17
|
| License | Apache-2.0 |
|
|
18
18
|
| Date | November 4, 2026 |
|
|
19
19
|
| Supersedes | `COMETRIC_SPEC_v0.2.md` (kept for history, with the v0.1 to v0.2 change log) |
|
|
@@ -55,8 +55,12 @@ v0.3 records what was built. Most changes resolve questions v0.2 left implicit;
|
|
|
55
55
|
| V3-20 | 11 | Open questions updated; new questions from implementation. |
|
|
56
56
|
| V3-21 | App. C | Case H (consulting); fixtures live in `src/cometric/examples/`. |
|
|
57
57
|
| V3-22 | App. D | Evidence verification status replaces the v0.2 priority list. |
|
|
58
|
-
| V3-23 | 4.2, 9 | ALL_UNITS cliff bands compare every earlier tier with each threshold, with an inclusive lower bound where a band starts at a tier edge (
|
|
59
|
-
| V3-24 | 8.3, 9, 10 | `reconcile` operation for M6, with a publishable summary (
|
|
58
|
+
| V3-23 | 4.2, 9 | ALL_UNITS cliff bands compare every earlier tier with each threshold, with an inclusive lower bound where a band starts at a tier edge (0.2.0). |
|
|
59
|
+
| V3-24 | 8.3, 9, 10 | `reconcile` operation for M6, with a publishable summary (0.2.0). |
|
|
60
|
+
| V3-28 | 4.4, 6.1, 9 | Termination scenarios: `termination_date` on a scenario, `termination_rule` on minimums, `termination_fee` on a version (0.3.0). |
|
|
61
|
+
| V3-29 | 3.4, 6.3, App. C | ALSP template `tiered_units_annual_minimum` and five worked patterns (`docs/PATTERNS.md`); "pending human review" defined (0.3.0). |
|
|
62
|
+
| V3-27 | 6.2, 6.4, 8.3, 11 | Search returns best results first with full figures, tie-breakers, constraint results, grid-edge warnings, and baseline differences; dry run; linked and scaled parameters; detail and precision levels; the server stays stateless (0.3.0). |
|
|
63
|
+
| V3-26 | 4.5, 5.4, 7.3, 8.3, 9 | From an LLM-driven pricing analysis (0.3.0): threshold scope for discounts and rebates; unit price only for an unambiguous quantity; a `definitions` block on results; `quickstart`; no unstructured errors; candidate and constraint input forms. |
|
|
60
64
|
| V3-25 | 4.1, 4.3, 4.5, 4.6, 5.2, 6.1, 8.4, 9 | Rules clarified by the full engine review (0.2.0): full-month proration, horizon simulation, one-time fees, indexation scope and contract years, required performance triggers, term-cost spreading, incurred view, component order. |
|
|
61
65
|
|
|
62
66
|
## 1. Purpose and intended decisions
|
|
@@ -426,6 +430,15 @@ As built `[V3-09]`:
|
|
|
426
430
|
- A grant is posted when an entitlement's accumulation period opens, for the full `included_quantity`; grants are not prorated when a contract version starts mid-period.
|
|
427
431
|
- Consumption is FIFO with rolled-in lots first. `NEXT_PERIOD` rolls unused granted quantity (up to `ceiling`) into the next period, where it expires if unused; it does not roll twice. `TERM` rolls everything until the engagement ends. Remaining quantity expires at the engagement's end; a horizon that ends earlier leaves lots open.
|
|
428
432
|
|
|
433
|
+
**Termination** `[V3-28]`. A scenario may set `termination_date` (on or after the start, before the end; mid-month needs a proration policy). The engine then runs to that date:
|
|
434
|
+
|
|
435
|
+
- Fees and costs stop. Quantities and `TERM` costs are still spread over the original term, so a year's volume is not compressed into the months that ran.
|
|
436
|
+
- Each `MINIMUM_SPEND` commitment needs a `termination_rule` (an error otherwise, raised only for terminated scenarios): `PRORATE` charges the shortfall against the current period's minimum pro rata by days; `REMAINDER_DUE` charges the current period's full shortfall plus the full minimum for every later period of the original term, including when termination falls on a period's natural end; `WAIVED` charges none.
|
|
437
|
+
- The version's `termination_fee`, if any, is charged once in the termination month, after caps.
|
|
438
|
+
- Allowances expire. One-time costs still being amortized are written off in the termination month (amortized view), and the amount is reported.
|
|
439
|
+
- Outcome fees and rebates whose accumulation period is cut short are not charged, with `TERMINATED_MID_PERIOD`: the contract decides what is owed.
|
|
440
|
+
- Results carry a `termination` block: date, original end date, months run and not run, minimum charges, termination fee, and unamortized cost written off.
|
|
441
|
+
|
|
429
442
|
[O] Treatment of unused prepaid entitlements for financial-statement accounting is excluded from v1.
|
|
430
443
|
|
|
431
444
|
### 4.5 Evaluation order
|
|
@@ -457,7 +470,7 @@ Step semantics as built `[V3-10]`:
|
|
|
457
470
|
|
|
458
471
|
- **Split months.** Steps 3 and 4 run per day segment. Steps 5 to 9 run once per month with the adjustments and commitments of the version in force at the month's last priced segment.
|
|
459
472
|
- **Collar.** Evaluated per month on that month's measured quantity. Above `upper`, units above the band are repriced on the alternate schedule; below `lower`, all units are repriced on it.
|
|
460
|
-
- **Discount** applies a percentage to each component's step-5 subtotal (all components unless `applies_to` is set). **
|
|
473
|
+
- **Discount** without a threshold applies a percentage to each component's step-5 subtotal (all components unless `applies_to` is set). **Thresholds** `[V3-26]`: a `DISCOUNT` or `REBATE` with a `threshold` must declare `threshold_scope` and `accumulation_period` (no defaults). `EXCESS_ONLY` applies the percentage only to the period subtotal above the threshold ("10% off charges above the minimum"); `ENTIRE_SUBTOTAL` applies it to the whole period subtotal once the threshold is reached. A threshold discount is recognized cumulatively: the crossing month takes the amount for the excess (or the catch-up for the whole subtotal), later months take their share, and amounts are rounded cumulatively so they sum exactly to the period figure. A rebate settles at period end on the same basis. `CAP` also requires `accumulation_period`.
|
|
461
474
|
- **Indexation** adds, from the second contract year, `(1 + percent)^n - 1` times each step-4 fixed, resource, time, unit, and overage line (including period-end overage), where n is the contract year. Project payments and outcome fees are not indexed. A month belongs to the contract year containing its first day, counting anniversaries of the engagement start date. `[V3-25]`
|
|
462
475
|
- **Performance.** A trigger quantity the scenario does not provide is an error with a pointer to the adjustment's `trigger`, never a silent zero. `[V3-25]` `SLA_CREDIT` and `BONUS` multiply `percent` × the step-7 subtotal × a scenario trigger quantity (for example, misses in the month), limited by `cap_percent` of that subtotal. `HOLDBACK` withholds `percent` of the subtotal unless the trigger quantity releases it (1).
|
|
463
476
|
- **Cap** accumulates the pre-cap total over its period and reduces the month in which the cap is crossed and any month after.
|
|
@@ -583,6 +596,8 @@ For AI-assisted services, cost drivers SHOULD include document complexity, infer
|
|
|
583
596
|
|
|
584
597
|
### 5.4 Financial outputs
|
|
585
598
|
|
|
599
|
+
**Unit price basis** `[V3-26]`: effective client unit price, cost per unit, and unit contribution divide by `client_value_unit` when set (one quantity, `weighted:<name>`, or quantities joined with `+`, with a `MIXED_UNITS_IN_PRICE` warning when their units differ). Without it they are reported only when the engagement prices exactly one quantity; otherwise they are null with an `AMBIGUOUS_UNIT_PRICE` warning. Every calculation result carries a `definitions` block stating the unit-price basis, how assumptions were spread across months, threshold scopes, allowance recognition, and minimum rules, so a summary can carry the right caveats.
|
|
600
|
+
|
|
586
601
|
Required metrics `[V3-14]`: contractual fee, outcome fee, direct delivery cost, unavoidable direct cost, gross profit and margin, engagement-avoidable cost, contribution profit and margin, cost per accepted unit, effective client price per accepted unit (and per used hour for resource arrangements), reserved-capacity utilization, productive-hours utilization, included-allowance consumption, commitment shortfall, overage fee, cumulative contribution, transition payback month (incurred view), break-even volume where mathematically defined, and, when the delivery plan has a standard rate card, worked hours, standard value, realization (contractual fee / standard value), write-down (standard value − contractual fee), and effective billing rate (contractual fee / worked hours).
|
|
587
602
|
|
|
588
603
|
Break-even volume is found by bracketing whole driver units and interpolating linearly between the bracketing pair; it is reported as that decimal value and as the whole unit at the boundary (the smallest whole unit with non-negative contribution when contribution rises with the driver, the largest when it falls). The result states the interpolation assumption. For piecewise fees or costs, the engine solves piecewise and returns null with a reason when no break-even exists in the horizon.
|
|
@@ -655,7 +670,7 @@ Given one service and demand profile, the engine SHOULD compare at least:
|
|
|
655
670
|
- dedicated resource or capacity model;
|
|
656
671
|
- base fee plus output-based overage.
|
|
657
672
|
|
|
658
|
-
Each comparison MUST show fee, cost, contribution, client effective unit cost, capacity utilization, declared and derived risk exposure (§5.5), and the assumptions that differ. A model can be rejected for infeasibility without being labeled commercially inferior.
|
|
673
|
+
Each comparison MUST show fee, cost, contribution, client effective unit cost, capacity utilization, declared and derived risk exposure (§5.5), and the assumptions that differ, at the requested `detail` (`summary` default: key metrics per scenario and dominance; `standard` adds all summary metrics and risk deviations; `full` adds complete exposure and issues) and `precision` (`display` default, or `exact`). `[V3-27]` A model can be rejected for infeasibility without being labeled commercially inferior.
|
|
659
674
|
|
|
660
675
|
**Dominance, not ranking.** By default the engine ranks nothing. For each feasible candidate it reports whether another candidate dominates it: at least as good on every comparison metric and strictly better on one. The default metrics are provider contribution (higher is better) and client effective unit price (lower is better), evaluated in every scenario of the set. The non-dominated candidates are returned as a set. A weighted or constrained objective is applied only when the caller supplies one, and the result records it verbatim.
|
|
661
676
|
|
|
@@ -671,6 +686,8 @@ An AI layer MAY propose alternatives, explain tradeoffs, or identify missing fac
|
|
|
671
686
|
|
|
672
687
|
Recommendations SHALL cite calculation IDs, assumptions, constraints, and evidence claims. Human sign-off is required before adopting a commercial recommendation.
|
|
673
688
|
|
|
689
|
+
**Pending human review** `[V3-29]` is a label, not a workflow. Cometric never changes it and has no notion of approvers: it marks every search and comparison result as advice that a person with authority over the commercial terms must accept in the user's own process. A reviewed result is cited, with its fingerprint, in that process's record.
|
|
690
|
+
|
|
674
691
|
### 6.4 Structure search (Optimize)
|
|
675
692
|
|
|
676
693
|
In Cometric, "optimize" means a deterministic search over a space of candidate structures that the caller declares. It never means asking a model for an answer.
|
|
@@ -696,7 +713,11 @@ In Cometric, "optimize" means a deterministic search over a space of candidate s
|
|
|
696
713
|
Callers may declare a different metric set.
|
|
697
714
|
6. If an objective is supplied, also return the best constraint-satisfying candidate(s) under it. Ties are all returned.
|
|
698
715
|
|
|
699
|
-
**Output
|
|
716
|
+
**Output** `[V3-27]`: the best results come first. With an objective, `best` lists every candidate tied at the top after applying `objective.tie_breakers` in order, each with its parameter values, objective values, key metrics per scenario, difference from the baseline per scenario, the result of each constraint leaf, provider and client downside per deviation, `grid_edges` (parameters whose winning value is the lowest or highest in the grid), and calculation fingerprints. A `BEST_AT_GRID_EDGE` warning says when the grid should be widened before calling a result optimal. The baseline (default on) is the search_spec engagement as given. Then come counts (enumerated, invalid, infeasible, failing constraints, on frontier), invalid reasons, and the unranked frontier. If the frontier exceeds `max_returned` (default 20), the result says so. It never applies an undeclared ranking.
|
|
717
|
+
|
|
718
|
+
**Parameters and sizing** `[V3-27]`: a parameter may write one `pointer` or several `pointers`, with `transform` `set` (write the value), `scale` (base × (1 + value)), or `add` (base + value), so "the same uplift on every tier" is one parameter instead of a combinatorial grid. `dry_run: true` returns grid size, calculation count, and an estimated time without running the search, so the user can confirm first.
|
|
719
|
+
|
|
720
|
+
**Detail and precision** `[V3-27]`: `detail` is `summary` (default: best results in full, frontier as parameter sets, key metrics only, empty nested fields dropped), `standard`, or `full`; `precision` is `display` (default: ratios to 4 places, prices to 2) or `exact`. Fingerprints are unaffected.
|
|
700
721
|
|
|
701
722
|
**Guardrails.** Results are `PricingRecommendation` records with `approval_state = PENDING_HUMAN_REVIEW` (§6.3). The engine never invents parameter ranges or objectives. An advisory agent may propose a `search_spec`, and the spec must be shown to the user before it runs.
|
|
702
723
|
|
|
@@ -733,6 +754,7 @@ The system SHALL emit warnings and approval requirements (it does not run an app
|
|
|
733
754
|
- floor/cap conflicts (`requires_contract_interpretation`);
|
|
734
755
|
- capacity breach under any breach mode;
|
|
735
756
|
- declared/derived risk mismatch (`RISK_MISMATCH`);
|
|
757
|
+
- an ambiguous unit price (`AMBIGUOUS_UNIT_PRICE`) or one that sums different units (`MIXED_UNITS_IN_PRICE`); `[V3-26]`
|
|
736
758
|
- outcome fees without a cap or recorded approval (`UNCAPPED_OUTCOME_FEE`, `OUTCOME_FEE_APPROVAL`), and SLA credits or bonuses without `cap_percent` (`UNCAPPED_PERFORMANCE_ADJUSTMENT`);
|
|
737
759
|
- missing evidence for asserted market benchmarks.
|
|
738
760
|
|
|
@@ -911,7 +933,7 @@ The CLI, Python API, and MCP server expose the same operations. Every operation
|
|
|
911
933
|
|
|
912
934
|
- `reconcile(engagement, scenario, cost_policy, actuals, tolerance_absolute?, tolerance_relative?) -> reconciliation_result`. `actuals` holds recorded figures by month and for the term, as decimal strings or integers. Each compared figure passes within either tolerance (both non-negative). Unknown metrics, malformed months, floats, nulls, and negative tolerances are errors with JSON Pointer paths, never silently skipped. A metric the engine did not compute (costs without a cost policy, realization without a rate card) is reported as not computed, never as zero. Status is `reconciled`, `discrepancies`, `infeasible` (the scenario breaches capacity, so matching figures do not reconcile it), `nothing_compared`, or `invalid`. Failing monthly rows carry that month's fee line items. The result carries its own fingerprint over the inputs, actuals, and tolerances, plus the underlying calculation's fingerprint. `publishable_summary` carries only metric, month of the engagement term (1 = first month of the engagement), relative difference, direction, and the mechanisms priced that month; no amounts, dates, or names.
|
|
913
935
|
|
|
914
|
-
The MCP server exposes
|
|
936
|
+
The MCP server exposes 19 tools, starting with `quickstart`, which returns the conventions and, per tool, a complete runnable argument object (each one is executed by the test suite). `[V3-26]` The others are the operations above plus `describe_schema`, `list_packs`, `describe_pack`, `list_templates`, `get_template`, `list_vocabulary`, and `lookup_concept`; `reconcile` is the 18th. `[V3-17]`
|
|
915
937
|
|
|
916
938
|
**MCP server requirements:**
|
|
917
939
|
|
|
@@ -919,7 +941,8 @@ The MCP server exposes 18 tools: the operations above plus `describe_schema`, `l
|
|
|
919
941
|
- **Transports**: stdio from M2. Streamable HTTP from M4, so web-based clients and hosted connectors can reach Cometric. The HTTP transport MUST be stateless: no session ids, no server-side state, `POST /mcp` only, and `GET /mcp` answered with `405 Method Not Allowed` so clients do not hold idle event streams open. Authentication is the deployer's concern; the server accepts an optional bearer-token check and nothing more.
|
|
920
942
|
- Inputs are passed inline, or as file paths when the server runs over stdio with `COMETRIC_ALLOWED_ROOT` set. Paths outside that root are rejected. A file holding a casebook fixture (an object with an `engagement` key) is unwrapped to its engagement. The HTTP transport accepts inline inputs only. `[V3-17]`
|
|
921
943
|
- The HTTP transport keeps DNS-rebinding protection on. Allowed `Host` headers default to localhost; deployments set `COMETRIC_ALLOWED_HOSTS` (comma-separated). A bearer token is checked when `COMETRIC_MCP_TOKEN` is set. `[V3-17]`
|
|
922
|
-
- Errors are structured: `{code, message, path}` where `path` is a JSON Pointer into the input, so an
|
|
944
|
+
- Errors are structured: `{code, message, path}` where `path` is a JSON Pointer into the input, often with `example` or `hint`. Every tool is wrapped so no exception reaches the client as an unexplained failure: unknown names, invalid input, and internal defects each return a code and message. `[V3-26]`
|
|
945
|
+
- `describe_schema` also covers `candidate`, `constraint`, `paths` (every reference syntax in one place), and `actuals`. Candidates may be `{id, engagement}` or bare engagements. Constraint leaves may also be written `{"path", "op", "value"}` with op one of `==`, `>`, `<`, `>=`, `<=`, `in`. `[V3-26]`
|
|
923
946
|
- `detail` controls result size: `summary` (term and annual totals, metrics, warnings), `periods` (adds monthly rows), `line_items` (adds the full trace).
|
|
924
947
|
- Every result carries `engine_version`, `schema_version`, pack versions, the effective money policy, and the input fingerprint.
|
|
925
948
|
|
|
@@ -1022,6 +1045,9 @@ The test suite MUST include:
|
|
|
1022
1045
|
| T-040 | Consulting pack `[V3-19]` | The pack validates; each of its five templates round-trips (T-029); Case H fires CONS-R-001 (approval) and CONS-R-003 |
|
|
1023
1046
|
| T-041 | Pack templates over MCP `[V3-19]` | `cometric://packs/{pack}/templates/{id}` resolves for every pack template |
|
|
1024
1047
|
| T-043 | Engine review regressions `[V3-25]` | Full-month policies bill whole months; a project payment in a split month posts; a mid-year horizon carries the annual allowance; one-time and annual fees keep their totals; collars reprice at the cumulative tier position; cumulative and period-end overage index identically and project payments are not indexed; a later-starting term cost keeps its total; the incurred view ignores portfolio costs; a missing trigger is an error; the price floor needs costs; quarterly shares anchor at the component start; contract years honor the start day; component order never changes results |
|
|
1048
|
+
| T-044 | LLM-feedback fixes `[V3-26]` | Threshold discount and rebate: EXCESS_ONLY 3,175,000 and ENTIRE_SUBTOTAL 2,925,000 on a 3,250,000 gross with a 2,500,000 threshold; the excess discount starts in the crossing month; missing scope or period is an error with an example; several unit types give a null unit price with a warning, and `client_value_unit` with `+` sums them; bare-engagement candidates work and bad ones get a pointer; the constraint `op` alias works; no tool returns an unstructured error; every quickstart payload runs through the MCP server |
|
|
1049
|
+
| T-045 | Termination `[V3-28]` | PRORATE charges the shortfall against 150,000 x 181/365 at a 30 June termination; REMAINDER_DUE charges 90,000 for one year and 240,000 with a second year, and owes later years at a period-end termination; WAIVED charges none; the fee posts; quantities spread over the original term; unamortized transition is written off; a cut-short outcome fee is not charged; a missing rule, an out-of-range date, and a mid-month date without proration are errors |
|
|
1050
|
+
| T-046 | Patterns `[V3-29]` | Every pattern file matches figures computed by hand in `scripts/build_alsp.py`; the ALSP template round-trips |
|
|
1025
1051
|
| T-042 | Reconciliation `[V3-24]` | Actuals equal to computed figures reconcile; a changed July invoice is reported at month 7 with the mechanism that priced it; the publishable summary contains no amounts, dates, or names; relative tolerance and unknown metrics are honored |
|
|
1026
1052
|
|
|
1027
1053
|
**Property tests** SHOULD verify: non-negative accepted units; non-overlapping effective dates; contiguous tiers; under `MARGINAL` tier schedules with non-negative rates, the pre-credit fee never decreases when eligible consumption increases, holding other terms fixed. Under `ALL_UNITS` schedules the property holds outside every band reported by `TIER_CLIFF` and is not asserted inside them. T-033 runs only when the private research report is present; CI skips it.
|
|
@@ -1077,6 +1103,7 @@ v0.1 framed most open decisions as questions for one organization's stakeholders
|
|
|
1077
1103
|
- **Q-8 [O] Other commitment kinds.** Which of `MINIMUM_VOLUME`, `RESERVED_CAPACITY`, and `PREPAID_CREDIT` should be computed next, and with what semantics?
|
|
1078
1104
|
- **Q-9 [O] Mid-period amendments.** Should allowance grants be prorated when a version starts mid-period, and should adjustments split by segment within a month?
|
|
1079
1105
|
- **Q-10 [O] Custom evaluation orders.** Is there a real contract that needs one?
|
|
1106
|
+
- **Q-11 Resolved: memory between calls.** The server stays stateless and read-only. Engagements are passed by reference as file paths under `COMETRIC_ALLOWED_ROOT` (stdio); results carry fingerprints and can be reproduced exactly from their inputs. No engagement store or run ids. `[V3-27]`
|
|
1080
1107
|
|
|
1081
1108
|
## 12. Decisions recorded in v0.3
|
|
1082
1109
|
|
|
@@ -1159,6 +1186,8 @@ Expected: low 5,000 at 70/20/10 → 6,800 WU, fee $776,000, direct $508,000; bas
|
|
|
1159
1186
|
Case A with demand 16,000 units and `OVERFLOW_COST` at $40/unit replacing the $18 variable rate for units above capacity.
|
|
1160
1187
|
Expected: fee $1,200,000 + 4,000 × $120 = $1,680,000; direct $660,000 + 14,000 × $18 + 2,000 × $40 = $992,000; GP $688,000; CP $548,000; overflow recognized in November and December under cumulative capacity. Variants: `BACKLOG` carries 2,000 units past the horizon with an SLA warning; `INFEASIBLE` and undeclared mode fail feasibility (T-010).
|
|
1161
1188
|
|
|
1189
|
+
**Patterns** `[V3-29]`: `pattern_tiered_minimum`, `pattern_transition_credit`, `pattern_partial_and_hours`, and `pattern_termination` are documented in `docs/PATTERNS.md`, with expected figures computed independently of the engine.
|
|
1190
|
+
|
|
1162
1191
|
**Case H (new): consulting phased fixed fee plus gain-share.** *(v0.3, illustrative, not from the report)* `[V3-21]`
|
|
1163
1192
|
`FIXED_PROJECT` $600,000 paid $150,000 / $250,000 / $200,000 in March, July, December; `OUTCOME_ADJUSTMENT` SHARE of 10% with 70% attribution on reduction of annual addressable spend below a $10,000,000 baseline (`LOWER_IS_BETTER`), capped at $100,000. Costs: 4,000 delivery hours at $90 → `DIRECT_DELIVERY`; engagement overhead $30,000 → `ENGAGEMENT_AVOIDABLE`. Standard rate card: partner $400 (500 hours), consultant $175 (3,500 hours). Declares the consulting pack; service category `TRANSFORMATION`; provider type `BOUTIQUE`.
|
|
1164
1193
|
Expected under `reference`: spend 9,900,000 → outcome fee $7,000, fee $607,000, CP $217,000; 9,500,000 → $35,000 / $635,000 / $245,000; 9,000,000 → $70,000 / $670,000 / $280,000. Standard value $812,500 in every scenario; base realization 0.7815.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Commercial patterns
|
|
2
|
+
|
|
3
|
+
Worked engagements for structures that are common in managed legal services and easy to get wrong. Each file is in `src/cometric/examples/`, is served by the MCP server at `cometric://examples/<name>`, and is checked by the test suite against figures computed by hand in `scripts/build_alsp.py`.
|
|
4
|
+
|
|
5
|
+
The template behind patterns 1, 2, and 5 is `tiered_units_annual_minimum` in the ALSP pack:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cometric template tiered_units_annual_minimum --pack alsp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 1. Tiered unit prices, an annual minimum, and a discount on the excess
|
|
12
|
+
|
|
13
|
+
`pattern_tiered_minimum`. Four complexity tiers priced per unit (4,000 / 2,000 / 1,000 / 500), an annual minimum of 3,000,000, and 10% off charges above the minimum.
|
|
14
|
+
|
|
15
|
+
- The minimum is a `MINIMUM_SPEND` commitment per `CONTRACT_YEAR`, trued up at year end.
|
|
16
|
+
- The discount is a `DISCOUNT` with `threshold` 3,000,000, `threshold_scope: EXCESS_ONLY`, and `applies_to` the four tier components. It starts in the month cumulative charges pass the minimum.
|
|
17
|
+
- `client_value_unit: "tier_1+tier_2+tier_3+tier_4"` makes the unit price an average over all tiers. Without it the unit price is not reported, because several units are priced.
|
|
18
|
+
|
|
19
|
+
| Scenario | Gross | Shortfall | Discount | Fee |
|
|
20
|
+
|---|---|---|---|---|
|
|
21
|
+
| low | 2,460,000 | 540,000 | 0 | 3,000,000 |
|
|
22
|
+
| base | 4,080,000 | 0 | 108,000 | 3,972,000 |
|
|
23
|
+
|
|
24
|
+
## 2. A transition fee that counts toward the minimum
|
|
25
|
+
|
|
26
|
+
`pattern_transition_credit`. Pattern 1 plus a one-time 200,000 transition fee in January. Because the minimum's `aggregation_scope` is `ENGAGEMENT`, the transition fee counts toward it; because the discount's `applies_to` lists only the tier components, the fee is not discounted and does not count toward the discount threshold.
|
|
27
|
+
|
|
28
|
+
| Scenario | Shortfall | Fee |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| low | 340,000 | 3,000,000 |
|
|
31
|
+
| base | 0 | 4,172,000 |
|
|
32
|
+
|
|
33
|
+
To keep a transition fee outside the minimum, give the minimum `aggregation_scope: COMPONENT` with the tier components.
|
|
34
|
+
|
|
35
|
+
## 3 and 4. Partial billing and cost from hours
|
|
36
|
+
|
|
37
|
+
`pattern_partial_and_hours`.
|
|
38
|
+
|
|
39
|
+
- **Partial billing:** reviews handed back part-way are their own unit (`returned_review`) with a component priced at 40% of the full rate. 1,200 reviews at 1,000 plus 60 returned at 400 gives 1,224,000.
|
|
40
|
+
- **Cost from hours:** `production_standards` set hours per unit (2.5 for a review, 1 for a returned one), which the engine turns into `demand_hours`. A `VARIABLE` cost on `demand_hours` at a blended 80 an hour gives 3,060 hours and 244,800 of delivery cost; with 50,000 of account management, contribution is 929,200.
|
|
41
|
+
|
|
42
|
+
## 5. Early termination
|
|
43
|
+
|
|
44
|
+
`pattern_termination`. Pattern 1 terminated on 30 September, with `termination_rule: PRORATE` and a 100,000 termination fee.
|
|
45
|
+
|
|
46
|
+
- Fees stop after September. Quantities declared for 2027 are still spread over the whole year, so nine months of volume are billed.
|
|
47
|
+
- `PRORATE` requires 3,000,000 × 273 / 365 = 2,243,835.62 for the nine months. The low scenario billed 1,845,000, so 398,835.62 is due; the base scenario billed more than the prorated minimum.
|
|
48
|
+
- The discount threshold is not prorated: in the base scenario, nine months of charges (3,060,000) pass the annual threshold by 60,000, so 6,000 of discount applies.
|
|
49
|
+
- The result's `termination` block reports months run, minimum charges, the termination fee, and any unamortized one-time cost written off.
|
|
50
|
+
|
|
51
|
+
| Scenario | Fee |
|
|
52
|
+
|---|---|
|
|
53
|
+
| low | 2,343,835.62 |
|
|
54
|
+
| base | 3,154,000 |
|
|
55
|
+
|
|
56
|
+
Other termination rules: `REMAINDER_DUE` charges this period's full minimum and every later period's; `WAIVED` charges none. Outcome fees and rebates whose period termination cuts short are not charged, with a `TERMINATED_MID_PERIOD` warning, because the contract decides what is owed.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cometric implementation status
|
|
2
2
|
|
|
3
|
-
Version `0.
|
|
3
|
+
Version `0.3.0` (0.1.0 released 2026-11-04; 0.2.0 added reconciliation and the fixes from two code reviews; 0.3.0 adds termination scenarios, the ALSP tiered-minimum template and patterns, and the fixes from an LLM-driven pricing analysis). The normative specification is `COMETRIC_SPEC_v0.3.md`, which incorporates every clarification below.
|
|
4
4
|
|
|
5
5
|
## Milestones
|
|
6
6
|
|