Feature Announcement: General Mercy

Wednesday, August 22, 2018
By bsoule

image of a hospital building

In the beginning, God created the heavens and the Earth and derailing on a Beeminder goal meant getting a week of respite. That is still in fact the default. After derailing you get a week of safety buffer. It gives you time to re-evaluate how the goal is working, and time to adjust your Yellow Brick Road or even quit if you’re over it. The default week off makes this possible because things that make the road easier have a one-week delay.

But Beeminder users are very hardcore and wanted an option for no-mercy derailments. In 2013 we added such an option.

For convoluted technical reasons (not that the technical reasons are insurmountable; just not on the table quite yet because, well, it’s technical) “no-mercy” actually allows 2 safe days that you can do nothing after derailing before you’ll derail again. And the original week of respite is actually 9 days of safety buffer.

The point is, until now you had a choice between 2 days of mercy after derailing or 9 days of mercy. The first bit of news is that now you can choose any amount of mercy in between. Exciting! Or at least handy, for some of you.

Different Types Of Safety Buffer

What we’ve said so far applies to Do More goals and glosses over the situation with Do Less. Do Less goals don’t take days of buffer. A keen-eyed Beeminder user might have noticed this when ratcheting a goal. For ratcheting most goals we ask how many days of safety buffer you want to keep, and then move the road in the x-direction, to the left.

But for Do Less goals we talk about your buffer in terms of your goal units (pages, hours, servings, etc) and the hard limit, not days until derailment. For example “limit +2 cups of coffee today” for a coffee goal. When we recommit such a goal, we give you buffer in the y-direction by moving your road up, above your datapoint.

The recommit buffer setting for Do Less goals is not restricted to integer values from 2 to 9. You can give any non-negative value.

But Weight, There’s More

Most goals take either x- or y-buffer, but for weight goals we now give you both. Weight goals are special snowflakes.

Needing a configurable y-buffer for weight road recommits was actually the whole instigator for General Mercy. It all started with a footnote [1] on a now long-overdue blog post about the changes we’ve been making to weight roads.

“Weight goals are special snowflakes”

Without getting into the why (I swear, that blog post is coming, now that this one is done!), if you’ve started a weight road recently, you might have noticed that they are now razor thin and ask you for an explicit amount of buffer to start you off with — your maximum daily weight fluctuation. We give you that buffer when you start, by starting your razor road that much above your initial datapoint. It’s up to you to maintain that much buffer if you want to stay robust to your max possible weight fluctuation.

But we didn’t restore any safety buffer in the y-direction when you derailed and were recommitted. We only gave you the x-buffer, and put your razor thin road exactly on top of the derailing datapoint.

Personally I love that. I hated how in the old version with wide roads, if I derailed my weight goal my road moved to put my offending datapoint right in the middle of the road, with a big wide buffer above me. That meant that one bad day not only cost me money, it was allowed to compound into many bad days in a row, which made it easy to backslide. Now if I screw up, the road recommits with me right on the edge. I get a little buffer above where the road previously was (because my derail point is necessarily above the old road), while still having to stay in the game and making progress.

But not everyone loves that. Some people want to be more careful around the edge and get a merciful recommit even on weight roads. With a razor-thin road, x-buffer was no longer sufficient to give you that. We needed to introduce y-buffer to the weight road recommits and we needed to let you choose how much you wanted. So we generalized the concept of mercy (normal derails with a week of respite) vs no-mercy and let you specify how much mercy to get.

Global Mercy

“We generalized the concept of mercy vs no-mercy and let you specify how much mercy to get”

If you know you want all your goals to always have 3 days of buffer after a recommit (or 5 or 2 or whatever), we’ve got you covered there too. There’s a default mercy setting in the New Goal Defaults section of your account settings that replaces the former “new goals default to no-mercy” checkbox. It asks for the number of days you want by default after a derail. That’s straightforward for goals that take x-buffer, but for goals with y-buffer, it works a little differently. We don’t collect a separate value for default-y-buffer in the New Goal Defaults, because any single amount wouldn’t make sense across all your Do Less goals. (Consider a “milligrams of caffeine” goal which allows 200mg per day vs an “hours of distracting time” RescueTime goal which allows 0.5h per day.)

Instead we use the daily rate of the goal, and multiplication technology to set a default that’s reasonable for each goal’s own unit-magnitude. [2] Namely, we set the goal’s recommit safety buffer to be \(N\cdot\mathit{dailyRate}\), where \(N\) is your default recommit mercy from New Goal Defaults. Weight goals [3] will not have y-mercy set that way; their y-mercy is just the maximum daily fluctuation that the user specifies.


 

And there you have it. We wanted to keep things as similar to the previous status quo as possible at first, but now that we’re pretty sure things are not insidiously broken, we’ll lift the 9 day restriction. [UPDATE: done as of UVI #2770!] We’re still working towards fixing the technical reasons behind the 2-day lower bound so that all you eager beavers can have beemergencies all day every day.


 

Footnotes

[1] Footnote-driven development FTW! (It’s actually a special case of Documentation-Driven Development, which is already a thing.)

[2] This is actually doing as we do for the initial starting buffer on a Do Less goal. When you start a new Do Less goal we give you a y-buffer of \(7\cdot\mathit{dailyRate}\).

[3] You might have noticed that we’ve referred only to Do More, Do Less, and Weight goals in this post. If you want to get super technical, well, first learn about \(\mathit{dir}\) and \(\mathit{yaw}\) in our API docs. All clear on the Four Platonic Goal Types? Great! So goals with \(\mathit{dir}\cdot\mathit{yaw}>0\) (Do More, Odometer, Weight Gain, Weight Loss, Inboxer, Net Calories) get x-buffer and goals with \(\mathit{dir}\cdot\mathit{yaw}<0\) (Do Less and Rationing) get y-buffer. But also so-called noisy goals (where the datapoints have random fluctuation) get y-buffer. So Weight goals get both x-buffer and y-buffer. Inboxer or Whittle Down goals are actually conceptually/structrually almost identical to Weight Loss goals but since we haven’t considered them noisy, they don’t get a y-buffer. (As you can perhaps tell, this was all surprisingly intricate to pick apart, refactor, and put back together. Especially for something that initially seemed eminently straightforward — generalizing a boolean parameter to a numeric one!)

Tags: , , , , ,