what the word indexes in the runtime
Accountability partner means one JSON field, read at 14:00 UTC.
Every article on this topic defines the word as a role: “someone who supports your goals,” “a peer who checks in on you.” True, and useless to a program. On vipassana.cool, a daily cron reads event.attendees[].responseStatus on your Google Calendar invite and asks one question: is that string equal to "declined"? That inequality is the full operational meaning of “accountable” on this site.
Four numbers that exhaust the meaning
If you collapse the word to what a program actually reads, every interesting claim fits into four constants. These are not motivational numbers. They are constants in the source.
Where “accountability” actually lives
Two humans on the left. One aggregator in the middle: the cron at /api/check-rsvp. Three outputs on the right: a Postgres row update, a notification email, and, in the “declined” case, an auto-end of the match. The word the page is about is the name of the aggregator.
Who reads what
The exact code, in the exact file
If you want to audit the claim directly, open src/app/api/check-rsvp/route.ts. Lines 119 to 137 are the entire semantic content of the word “accountable” on this product. Six lines of variable assignment, one conditional, one update call.
All the string values responseStatus can take
Google Calendar returns one of four canonical strings on a normal event, plus an internal fifth value the cron writes when the event has been deleted on both calendars. The word “accountable” resolves to “not declined and not deleted.”
What the daily 14:00 UTC tick actually does
The cron is the whole operational meaning of “is this partnership still accountable.” Six steps, executed in order, no branching except on the two attendee strings.
14:00 UTC: Vercel cron fires
Triggered by the line 'schedule': '0 14 * * *' in vercel.json. The request carries an Authorization header with the CRON_SECRET; any request without it is rejected at route.ts line 24.
Query active matches with a calendar event id
getActiveMatchesWithCalendar() returns every match row whose status is still live and whose calendar_event_id is not null. Matches that were never confirmed or never created a Meet event are skipped.
Fetch the Google Calendar event for each pair
For every row the cron calls GET /calendar/v3/calendars/primary/events/<eventId> with a refreshed access token. A 404 on the primary calendar triggers a retry against the mediar fallback calendar before concluding the event is gone.
Read the one JSON field that defines accountability
From event.attendees, find the entry whose email matches person_a_email, then the one whose email matches person_b_email, and pull each attendee's responseStatus. If missing, fall back to the string 'needsAction'.
Compare both values against the string 'declined'
The check at line 133 is an OR, not an AND. Either value equal to 'declined' is sufficient to auto-end the match via updateMatchStatus(match.id, 'ended', 'cron'). Everything else preserves the relation, even missed sits.
Email the operator on any RSVP change
rsvpChanges[] is assembled as the loop runs. If anything moved, a single summary email goes to i@m13v.com with a table of old and new statuses per pair and an 'Auto-ended' flag on the rows that crossed the 'declined' threshold.
What happens the moment one person clicks Decline
Between Gmail, Google Calendar, the Vercel cron, Neon Postgres, and the operator’s inbox, here is the sequence that runs from the tap to the ended status. The partnership dissolves without anyone being told by the product.
from decline click to ended status
Dictionary meaning vs runtime meaning
| Feature | Dictionary meaning | Runtime meaning |
|---|---|---|
| What the word indexes in the runtime | A relationship, roughly. No runtime at all. | One string field: attendees[].responseStatus. |
| How often the meaning is re-evaluated | Whenever the two humans feel like checking in. | Once a day, at 14:00 UTC, by a Vercel cron. |
| What ends the relation, officially | A mutual conversation. Sometimes just drifting apart. | responseStatus === 'declined' on the next cron tick. |
| What 'silent but still in it' resolves to | Ambiguous. Either person guesses at the other's state. | responseStatus stays 'needsAction' or 'accepted'. Relation holds. |
| Who is notified on status change | Sometimes nobody. Sometimes a long email. | Operator gets an email with old/new statuses per pair. |
| Is the definition checkable by anyone other than the authors | Not really. It lives inside the humans. | Yes. One file, one line, one string. |
the anchor fact
The word collapses to a six-character comparison
“Accountability partner” on this site means a person whose attendee entry on the shared Google Calendar event has a responseStatus value that is not the literal string "declined" at the most recent 14:00 UTC cron poll. The number of predicates the runtime evaluates to answer “are these two still accountable to each other” is 0.
Source: src/app/api/check-rsvp/route.ts:133 and the schedule line "0 14 * * *" in vercel.json.
A single cron run, in the log
A compressed sketch of one real-shape run of /api/check-rsvp. The numbers are representative; the shape is exact. One pair had a declined invite, one pair moved from accepted to tentative, the other 39 were unchanged.
Why collapse the word to a string comparison at all
A role description works for someone already in the relation, who wants to check in with the person they have. It does not work for a runtime that has to decide, once a day, whether to update a row in the matches table from “active” to “ended.” A runtime needs a signal it can read. The signal has to come from somewhere.
Google Calendar returns four well-defined strings for an attendee’s state. One of them is the one a human clicks when they are deliberately stepping out. Reading that one string is the narrowest responsible sampling the runtime can do. Everything else, silence, lateness, a missed sit, a quiet week, stays with the humans and their operator.
This is also why the service is free. Dropping a partnership on ambient silence would be expensive to the relation and easy to automate. Dropping it only on a deliberate click is inexpensive to everyone, and it is a boundary a donation-supported product can hold.
For anything beyond logistics, how to sit, how to meet difficulty, how to work with whatever arises in the mind, go to dhamma.org and an authorized assistant teacher at a 10-day residential course. That boundary is also part of what the word means here: this site handles scheduling; it does not handle practice.
Want to see the single-field meaning in action?
Book a short call and I will walk you through the exact matches row, the exact calendar event, and the exact JSON field the cron reads to decide whether your partnership is still live.
Frequently asked questions
What does 'accountability partner' mean on this site, in one sentence?
It means the other human whose email address is attached to the same Google Calendar event as yours, whose attendees[].responseStatus field in that event is not the literal string 'declined' when the /api/check-rsvp cron polls the calendar at 14:00 UTC every day. If either of the two responseStatus values is 'declined' on any daily poll, the partnership is auto-ended the same minute by updateMatchStatus(match.id, 'ended', 'cron') at src/app/api/check-rsvp/route.ts line 134. Nothing else changes that status automatically. Silence does not. A low reply rate does not. A missed sit does not. The only machine-readable predicate the runtime watches for 'accountable' is that one inequality on one JSON field, polled once a day.
Why is 'declined' a decline but 'needsAction' is not?
Google's Calendar API returns responseStatus as one of four canonical strings: 'needsAction' (the invite has not been answered yet), 'tentative' (the invitee marked it maybe), 'accepted' (the invitee said yes), and 'declined' (the invitee said no). The RSVP cron in route.ts lines 121 to 122 reads the string as-is. Line 133 asks whether either person's value is exactly 'declined'. Everything else, including 'needsAction' and 'tentative', is treated as still in the pool. The design is asymmetric on purpose. 'needsAction' is common, it happens any time Gmail just drops the invite into someone's mail without them tapping a button, and it would be a bad idea to end a partnership on the absence of a tap. 'declined' requires a deliberate click in Gmail or Calendar. The only signal the cron treats as final is the one a human had to affirmatively send.
What happens to a partnership on the day one person clicks 'Decline'?
Within 24 hours, at the next 14:00 UTC tick, the cron fetches the event, reads attendees, finds the string 'declined', updates the match row's status to 'ended' with source 'cron', stores the new calendar_rsvp_a and calendar_rsvp_b values, and queues an operator email. The email lands in i@m13v.com with a subject like 'Calendar RSVP update: 1 match changed (1 auto-ended)' and a table of the old and new statuses. No one tells the two meditators directly. Their intro thread goes quiet, the shared Meet URL stops being opened, and the operator sees the change on the admin dashboard. The relation does not formally announce its own ending because it never formally announced its own starting either; on this site both events are rows in the database that the operator reads.
If the cron only runs once a day, what does 'still accountable' mean for the other 23 hours?
It means the last reading of the JSON field was not 'declined'. Between cron runs the runtime has no live signal on whether you are still in the relation; it has only the last poll's answer and the heartbeat of meet_clicks rows written each time either of you hits the /meet/<token> link (src/app/meet/[token]/route.ts line 27). The design choice is that a daily cadence is enough. Meditation is a daily practice, not a minute-by-minute one, and the 14:00 UTC tick catches any intentional decline inside one calendar day. Anything shorter would be chasing ambient state at the cost of email volume; anything longer would let the relation drift out of sync with reality. One poll per day, on a field a human had to click, is the full sampling plan.
Why not also auto-end on silence or missed sits, not just 'declined'?
Because the runtime cannot distinguish a silent day from a traveling day from a sick day from a day the Meet URL was clicked on a phone that the server cannot see. Any automated reading of silence would be a false positive a meaningful fraction of the time, and a false positive here would dissolve a real partnership that both humans still believe in. The only signal the cron treats as final is one that required a human to affirmatively press a button labeled 'Decline'. Everything softer stays in the pool and is left to the pair to resolve with each other or with the operator. This is the boundary between what a program can know about the relation and what it cannot.
Is the word 'partner' symmetric in this signal too?
Yes. If either person's responseStatus is 'declined', the match ends. The check at line 133 is an OR, not an AND. A unilateral click by one participant is sufficient to close the relation from the runtime's point of view, even if the other participant never touched their invite and would have happily kept sitting. The symmetry is that either side can end it alone; the asymmetry is that nobody can unilaterally keep it alive once the other party has declined. This is the same shape the word carries everywhere else on the product. Two humans enter a partnership together and either one of them can leave it alone.
Does any of this tell me how to practice or how to handle a difficult sit?
No, and nothing on this site should. Questions about technique, posture, how to work with sensations, or how to respond to difficulty on the cushion are for an authorized assistant teacher at a 10-day residential course, arranged through dhamma.org. This page is about what a matcher and a cron do with two email addresses and a Google Calendar event. The technique itself stays with the tradition and its authorized teachers. The product handles logistics. The practice is yours and your teacher's.
Where exactly are the source lines so I can verify?
Four files. The cron schedule is in vercel.json ('schedule': '0 14 * * *' for '/api/check-rsvp'). The check itself is at src/app/api/check-rsvp/route.ts lines 119 to 137, with line 121 extracting rsvpA, line 122 extracting rsvpB, line 133 comparing both against the string 'declined', and line 134 auto-ending the match. The heartbeat counterpart is src/app/meet/[token]/route.ts line 27, which inserts into meet_clicks every time either partner hits their personal Meet URL. The third piece is src/app/api/expire-matches/route.ts line 11, where a separate daily cron at 12:00 UTC drops any match that has been stuck in 'confirming' status for more than 3 days without a reply. Together those four files are the complete machine-readable definition of accountability on this product.
Same word, different layer of the operational definition.
Related pages
Accountability partner definition
Seven predicates and one integer, sixty. The matcher's pre-pair filters.
Define accountability partner
The URL is the relation. One permanent Meet link with RRULE:FREQ=DAILY.
What is an accountability partner
A peer, not an overseer. Four symmetric similarity traits in buildCommonTraits.
Accountability partner app
The inbox as state machine. No dashboard, no push, just one daily email.
Vipassana daily practice
How a daily cadence actually becomes a cadence and not a streak.
Practice Buddy, how it works
Signup, 24-hour cooldown, auto-match, confirmation, calendar event, all in one view.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.