One Week in Hacker Paradise

2014-09-06 07.57.13

Paradise. That is how it was pitched. Hacker Paradise, to be exact: “a programming retreat in the beautiful country of Costa Rica” where “participants come from all over to get away from the hustle and bustle of everyday life and spend 12 weeks writing code and building things with other passionate individuals”.

hackerparadise_4

I was technically not a participant of Hacker Paradise. I was joining as a plus-one of a Hacker Paradise facilitator/mentor: ZYX. I had technical creds of my own, not to be dismissed as a mere tag-along simply there to soak in the sun and wade in the ocean. That said, coming in, I had a tinge of intimidation, of impostor syndrome, of a party crasher. Not being a one of the “chosen ones” cherry-picked from a pool of already self-selecting applicants, I anticipated the feeling of “what is she doing here?” eyes on me. Plus, the caliber of participants was quite impressive in itself: digital producer turned Mozilla-Knight fellow turned Times data journalist, science PhD turned med student turned data scientist, English major turned poker player turned developer (and owner of a popular coffee shop to boot!). Meeting everyone in flesh and listening to their “this how amazing I am” stories was going to be a bit like a more intimidating version of teenage summer camp where you go around the circle sharing “What is your favorite …?”.

My favorite food is Kraft mac & cheese!”

Oh, my favorite food is my homemade mac & cheese “seasoned with salt, pepper and nutmeg, and combined with butter, grated Gruyère and Parmesan cheeses, and very red tomato purée, and combined with a julienne of very lean cooked ham, tongue, mushrooms and truffles, heated in Madeira”.

“My favorite color is red.”

“Oh, red? Mine is vermilion.”

That first night though, what surprised (and intimidated) me most was not the intensity of everyone’s “well, I am …” stories but the silence that permeated Paradise.

* * *

After a prolonged 24+ hour flight delay from Croatia to the Dominican Republic to Costa Rica and a 6+ hour drive from the San Jose airport to Playa Carrillo, home of Hacker Paradise, I unloaded my bags and immediately headed up to the restaurant/bar area (the “Summit”) where the early arrivals were hanging out. We had arrived around dinner time and the sun had already set the scene to black. With a rumbling stomach, I was ready to gobble up my first taste of Costa Rican food: casado con carne or some other rice-and-beans with plantains dish. I brought with me only the necessities – or so I thought: myself and my appetite.

2014-09-13 12.03.54

I was also eager to put faces to LinkedIn profiles: who were these adventurers, these nomads, these dreamers coming to a remote village in Costa Rica for 3 months to hack on technology?

That excitement was soon dampened though and replaced by heavy weight, much like the humidity that was already drenching me in dripping sweat.

As I stepped into “Paradise”, all I heard was silence and all I felt was stillness.

***

A long table of 6-7 people were heads down on their laptops. No one budged. No acknowledging smile let alone a welcoming “hello”. This was in exaggerated contrast to the vibrancy of the “Summit”: every flat surface – from the walls to the tables – were hand-painted with tropical scenes; ceiling beams were dripping with rainbow hammocks.

2014-09-06 08.50.56

Sure, I was only the plus-one and other than a brief intro on the Hacker Paradise Facebook group, I wasn’t involved in the pre-retreat chatter online. I could have been a random resort guest. But by my side was ZYX. He was a Hacker Paradise facilitator, second in command, and active in the pre-retreat Facebook-ing. And, unlike my less pattern-matchable attire, he did not look like a random resort guest with his Meteor t-shirt and pre-release Google watch).

But no one stood up from their seats to say hello — only a few glances up and back down to their laptops.

Strange but I shook it off. Maybe they were all really in the flow and couldn’t break from their coding. Maybe they were all shy folks — a feeling I understood being the shiest of the shy.

We sat down at the end of the table and ZYX – an extrovert to my introvert – started chatting with the guy next to him. Not having any distractions (laptop or cellphone) and not having the chutzpah or rank to interrupt with a “Hey, whatcha working on?“, I leaned in on ZYX’s conversations nearby.

“What are you working on?”

“… Ruby … poker … bets …”

“Ah, that’s cool! How are you implementing …?”

“…”

“You should look into … Excited to see what you build!”

