Bin Rota Skill

Purpose

Use this skill whenever the user asks about bin collection, bin night, the building bin rota, responsible flats, bin types, swaps, or reminders.

The skill must use deterministic state, not conversational memory, for rota calculations.

Core rules

Normal collection:

  • Collection is normally Friday morning.
  • Bin night is normally Thursday night.

Bank holiday shift:

  • If a UK bank holiday affects the collection week, collection shifts from Friday to Saturday.
  • Shifted bin night is Friday night.
  • Use England and Wales bank holidays unless configured otherwise.
  • Bank holiday data should come from the GOV.UK bank holidays JSON feed.
  • The council website may be checked as an advisory source, but it is not the source of truth unless manually confirmed.

Bin pattern:

  • Collections alternate between:

  • black and green bins

  • green bins only

Flat rota:

  • There are 8 flats.
  • The rota sequence is:
1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1
  • Repeat this sequence indefinitely.
  • Advance one rota position per collection.
  • Do not advance based on calendar weeks alone.

Required persistent state:

{
  "timezone": "Europe/London",
  "bank_holiday_region": "england-and-wales",
  "anchor_collection_date": "YYYY-MM-DD",
  "anchor_rota_index": 0,
  "anchor_bin_pattern": "black_green",
  "swaps": [],
  "manual_overrides": []
}

Definitions:

  • anchor_collection_date: a known real collection date.
  • anchor_rota_index: the rota index for that collection date.
  • anchor_bin_pattern: the bins for that collection date. Allowed values:

  • black_green

  • green_only
  • swaps: persisted swap records.
  • manual_overrides: explicit human-confirmed corrections.

Swap records:

{
  "type": "one_off",
  "collection_date": "YYYY-MM-DD",
  "original_flat": 3,
  "replacement_flat": 6,
  "recorded_by": "name or handle",
  "recorded_at": "ISO-8601 timestamp",
  "reason": "optional"
}

True exchange records:

A true exchange means one flat later in the rota covers an earlier flat's turn, and the earlier flat then takes the later flat's future turn.

Example:

Flat 3 is due on 2026-06-05. Flat 6 is due on 2026-07-31. Flat 3 and Flat 6 swap.

Result:

  • 2026-06-05: Flat 6 is responsible.
  • 2026-07-31: Flat 3 is responsible.
  • Both dates must be annotated in schedule listings.

Record format:

{
  "type": "exchange",
  "flat_a": 3,
  "flat_b": 6,
  "collection_date_a": "2026-06-05",
  "collection_date_b": "2026-07-31",
  "recorded_by": "name or handle",
  "recorded_at": "ISO-8601 timestamp"
}

Manual override records:

```json
{
  "collection_date": "YYYY-MM-DD",
  "responsible_flat": 5,
  "bins": "black_green",
  "source": "human confirmed",
  "recorded_at": "ISO-8601 timestamp"
}

Deterministic calculation

To answer a rota query:

  1. Generate all expected collection dates from the anchor date to the target date.
  2. For each collection:

  3. normally use Friday

  4. shift to Saturday if bank holiday logic applies
  5. Count the number of collections elapsed since the anchor collection.
  6. Calculate rota index:
effective_index = (anchor_rota_index + elapsed_collections) mod 16
  1. Calculate responsible flat:
rota_sequence[effective_index]
  1. Calculate bin pattern:
black_green if elapsed_collections is even relative to anchor black_green
green_only if elapsed_collections is odd relative to anchor black_green

Invert this if the anchor collection is green_only.

  1. Apply manual overrides first.
  2. Apply swaps second.
  3. Return the final answer.

Response format

For a normal bin night answer:

Yes. Tonight is bin night. Collection is tomorrow morning: [DATE]. Bins: [BINS]. Responsible flat: [FLAT]. [Swap/override note if any.]

For a non-bin-night answer:

No. The next bin night is [DATE]. Collection is [DATE]. Bins: [BINS]. Responsible flat: [FLAT].

For a swap confirmation:

Recorded. For collection on [DATE], Flat [REPLACEMENT] is covering Flat [ORIGINAL]. Bins: [BINS].

For uncertainty:

I cannot determine that safely because the anchor collection date, bin pattern, or rota index is missing.

Cancelling swaps

Residents may cancel a previously recorded swap.

A swap cancellation must be persisted in state. Do not delete the original swap record. Mark it as cancelled instead.

Cancelled swap records must not affect rota calculations or schedule listings.

Swap records should have stable IDs such as:

swap-0001
swap-0002
swap-0003

When a swap is recorded, report the swap ID. When a resident asks to cancel a swap: 1. Identify the swap by its ID. 2. If no ID is provided, list active swaps and ask for the ID. 3. Mark the matching swap as cancelled. 4. Record: * cancelled_at * cancelled_by * optional cancellation_reason 5. Confirm cancellation. 6. Do not physically delete the swap from the state file.

Command:

scripts/bin_vader.py cancel-swap swap-0001 --cancelled-by "NAME"

Listing swaps:

scripts/bin_vader.py list-swaps

Cancellation response:

Cancelled swap-0001.

If a cancelled swap appears in state, ignore it when calculating: * tonight's bin responsibility * next collection * schedule listings * reminders

Existing swaps without IDs should be migrated manually or by adding IDs once. Example:

{
  "id": "swap-0001",
  "type": "exchange",
  "flat_a": 3,
  "flat_b": 6,
  "collection_date_a": "2026-06-05",
  "collection_date_b": "2026-07-31",
  "recorded_by": "Nigel",
  "recorded_at": "2026-06-01T18:00:00+01:00"
}

Schedule listing

Use this when a resident asks for the next few weeks, next N weeks, upcoming bin nights, or the rota schedule.

The skill may list future bin nights and collections for up to 12 weeks maximum.

Rules:

  • Accept requests from 1 to 12 weeks.
  • Reject requests above 12 weeks.
  • Do not silently truncate requests above 12 weeks unless the user explicitly asks for the maximum allowed range.
  • Use the deterministic rota script, not language-model reasoning.
  • Include:
  • bin night day
  • bin night date
  • collection day
  • collection date
  • bin type
  • responsible flat
  • swap or override notes, if any
  • Apply manual overrides first.
  • Apply swaps second.
  • Respect bank-holiday shifts.

Command:

scripts/bin_vader.py schedule N

Safety and reliability

  • Do not guess missing anchor state.
  • Do not silently change rota state.
  • Do not treat natural conversation as a confirmed swap unless the intent is explicit.
  • Do not rely on the council website as the sole authority.
  • Do not use LLM reasoning to calculate dates when deterministic code is available.
  • All reminders must be generated by cron or another deterministic scheduler.

WhatsApp group activation

When operating inside the WhatsApp group chat, this skill must only run after the agent has been explicitly addressed with:

Hey Bin Vader

Case and comma differences are acceptable.

Examples that activate the skill:

Hey Bin Vader, is tonight bin night?
hey bin vader whose turn is it?
Hey, Bin Vader list the next 6 weeks
Hey Bin Vader Flat 3 and Flat 6 are swapping 2026-06-05 and 2026-07-31

Examples that must be ignored silently:

Is it bin night?
Whose turn is it?
I think Flat 4 has the bins this week.
Can someone take my turn?
The bins are overflowing again.

It does not apply to: * deterministic scheduled reminders * direct CLI commands * admin commands outside the WhatsApp group * tests