<commit_before>---
title: "Tweeting for 10,000 Years: An Experiment in
  Autonomous Software"
published_at: 2018-07-20T13:41:22Z
location: San Francisco
hook: Using the principles of a 10,000 year clock to build
  a program that's intended to run for a very long time.
---

Deep inside a mountain in Texas, a clock is being built.
Unlike other clocks, this one is designed to outlast every
other invention of humankind, carefully engineered to
maximize longevity on a scale of time that's
incomprehensible to our most fundamental intuitions.

The counterweight for its drive mechanism is housed in a
hollowed out shaft that's 500 feet high and 12 feet in
diameter. It's the size of a small car and weighs an
unbelievable 10,000 pounds. The clock's periodic chimes are
controlled by 20 huge gears stacked on top of one another
-- each of which is 8 feet in diameter. It keeps time
through a 6-foot pendulum assembly terminating with
football-sized titanium weights that swing as unhurriedly
as one might imagine from such a leviathan, taking a full
ten seconds to move all the way back and forth. Components
are machined to within tolerances of a fraction of an inch,
rather than thousandths of an inch common in similar
devices, so that they'll keep working as time takes its
inevitable toll through expansion and rust.

!fig src="/assets/10000-years/orrery.jpg" caption="The design of the orrery to be used in the 10,000 year clock. It shows the relative position of six human-eye visible planets in our solar system."

If all goes well, the clock will keep time for 10,000
years. It's called the "[Clock of the Long Now][clock]" and
is a project of the [Long Now Foundation][longnow], who aim
to foster that values long-term planning and
responsibility, and counteract what seems to be an
accelerating trend towards an ever shortening attention
span that we see in society today. Their scale is one of
centuries and millennia, and they aim to construct
frameworks that will be functional for 10,000 years and
beyond. As a reminder of this charter, the Long Now
represents years in five digits instead of four -- under
their calendaring system, it's the year 02018.

## How to tweet as long as possible (#tweeting)

Software may not be as well suited as a finely engineered
clock to operate on these sorts of geological scales, but
that doesn't mean we can't try to put some of the 10,000
year clock's design principles to work. As seen by the
short functional lifetime of most software, and its
tendency to continually complexify and bloat, our industry
is one that's reliably short-sighted when it comes to
building products that will last.

Software does have some advantages for longevity compared
to a mechanical apparatus. Especially in the age of the
cloud, a well-designed program isn't dependent on any
single host. It can be moved around as the hardware below
it succumbs to the physical realities of entropy, and rely
on its underlying platform to stay stable thanks to the
efforts of human maintainers.

I wanted to write a little experiment inspired by the
10,000 year clock to see how long I could make a simple
program last without my intervention. It's called
[Perpetual][perpetual], and it has the simple task of
posting a total of ten pre-configured tweets to my timeline
on something close to an exponential scale; the last being
very optimistically scheduled to fire 10,000 years from
now. The first of them went out just a few minutes after
this article was published.

_A screenshot of that tweet goes here._

