Canonical program page: Daily Cards — the same program, ruled by Steven 2026-08-13/14 over the Oregon-hikes practice process (discovered after this page was written). That page carries the program law: day blocks inside the r184 document (its P1), users.timezone derived from zip with 6 AM person-local sends (its P2), the offer card (P3), the dispatcher (P4), the day card with Did-it / note / Share (P5). This page carries the deeper machinery (tables, ledger events, walker detail, three-surface work). The 2026-08-18 rulings below are recorded as amendments on BOTH pages; where the two pages otherwise differ, Daily Cards governs. Builders read both, build once.
An agent working a target can deliver the work as a timed series instead of one lump. Example: a 30-day workout program, one workout arriving each day. The agent files the entire package up front with a schedule attached; our system releases one piece per day. The agent never has to show up mid-drip, and the drip window is never billed against the agent's delivery time.
Why the system drips and not the agent: agents are episodic and often unreachable (no prod agent is reachable today). A design that needs an agent awake on day 22 will miss day 22, and the person eats the silence. The agent's job ends when the full package is filed and approved; the calendar after that belongs to us.
Why it matters: a 30-day plan handed over as one document gets read on day 1 and abandoned by day 5. A drip turns the deliverable into a rhythm — it shows up in the person's feed and pocket on the day it matters. That is the connection this platform is for.
| # | Ruling |
|---|---|
| D1 | Approval and payment at filing. The agent sends the FULL list. The person must approve the full list before anything drips. That approval is the milestone approval — money releases there, on the normal lapse clock (reminders 3/7/12, deem at 14). The drip that follows is fulfillment, not an open approval question. |
| D2 | Channel pick at approval. Feed is ALWAYS on. When the person approves the list they select delivery channels: the feed card always lands (not optional); email and text are individually selectable toggles. |
| D3 | Mid-delivery control lives on the target card: the person can pause/resume or stop the remaining schedule and can independently turn email/text notifications on or off. Pause shifts unopened pieces forward; stop is final for unopened pieces; released cards remain. The feed lane has no independent notification toggle. |
| D4 | Target success and schedule activity are separate states. Approval can resolve the target successfully while the target card continues to show the timed delivery as Active, Paused, or Stopped. After normal completion, that same control area shows Completed and lets the person Schedule again from the approved package. |
| D5 | Delivery cards are feed-native and shareable. Agents deliver into the feed as the person requested; those cards behave like feed cards, and the person can SHARE one — at which point it goes into the house feed. |
| D6 | The drip is never the agent's fault or the agent's clock. The agent's delivery time on the bench is measured to package-filed. A missed release is a system fault (same spirit as the lapse law: lapse is never the agent's fault). Bench/leaderboard scoring counts the deal delivered at approval. |
| D7 | We need the walker. The release timer rides the hourly sweep, and the prod sweep cron (currently absent) must be installed. A drip system whose timer does not run silently delivers nothing — the worst failure mode. This item is non-optional and blocks go-live of the feature. |
Two additive tables. Idempotent prod-replay SQL ships in the commit AND in app/scripts/sql/, per standing law. No changes to existing tables beyond what is listed.
id, deal_id / step_id (whichever step filed it), goal_id, maker_idstatus: proposed → approved → delivering → completed (plus rejected)piece_count, cadence (v1: daily only), starts_on (date), approved_atemail_enabled, sms_enabled (booleans; the feed lane has no column — it is always on by law D2/D3)id, schedule_id, seq (1..N), titledocument — a sectioned document in the r184 block format (same shape file_document_outcome takes; walls of plain text are refused)scheduled_for (date), status: sealed → released (or missed, system-fault marker), released_atledger_event_id of its release event once releasedSealed means sealed: pieces are not readable by the person before their day — not in released_materials, not via any read endpoint. released_materials / released_materials_count keep the always-present-including-zero law and grow by one per release.
The closed event-type list grows by four (canonical RFC8785 envelope + event_hash like the other 41; remember the two-sync rule: rerun extract_rules.py / citations and bump the census literal or 5 tests fail):
| Event | When |
|---|---|
schedule.filed | Agent files the full package + schedule on a step |
schedule.approved | Person approves the full list (the milestone; money releases per D1), or explicitly schedules that already-approved package again with cause repeat and no second money release |
delivery.released | The walker unseals one piece on its day — one event per piece, the single seam every channel fans out from |
schedule.completed | Last piece released; target card changes from live controls to Completed + Schedule again |
A missed day is recorded on the piece row (missed) and released late by the next sweep pass; it is logged as a system fault, never attributed to the agent (D6).
target_path_sweep.py (hourly, pudding crontab, env --chdir pattern) gains a release pass:
for each schedule in status delivering:
for each piece where scheduled_for <= today(person-local) and status = sealed:
release piece -> write delivery.released -> fan out (feed / email / sms)
if all pieces released: schedule -> completed, write schedule.completed
Release is idempotent (a released piece is skipped), so a double-run or a late catch-up run is safe.
BLOCKER (D7): install the sweep cron on PROD. It has been on the open list since go-live. This feature does not ship until the prod walker runs and is verified (a piece scheduled for today actually releases within the hour on prod).
Everything hangs off delivery.released. One seam, so the channels can never disagree about what was delivered.
| Channel | Behavior |
|---|---|
| Feed card (always) | New card type in _cards.html: "Day 14 of 30 · <piece title>", opens the document reader (r169 reader, bullets bug already fixed). Rides high in the feed order on its day, sinks once seen like everything else. Carries the agent's name/A-number. |
| Email (toggle) | Piece title + link to the card/reader via Book of Houses email. |
| Text (toggle) | Short nudge + link. Requires a new permitted event in the want-flow SMS allowlist (delivery.released). Interaction with the 20-text budget is an OPEN ruling below. |
The successful target card shows the schedule separately as Active, Paused, or Stopped, with its serving-through date or progress. Pause/resume and stop act on the whole schedule; email and text controls continue to flip email_enabled / sms_enabled independently. The feed lane shows no independent notification toggle.
Per D5: a Share action on the delivery card, person-only. Sharing creates a house-feed post in the person's house wrapping a snapshot of the piece (the person owns the delivered work; sharing is their call, so consent is built in).
released pieces only — never sealed ones.A capability that is not on agent-api.openapi.json AND agent-skill.md AND the MCP tool list does not exist. All three land in the same pass:
file_delivery_schedule — files the full piece list + schedule on a step (analogous to file_document_outcome, but N dated documents). Contract path + skill section + MCP tool together.current_step and /me/attention. No new polling loop.schedule.completed, then delivered — the agent's score never waits on the calendar.| Item | |
|---|---|
| open | SMS budget: do drip texts count against the 20 free want-flow texts? A 30-day program is 30 texts. Recommendation: drip texts do not consume the free budget (the person asked for them), or they consume it and fall back silently to email+feed when it runs out. |
| ruled | Release hour / timezone: RESOLVED by Daily Cards P2 — users.timezone derived from the address/zip the platform already collects, editable in Settings, asked only when underivable; every send fires at 6:00 AM the person's time, never ours. |
| ruled | Pause / stop: pause freezes unopened pieces and resume shifts their remaining dates; stop permanently closes the unopened remainder. Already-released cards remain available. |
| open | Cadence beyond daily (weekly, custom dates): v1 is daily only. The schema (per-piece scheduled_for) already permits arbitrary dates so this is a gate-loosening later, not a migration. |
| open | Rule numbers: D1–D7 become numbered rules on the-rules page (gray chips) with one cause line each in protocol/rule-causes.md. Numbers assigned when written. |
| Phase | What | Done when |
|---|---|---|
| P1 to build | Tables + ledger event types + rules written (gray chips) + census/citation syncs | SQL replayed on staging DB; rules render; tests green |
| P2 to build | Agent surface: file_delivery_schedule on contract + skill + MCP, with REJ gates | An agent files a real schedule over the API and it lands proposed |
| P3 to build | Person approval: full-list review card + channel picker (feed locked on, email/text toggles) wired to the milestone release | Approve on staging releases funds (fake/test mode) and flips schedule to delivering |
| P4 to build | Walker release pass + prod sweep cron installed | A due piece releases within the hour on staging AND the prod cron is running |
| P5 built | Fan-out: feed delivery card, email, SMS allowlist event; successful target-card state plus pause/resume, stop, and notification controls | A released piece shows in feed + chosen channels; pause/resume and stop preserve released cards |
| P6 to build | Share to house feed (snapshot post, agent attribution, passport link) | A shared piece renders in the house feed and survives deal changes |
Each phase is verifiable on staging on its own. Chips (rules and board) flip only on live-verified behavior, per move-over law. Prod gets the batch only on Steven's explicit go.