He continued down the row.  Barely audible even one chair away, he was soon too far for me. No longer able to gracefully extend my torso or perk my ears to hear more than a mumble of jumble, I recoiled in my seat twiddling my thumbs. After a much-too-long 15 minutes of staring at the backs of laptops (the many stickers helped pass the awkward seconds with visual narratives), I had to escape.

I headed over to the bar and plopped myself next to a middle-aged brunette who was not engrossed in anything in particular: no cellphone, no laptop, no iPad, no book. Ah, perfect! But after the polite chat of “How are you? What’s your story?” winded down, I again found myself in eye-wandering, lip-pursing silence.

The Hacker Paradisers were still heads-down and ZYX still had half the length of the table left. I estimated that with 4 persons remaining I had at least 40 more minutes until his lap was complete and I sure wasn’t going to return to the table empty-handed to wait. Without a room key to retrieve my laptop or escape into privacy, my only reprieve was circling the grounds: down the stairs, past the cabins, up the stairs, through the pool area, down the stairs, past the cabins, down the stairs, past the cabins, up the stairs, through the pool area.

For almost one hour, I walked in the wet darkness, my only companions being the companions I did not want to keep: mosquitos.

* * *

That first night was actually an anomaly. It could have become the status quo but the next day, fresh blood arrived with self-proclaimed title of “Dream Catalyzer”. He too had noticed how only a couple people stood up from their tables to introduce themselves when he arrived. Unlike me, he would not let it slip. Soon enough, the “Dream Catalyzer” convinced the facilitators that – for the sake of much-needed team building – icebreakers were worth any initial embarrassment. And so with that, for two consecutive nights, ridiculousness, awkwardness, laughter (and a bit of consternation) ensued as we circled around shoulder-to-shoulder breaking the ice with “Where the West Wind Blows”, “Yes and …”, “I have Failed!” and many more.

  • “Where the West Wind Blows”: sharing common interests and experiences
  • “Yes and …”: communicating with positive reinforcement however ridiculous
  • “I have Failed!”: not being ashamed of failure but owning it

The icebreakers brought the group together, literally, to get off their chairs and out from behind their laptops. It was not without the mortifying dread of “Are you seriously going to make me [run around playing musical chairs] [beatbox about myself] [yell “I have FAILED!” while in a yoga pose] […]?”, but by improv night’s end, we had gotten to know each other beyond the “Hi, my name is … I work on …”: our near-death experiences, our secret crushes on Taylor Swift, our guilty pleasures watching odd animal coupling videos, etc.

Soon more activities enlivened the initial reserve. The tables (for working and eating) initially set up as a long station were broken up to encourage more intimate conversations between the participants. Facilitators scheduled morning standups, office hours, and demo nights. Participants organized activities to break up their work day: morning runs, surfing lessons, and game nights.

Day after day, Paradise become less a group of individuals working remotely at the same retreat but a community of individuals working together to build, learn, and enjoy working (and living) in “Paradise”.

2014-09-11 18.28.14

* * *

All this said, this is more a story of me than of Hacker Paradise. In the one week I was at Hacker Paradise, despite all the talk of walking into downturned heads and hoping instead for a “Hey, welcome! Join us in Paradise!” bear hug, if I wanted to make that connection, I needed to initiate it. I needed to have the courage to create that connection myself, not expect it as something someone else would do nor something that would happen spontaneously.

The “Dream Catalyzer” knew this.

I wasn’t able to get quite out of my shell by the end of my one-week stay at Hacker Paradise. I remained on the sidelines, sort-of a self-prophecy of the “what is she doing here?” insecurity I came in with. And while my nerves will still probably get the best of me when stepping into the social unknowns such as Hacker Paradise, I’ll probably not be alone in my jitters. So, from hereon, I will challenge myself to make each “hello” an icebreaker of sorts — because what’s the worse that can happen? I may look silly and sound ridiculous but at least I won’t be stuck in awkward silence.

So I say, my parting words:

“The west wind blows to anyone who is a Code for America fellow!”

“Yes and … let’s build a social app that let’s you have a conversation only one word at a time to only people in the same room as you!” 

“I have FAILED! I have FAILED! I have FAILED!

 

Review: The Art of Readable Code

Title: The Art of Readable Code: Simple and Practical Techniques for Writing Better Code

Authors: Dustin Boswell & Trevor Foucher

art_of_readable_code

Contents

  1. Code Should Be Easy to Understand
  2. Packing Information into Names
  3. Names that Can’t be Misconstrued
  4. Aesthetics
  5. Knowing What to Comment
  6. Making Comments Precise and Compact
  7. Making Control Flow Easy to Read
  8. Breaking Down Giant Expressions
  9. Variables and Readability
  10. Extracting Unrelated Subproblems
  11. One Task at a Time
  12. Turning Thoughts into Code
  13. Writing Less Code
  14. Testing and Readability
  15. Designing and Implementing a “Minute/Hour Counter”

art_of_readable_code_cartoon

Source: The Art of Readable Code

My Story

When I first arrived at Stanford a few years back, I was shocked by the disarray in which project files were being “organized”: no discernible structure, no standardization, no version control, etc. It was sheer confusion as I waddled through the files trying to figure out what was what. For example:

  • Is “analysis teacher turnover v3.do” or “analysis teacher turnover final.do” (same date-stamp) the latest version of the program file?
  • Does “analysis teacher turnover.do” have to be run before or after “analysis student turnover.do” … or does order not matter?

It was not only how files were named but the content of the files i.e., the code. It was as if I was reading someone’s diary and getting a gist of the underlying story swathed in inside jokes, unique lingo, and subtle inflections. The problem is code shared and collaborated across a team cannot be a personal journal of more or less rambling thoughts. If a graduate student or staff researcher on our team had left, his/her replacement would have little idea of how to replicate or update the code — or at least would have to spend an inordinate amount of time playing Sherlock Holmes. I wouldn’t even be surprised if the author wasn’t able to figure out the code without jolts of memory defibrillation.

Hence, as soon as I settled in, I wrote a manual of best practices for planning, organizing, and documenting code. Adopted by 30+ professors, graduate students, and staff, I called my manual the “POD”, drawing inspiration from J. Scott Long’s “The Workflow of Data Analysis Using Stata“. I wasn’t an expert on the topic but I had enough experience to share my know-how to lead an otherwise blind team towards adopting basic efficiencies (e.g., readability, consistency, etc) for reproducible research.

Some of the best practices in my “POD” manual echoed those in “The Art of Readable Code” including:

  • Packing information into your variable, function, and class names (8)
    • Choose specific words
    • Avoid generic names (or know when to use them)
    • Use concrete names instead of abstract names
    • Attach extra information to a name, by using a suffix or prefix
    • Decide how long a name should be
    • Use name formatting to pack extra information
  • Aesthetics (34)
    • Use consistent layout, with patterns the reader can get used to
    • Make similar code look similar
    • Group related lines of code into blocks

The Art of Readable Code

Boswell & Foucher lay out a lot of useful tips and step-by-step examples demonstrating the “art of readable code”. While the purpose of the book is not to teach the art of architecture or design patterns, the essential basics are covered: naming variables, including comments, formatting code (e.g., column alignment, blocks, logic order, etc), simplifying loops, etc. Sure, many of these things may seem intuitive or could have been figured out on-the-job but if not, this is a great place to start. And, for those who have already mastered these practices, reiteration of the “why?” and “how?” is always a helpful reminder of what can be dismissed as common-sense or second nature.

The key idea behind the teachings is:

“The Fundamental Theorem of Readability: Code should be written to minimize the time it would take for someone else to understand it.” (3)

What I love about this book is its plethora of examples illustrating the multiple ways in which you can implement the Fundamental Theorem of Readability. Examples are provided in C++, Java, JavaScript, and Python. But fear not if you are a newbie to programming or an expert in some other language, say, Stata! You do not need to be proficient in any of these languages to understand the concepts being illustrated: the beautiful code “art” vs. the uglier stuff. And, if you do get lost or intimidated, each chapter is wrapped up with a summary that bullets the key principles and techniques so you will always have the takeaways in plain English.

Review: Team Geek

Title: Team Geek – A Software Developer’s Guide to Working Well with Others

Author: Brian W. Fitzpatrick & Ben Collins-Sussman

teamgeek

Contents

  1. The Myth of the Genius Programmer
  2. Building an Awesome Team Culture
  3. Every Boat Needs a Captain
  4. The Art of Organizational Manipulation
  5. Users are People, Too

Mission Statement

“The goal of this book is to help programmers become more effective and efficient at creating software by improving their ability to understand, communicate with, and collaborate with other people.” (xiii)

Team Geek is a light and fun read with insightful commentary on how marrying the human “soft skills” with the technical “hard skills” can create the foundation for a great team. While Team Geek is written for software engineers (and their managers) in mind, its takeaways are relevant to anyone — engineer or non-engineer, lone wolf or team player. Though common sense at times with lessons already picked up from experience, what makes this book worth the read is the packaging of these lessons as entertaining stories and analogies like:

  • “Strengthen what we call the bus factor … the number of people that need to get hit by a bus before your project is completely doomed” (7)
  • “Your team’s culture is much like a good loaf of sourdough” (27)
  • “A boat without a captain is nothing more than a floating waiting room” (54)
  • “Engineers are … like plants: some need more light, and some need more water (and some need more bullshit, er, fertilizer).” (81)

Three Core Principles

The building blocks for a great team are based on “three pillars” of social dynamics: Humility, Respect, Trust — or HRT (12).

  • Humility: “You are not the center of the universe. You’re neither omniscient nor infallible. You’re open to self-improvement.”
  • Respect: “You genuinely care about others you work with. You treat them as human beings, and appreciate their abilities and accomplishments.”
  • Trust: “You believe others are competent and will do the right thing, and you’re OK with letting them drive when appropriate.”

What does this mean in practice? Actions of HRT include:

  • lose the ego
  • learn to both deal out and handle criticism
  • fail fast; learn; iterate
  • leave time for learning
  • learn patience
  • be open to influence

Using anecdotes and accompanying illustrations, the authors emphasize the importance of HRT not only for one’s own growth but for the success of the larger team. While the rare specimen of a “unicorn” or “lone craftsman” may exist, none of us work in a vacuum. Successful leaders are especially important in managing the team – particularly when attacked from within by poisonous threats (e.g., ego, over-entitlement, paranoia, perfectionism). Patterns (and anti-patterns) adopted by leaders to build a resilient (or dysfunctional) team are collected from first-hand accounts:

Antipattern (for Unsuccessful Leadership)

  • Hire pushovers
  • Ignore low performers
  • Ignore human issues
  • Be everyone’s friend
  • Compromising the hiring bar
  • Treat your team like children

Pattern (for Successful Leadership)

  • Lose the ego
  • Be a Zen master
  • Be a catalyst
  • Be a teacher and a mentor
  • Set clear goals
  • Be honest
  • Track happiness

All in all, HRT must be taken to heart by each and every team member in all interactions, big and small.

What I took to heart

As I find myself in a transitional phase seeking to learn what I am lacking (currently be on a team of a lonely one without strong leaders and mentors to learn from) and what I am searching for to find that happy spot in a Team Geek, the following resonated with me:

  • “If you spend all your time working alone, you’re increasing the risk of failure and cheating your potential for growth.” (5)
  • “Working alone is inherently riskier than working with others. While you may be afraid of someone stealing your idea or thinking you’re dumb, you should be much more scared of wasting huge swaths of time toiling away on the wrong thing.” (10)
  • “Your self-worth shouldn’t be connected to the code you write. To repeat ourselves: you are not your code.” (17)
  • “Let’s face it: it’s fun to be the most knowledgeable person in the room, and mentoring others can be incredibly rewarding. The problem is that once you reach a local maximum on your team, you stop learning. And when you stop learning, you get bored. Or accidentally become obsolete. It’s really easy to get addicted to being a leading player; but only by giving up some ego will you ever change directions and get exposed to new things. Again, it’s about increasing humility and being willing to learn as much as teach. Put yourself outside your comfort zone now and then; find a fishbowl with bigger fish than you and rise to whatever challenges they hand out to you. You’ll be much happier in the long run.” (20)

Even if we think we can stand on our own and detach from the human dramas, software engineering (and essentially all personal relationships and professional endeavors) is a team sport and in order for us all to win, especially in the trenches of conflict and bureaucracies, everyone must play the game by the social rules: Humility, Respect, and Trust.

* * * * *

Check out Fitzpatrick & Collins-Sussman’s Google I/O 2009 talk “The Myth of the Genius Programmer”: http://youtu.be/0SARbwvhupQ

What are the Trends for the Top 10 GitHub Languages?

 

github_search_top10totals_coloredbylanguage github_search_top10totals_coloredbylanguage_forkfalse

 