Each tweet, or "interval", is prefixed with a magic string
and number like **LHI001** (LHI stands for "long heartbeat
interval") so that the scheduled tweets are recognizable,
and so that the program can easily find the last one that
it published. Here's the intended timeline:

<figure>
  <div class="table-container">
    <table class="overflowing">
      <tr>
        <th>Interval #</th>
        <th>Tweet prefix</th>
        <th>Scheduled time</th>
      </tr>
      <tr>
        <td align="center">0</td>
        <td align="center">LHI000</td>
        <td align="center">Today</td>
      </tr>
      <tr>
        <td align="center">1</td>
        <td align="center">LHI001</td>
        <td align="center">1 day (from now)</td>
      </tr>
      <tr>
        <td align="center">2</td>
        <td align="center">LHI002</td>
        <td align="center">1 week</td>
      </tr>
      <tr>
        <td align="center">3</td>
        <td align="center">LHI003</td>
        <td align="center">1 month</td>
      </tr>
      <tr>
        <td align="center">4</td>
        <td align="center">LHI004</td>
        <td align="center">1 year</td>
      </tr>
      <tr>
        <td align="center">5</td>
        <td align="center">LHI005</td>
        <td align="center">5 years</td>
      </tr>
      <tr>
        <td align="center">6</td>
        <td align="center">LHI006</td>
        <td align="center">10 years</td>
      </tr>
      <tr>
        <td align="center">7</td>
        <td align="center">LHI007</td>
        <td align="center">100 years</td>
      </tr>
      <tr>
        <td align="center">8</td>
        <td align="center">LHI008</td>
        <td align="center">1,000 years</td>
      </tr>
      <tr>
        <td align="center">9</td>
        <td align="center">LHI009</td>
        <td align="center">10,000 years</td>
      </tr>
    </table>
  </div>
  <figcaption>The scheduled publication time for each tweet/interval.</figcaption>
</figure>

And here's the code that checks for old intervals and
decides whether a new one should be posted (somewhat
simplified for succinctness):

``` go
func Update(api TwitterAPI, intervals []*Interval, now time.Time)
        (int, error) {

    it := api.ListTweets()

    for it.Next() {
        lastTweet = it.Value()

        id, ok = extractIntervalID(lastTweet.Message)
        if ok {
            break
        }
    }
<commit_msg>"Brevity" is a better word<commit_after>---
title: "Tweeting for 10,000 Years: An Experiment in
  Autonomous Software"
published_at: 2018-07-20T13:41:22Z
location: San Francisco
hook: Using the principles of a 10,000 year clock to build
  a program that's intended to run for a very long time.
---

Deep inside a mountain in Texas, a clock is being built.
Unlike other clocks, this one is designed to outlast every
other invention of humankind, carefully engineered to
maximize longevity on a scale of time that's
incomprehensible to our most fundamental intuitions.

The counterweight for its drive mechanism is housed in a
hollowed out shaft that's 500 feet high and 12 feet in
diameter. It's the size of a small car and weighs an
unbelievable 10,000 pounds. The clock's periodic chimes are
controlled by 20 huge gears stacked on top of one another
-- each of which is 8 feet in diameter. It keeps time
through a 6-foot pendulum assembly terminating with
football-sized titanium weights that swing as unhurriedly
as one might imagine from such a leviathan, taking a full
ten seconds to move all the way back and forth. Components
are machined to within tolerances of a fraction of an inch,
rather than thousandths of an inch common in similar
devices, so that they'll keep working as time takes its
inevitable toll through expansion and rust.

!fig src="/assets/10000-years/orrery.jpg" caption="The design of the orrery to be used in the 10,000 year clock. It shows the relative position of six human-eye visible planets in our solar system."

If all goes well, the clock will keep time for 10,000
years. It's called the "[Clock of the Long Now][clock]" and
is a project of the [Long Now Foundation][longnow], who aim
to foster that values long-term planning and
responsibility, and counteract what seems to be an
accelerating trend towards an ever shortening attention
span that we see in society today. Their scale is one of
centuries and millennia, and they aim to construct
frameworks that will be functional for 10,000 years and
beyond. As a reminder of this charter, the Long Now
represents years in five digits instead of four -- under
their calendaring system, it's the year 02018.

## How to tweet as long as possible (#tweeting)

Software may not be as well suited as a finely engineered
clock to operate on these sorts of geological scales, but
that doesn't mean we can't try to put some of the 10,000
year clock's design principles to work. As seen by the
short functional lifetime of most software, and its
tendency to continually complexify and bloat, our industry
is one that's reliably short-sighted when it comes to
building products that will last.

Software does have some advantages for longevity compared
to a mechanical apparatus. Especially in the age of the
cloud, a well-designed program isn't dependent on any
single host. It can be moved around as the hardware below
it succumbs to the physical realities of entropy, and rely
on its underlying platform to stay stable thanks to the
efforts of human maintainers.

I wanted to write a little experiment inspired by the
10,000 year clock to see how long I could make a simple
program last without my intervention. It's called
[Perpetual][perpetual], and it has the simple task of
posting a total of ten pre-configured tweets to my timeline
on something close to an exponential scale; the last being
very optimistically scheduled to fire 10,000 years from
now. The first of them went out just a few minutes after
this article was published.

_A screenshot of that tweet goes here._

Each tweet, or "interval", is prefixed with a magic string
and number like **LHI001** (LHI stands for "long heartbeat
interval") so that the scheduled tweets are recognizable,
and so that the program can easily find the last one that
it published. Here's the intended timeline:

<figure>
  <div class="table-container">
    <table class="overflowing">
      <tr>
        <th>Interval #</th>
        <th>Tweet prefix</th>
        <th>Scheduled time</th>
      </tr>
      <tr>
        <td align="center">0</td>
        <td align="center">LHI000</td>
        <td align="center">Today</td>
      </tr>
      <tr>
        <td align="center">1</td>
        <td align="center">LHI001</td>
        <td align="center">1 day (from now)</td>
      </tr>
      <tr>
        <td align="center">2</td>
        <td align="center">LHI002</td>
        <td align="center">1 week</td>
      </tr>
      <tr>
        <td align="center">3</td>
        <td align="center">LHI003</td>
        <td align="center">1 month</td>
      </tr>
      <tr>
        <td align="center">4</td>
        <td align="center">LHI004</td>
        <td align="center">1 year</td>
      </tr>
      <tr>
        <td align="center">5</td>
        <td align="center">LHI005</td>
        <td align="center">5 years</td>
      </tr>
      <tr>
        <td align="center">6</td>
        <td align="center">LHI006</td>
        <td align="center">10 years</td>
      </tr>
      <tr>
        <td align="center">7</td>
        <td align="center">LHI007</td>
        <td align="center">100 years</td>
      </tr>
      <tr>
        <td align="center">8</td>
        <td align="center">LHI008</td>
        <td align="center">1,000 years</td>
      </tr>
      <tr>
        <td align="center">9</td>
        <td align="center">LHI009</td>
        <td align="center">10,000 years</td>
      </tr>
    </table>
  </div>
  <figcaption>The scheduled publication time for each tweet/interval.</figcaption>
</figure>

And here's the code that checks for old intervals and
decides whether a new one should be posted (somewhat
simplified for brevity):

``` go
func Update(api TwitterAPI, intervals []*Interval, now time.Time)
        (int, error) {

    it := api.ListTweets()

    for it.Next() {
        lastTweet = it.Value()

        id, ok = extractIntervalID(lastTweet.Message)
        if ok {
            break
        }
    }

{'fraction_non_alphanumeric': 0.0890988862639217, 'fraction_numerical': 0.02362470469119136, 'mean_word_length': 3.240787119856887, 'pattern_counts': {'":': 0, '<': 195, '<?xml version=': 0, '>': 195, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '334940', 'n_tokens_mistral': 3662, 'n_tokens_neox': 3314, 'n_words': 1572}