Skip to content

WP1: shared-savings price, three urgency bands, first-hour floor - #9

Merged
Neal006 merged 1 commit into
mainfrom
worktree-wp1-pricing-emergency
Sep 13, 2026
Merged

Neal006 merged 1 commit into
mainfrom
worktree-wp1-pricing-emergency

Conversation

@Neal006

@Neal006 Neal006 commented Sep 12, 2026

Copy link
Copy Markdown
Owner

WP1 of prompt.md. Plan and deviations: .docs/implementation-plan.md.

prove.py before → after

                          kWh    $ bill    kg CO2   peak kW
before  charge-immediately 378.9   67.42      23.0     101.0
        noonshift          378.9   65.22       7.1     100.0     saving  3.3%  69.3%  1.0%
after   charge-immediately 378.9   67.42      23.0     101.0
        noonshift          378.8   65.46       8.1     100.0     saving  2.9%  64.6%  1.0%

530 solves, max 67 ms, 0 fallbacks, GATE PASS. With the first-hour floor switched off the after-code gives 69.4 %, so the floor alone costs 4.8 points of CO₂ saving (16.0 → 14.9 kg/day, $0.23/day) — above the 2–3 % the spec guessed, well under the 15 % gate. Kept: it is the trust promise (business.md §4).

What changed

  • 1.1 price(slack, *, r, saving_usd, kwh, alpha, urgent) = R − α·max(S,0)/E, clamped to [0, R]; urgent or < 1 h slack → exactly R. Tier labels unchanged. git grep "0.40" noonshift/ → nothing. /price preview uses today's site saving rate so far (estimate).
  • 1.2 POST /sessions/{id}/urgency {level, leave_at?}; /boost = alias of now. now → deadline = now + boost; soon → deadline = leave_at (< 15 min ⇒ now); priority → floor_alpha 0.9, priority 2.0 in solve_lp (shortfall weighs 2× in the fairness term and costs 2×M_SHORT). Event boost for now (both front-ends already handle it), urgency for the other two.
  • 1.3 First-hour floor min(need, 3.5 kWh) by arrival + 60 min, elastic through the floor slack.
  • 1.4 test_first_hour_floor_holds_for_every_car_on_the_day — asserted for the first hour only; the docstring says why (beyond it the 50 % pro-rata floor is the guarantee; a dumb-charger bound over every rolling hour would forbid shifting).
  • Correctness fix the floor exposed: the LP counted slot 0 as a full 5 minutes. A re-solve fires on every plug-in event, mid-slot, so a plan that landed "just enough, as late as possible" lost a sliver each time (session 4 got 3.11 kWh instead of 3.5). Slot 0 now carries its remaining minutes and floor checkpoints are times since arrival, pro rata in the slot containing the mark. Neutral on the headline (+0.1 pt).

Assumptions (spec asked to confirm)

  • A1 employee_rate_usd_per_kwh: code default 0.0 (free); data/site.json ships 0.25 (flat employee rate case, §0b) so the demo shows the §7b math instead of three $0.00 chips. Set to 0 for a free site.
  • A6 /boost = urgency now → WattWise "Charge now" forfeits the discount, per §4b.
  • Deviation: price() denominator is kwh_needed while charging (the receipt's saving covers the planned series; kwh_delivered is 0 at plug-in) and kwh_delivered once ended.

Tests

63 pass (10 new): price ≤ R / urgent = R / §6b 0.247; now full power next slot; priority ≥ 90 % pro-rata at every checkpoint and 0 shortfall when oversubscribed; 3.5 kWh at 60 min (unit + every car on the day); mass arrival bursts the block, never the feed. smoke.py → SMOKE OK incl. soon + priority.

🤖 Generated with Claude Code

https://claude.ai/code/session_017thvbGo7rTVnG2f46cLMzU

- scheduler.price(slack, *, r, saving_usd, kwh, alpha, urgent): business.md
  §7b, R - alpha*S/E clamped to [0, R]; urgent or < 1 h slack pays exactly R.
  No hardcoded prices left in noonshift/.
- POST /sessions/{id}/urgency {level: now|soon|priority, leave_at?};
  /boost is the alias of "now". Per-car floor_alpha / priority in solve_lp
  (priority car's shortfall weighs prio-fold in the fairness term and costs
  prio * M_SHORT, so it gives way last).
- First-hour floor: min(need, 3.5 kWh) 60 min after plug-in, elastic through
  the floor slack. prove.py: CO2 -69.3 % -> -64.6 %, bill -3.3 % -> -2.9 %,
  peak -1.0 %, 0 fallbacks. The floor alone costs 4.8 pts (16.0 -> 14.9 kg).
- Correctness fix the floor exposed: slot 0 only has its remaining minutes
  ahead (dur[0]); floor checkpoints are times since arrival, pro rata inside
  the slot containing the mark. Without it a mid-slot re-solve after every
  plug-in event booked energy that could no longer be delivered.
- site.json: employee_rate_usd_per_kwh 0.25, driver_share 0.5,
  noonshift_share 0.2. Contract files regenerated (additive).
- 10 new tests (63 total); smoke.py exercises soon + priority.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017thvbGo7rTVnG2f46cLMzU
Copilot AI lite review requested due to automatic review settings September 12, 2026 23:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Neal006
Neal006 merged commit a17e622 into main Sep 13, 2026
3 checks passed
@Neal006
Neal006 deleted the worktree-wp1-pricing-emergency branch September 13, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants