lesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it shipslesson 2 of 3 · batch plan and calendar — creative at volume, gated before it shipsbatch plan and calendar — creative at volume, gated before it ships
Checkpoint
One last thing before we move on. pass this to mark the lesson done, or skip and keep moving. hop to the next when you're ready.
Checkpoint: the full calendar gate, the one that runs before anything touches the scheduling tool.
Write gate(rows) returning a dict with three lists, each preserving
row order:
"schedule"— rows withstatus == "approved"AND a non-emptyapproved_by. These may enter the scheduler."blocked"— rows withstatus == "approved"but NO approver. These go back for a named sign-off, not into the scheduler."rejected"— rows withstatus == "rejected". These stay in the file as the record of what the team said no to.
The harness prints each list and a summary. The rows are the full relaunch calendar so far — including the teaser-story that's been sitting nameless since the gate first caught it. Expected output:
SCHEDULE 09-02 email launch-email (dana)
SCHEDULE 09-04 ads ad-set-a (sam)
SCHEDULE 09-05 email winback (sam)
BLOCKED 09-02 social teaser-story (no approver)
KEPT 09-03 social meme-post (rejected, stays in the file)
3 scheduled, 1 blocked, 1 rejected-and-kept