The graphs above display the annual top 10 GitHub languages over time in terms of repos and projects (data source: https://github.com/search/advanced). One important note is that the full history of a language’s presence in GitHub from inception to demise is not shown.

For example, a drop-out in the graph does not necessarily mean that no one is pushing repos or projects in that language anymore but may simply illustrate that the language is no longer ranked in the top 10 for that given year. Of course, the distinction cannot be explicitly tweezed out. Maybe the language has completely vanished! However, we can assume quite confidently that a top 10 language didn’t just suddenly die off. Conversely, a language that pops up is not necessarily a hot “new” language but simply may not have been previously ranked in the top 10.

Example: Shell is not observed in 2013 as it was replaced in the ranks by CSS, which in turn is in existence prior to 2013 but not in the top 10 (and hence not plotted in the graph).

The fun of taking simple numbers such as this and visually plotting the trends is to see if we can tell a story. So, what can we make from these graphs? How do the patterns jive with the known trends in programming languages?

A few starters:

 

Playing with GitHub Data: The Start (Part 2)

In continuation to the questions raised in “Playing with GitHub Data: The Start (Part 1)”, I decided to ask the Man. The man being Ilya Grigorik: the man behind GitHub Archive.

Surely, he will be able to provide insight on the differences observed between the GitHub search and GitHub Archive query search counts.

github_total_comparison_projectsgithub_total_comparison_repos

 

I reached out to Ilya.

20140317_github_ilyagrigorik_email1_v2

 

He responds.

 

20140317_github_ilyagrigorik_email2_v2

 

So let it be known. Keep it in mind when playing with GitHub Archive via BigQuery.

 

Playing with GitHub Data: The Start (Part 1)

Since March/April, I have been sitting on my hands not quite ready to hit the “Publish” button to push my words off onto the instantaneous online press. But as time passes by, I am losing the details of the what, why, how of my GitHub data explorations and going back through my GitHub history to identify my work processes requires more and more mental aerobics. Hence, while I am still in a state of partial clarity, I will do my best to squeeze out my months-past thoughts during an afternoon writing spurt.

* * * Here I go! * * *

Wanting to have fun exploring GitHub data, I headed first to the playground: GitHub’s API. It had all that I could want for my preliminary explorations. I could grab data on repository languages, pushes, forks, stars, etc. You name it. Problem was it was like standing at the base of a bouldering wall, positioning yourself in your first hanging form, and then not knowing how to reach the next boulder on the colored route. My technique was not quite even a V0 and my arms were too weak to compensate by just pulling myself up through sheer muscle.

That’s when I found GitHub Archive. GitHub Archive is a “project to record the public GitHub timeline, archive it, and make it easily accessible for further analysis.” With the data hosted on Google BigQuery, the GitHub event data was readily available to be queried using SQL.

SQL! SELECT statements! I can do that!

bigquery

 

I decided to go ahead and first explore GitHub’s data via GitHub Archive. The API would have to wait.

I started out with a basic question: What is the growth trend of total GitHub repositories? What is the growth trend of total GitHub projects i.e., repositories excluding forks?

To answer these questions, I parsed the GitHub Archive data in three ways:

  • GitHub Archive
  • GitHub Archive: CreateEvent
  • GitHub Archive: PushEvent

Side Track: CreateEvent vs. PushEvent

The reason why I looked at both CreateEvent and PushEvent was to investigate the peculiarities that emerged when running my initial query for the number of repositories by programming language and creation date, restricted only to CreateEvent. Looking for whether anyone else had run a similar analysis on which I could compare my results, I stumbled upon Adam Bard’s blog post “Top GitHub Languages for 2013 (so far)”.

Here was his query.

adambard_top25githublangs

 

This query was similar to mine but after exploring the data more closely, I had a couple issues with this approach. Although it may be difficult to see without looking at the raw data structure, the questions that popped up were:

  • Wouldn’t counting non-distinct languages i.e., count(repository_language) result in duplicate counts of unique repositories?
  • Shouldn’t we be looking at only CreateEvent’s payload_ref_type == “repository” rather than also including branches and tags?
  • Don’t we have a “null” issue for repository language identifications of CreateEvents?
    • over 99% of CreateEvents with payload_ref_type == “repository” have “null” repository language
    • over 60% of CreateEvents for all payload_ref_type {repository (>99%), branch (~28%), tag (~57%)} have “null” repository language

Example

Let’s look at the Ceasar’s repository “twosheds”.

createevent_ceasar_twosheds

 

If we count using count(repository_language), we would have the following total counts by language:

  • Python: 14
  • null: 1

Now this seems wrong. Why would we count these records multiple times as unique repositories? Instead, these should fall under one repository count for “twosheds” and be categorized as written in Python. What if we restrict the query to only CreateEvent’s payload_ref_type == “repository” and count as count(distinct(repository_url))? The issue here is that the assigned language is now “null”.

Sure, we could think of ways around this — for example, take the maximum non-missing language identification for each unique CreateEvent’s repository URL, regardless of the payload reference type. However, given the prevalence of “null” language identifications for CreateEvent, why not try PushEvent instead? We can check if PushEvent has similar missingness with its repository language identifications. If not, under the assumption that active repositories are pushed to, we can count the distinct repository URLs of PushEvents to identify unique repositories by creation date and programming language.

Indeed, only ~12% of PushEvents have “null” repository language identifications. PushEvent seems to be good alternative!

Back on Track & Back to Basics

Let’s go back to our initial question: What is the growth trend of total GitHub repositories? What is the growth trend of total GitHub projects i.e., repositories excluding forks? I computed the yearly totals using count(distinct(repository_url)) to count the total number of unique repositories by creation date (year).

total_sql_query_v2

 

As a litmus of sorts, I compared these yearly counts to those from GitHub Search.

github_total_comparison_reposgithub_total_comparison_projects

 

What do we notice here?

Assuming GitHub Search as the barometer of expectation:

  • prior to 2012, GitHub Archive (all, CreateEvent, PushEvent) seems to produce underestimates of total repositories and projects
  • repositories: Search ~ GitHub Archive (all)
  • projects: Search ~ PushEvent

Now, why do we observe these differences?

I mulled over the observed differences, raising my stack of questions higher. What is going on here? How will it affect my analyses?

paperstack

 

For now, I will leave it here and continue next time with more on the GitHub analysis I ended up pursuing.

As I say adieu, I ask: What interesting or curious things do you notice here so far?

 

Figuring out GitHub Search

I have been wanting to play around with GitHub data as a side project so when I first started poking around for what GitHub meta & event data I could grab, not yet being an API ninja, I went to the simplest point-click-Enter-Return shop in town: GitHub Search.

But when I was there, I noticed something strange. Each time I would refresh a search using the same parameters (e.g., “created:<2013-12-31 fork:true”), the results would produce different numbers. Moreover, conflicting counts of total repositories were displayed in the same search results: under “Repositories” and in “We’ve found [] repository results”.

search4search7search14search10

What was happening? I asked my to-go guy regarding all-things-tech (the technical stuff beyond the default “just try restarting your computer”). He gave me a “Hmmmm that’s strange. Something to do with caching?”. Not quite convinced, I decided to seek a more authoritative explanation from GitHub.

question_v2

I wasn’t waiting with bated breath (already having generated low expectations from a lifetime of mediocre customer service, unfair as it is to batch many tech startups/companies with bureaucratic behemoths like “Comcrap”, as my roommate amusingly nicknames).

Less than two days later I received a response from GitHub Support.

Thanks for getting in touch and asking about this!

 Some queries are computationally expensive for our Search to execute. For performance reasons, there are limits to how long queries can be executed. In rare situations when a timeout is reached, Search collects and returns matches that were already found, and the execution of the query is stopped.

That particular query you’re running is hitting this timeout, and as a result — you’re getting small variations in the number or results that were collected before the timeout was hit.

 The Search team is discussing this internally and looking into ways to make such situations less confusing, so your feedback is more than welcome!

 The reason why the two numbers provided under “We’ve found X repository results” and “Repositories” are different is caching. The number under “Repositories” is cached so it doesn’t change with page refreshes, as does the “We’ve found X repository results” number. That’s definitely confusing, and I’ll open an internal issue to get that fixed. 

Hope this explains things! If you have any other questions — please let us know.

Cheers

What a phenomenal answer!

GitHub Support not only responded in days time but addressed each question in a way that did not pass it off with a canned auto-reply or diminish it as “some silly question” wasting their customer support engineer’s precious time. The response even came with a swaddling of exclamations (“!”), welcoming the input as helpful feedback to be acted on for improved user experience.

I continued my conversation with the GitHub Support person with questions regarding a second-party data source. Likewise a timely, thorough, and – best of all – human response followed.

Thank you, GitHub!