From a7d3abb005a0f78eb32c07bacece1d901010c525 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Sun, 7 Jun 2026 22:33:45 -0400 Subject: [PATCH] Enforce anti-AI writing patterns with Vale Port the anti-AI prose rules from the book project as a local AIPatterns Vale style, translated for a conversational blog: - Errors (block CI): hedging openers, meta-commentary, "This ensures..." constructions, performative enthusiasm - Warnings: formulaic transitions, setup phrases - Suggestions: negation-antithesis, rhetorical questions, weak openings, vague intensifiers (deliberate voice, never gate) Vale was configured but never ran in CI (no install step) and the upstream BenBalter pack crashed Vale 3.x (removed `link` scope, fixed in vale-styles v0.0.2). Wire it up: - Install pinned Vale + sync packages in the Content Linting job - Lint .mdx posts too ([formats] mdx = md; script/vale globs) - Check in .github/styles/AIPatterns past the styles gitignore - Demote stylistic package rules (cliches, very, e.g., US dates, quoted profanity) to warnings so error level gates real problems Fix the genuine errors the new error level surfaced across legacy posts: doubled words, stray spacing, unhyphenated TODOs in prose, a handful of AI-pattern phrases, and an orphaned "I" line. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/styles/AIPatterns/AITics.yml | 27 ++++++++++++ .github/styles/AIPatterns/Antithesis.yml | 9 ++++ .github/styles/AIPatterns/Flourishes.yml | 13 ++++++ .github/styles/AIPatterns/MetaCommentary.yml | 14 +++++++ .../AIPatterns/PerformativeEnthusiasm.yml | 16 ++++++++ .../styles/AIPatterns/RhetoricalQuestions.yml | 16 ++++++++ .github/styles/AIPatterns/SetupPhrases.yml | 18 ++++++++ .../styles/AIPatterns/ThisConstructions.yml | 16 ++++++++ .github/styles/AIPatterns/Transitions.yml | 17 ++++++++ .../styles/AIPatterns/VagueIntensifiers.yml | 12 ++++++ .github/styles/AIPatterns/WeakOpenings.yml | 11 +++++ .github/workflows/ci.yml | 16 ++++++++ .gitignore | 2 + .vale.ini | 41 +++++++++++++++++-- CONTRIBUTING.md | 2 +- script/vale | 7 +++- src/content/CLAUDE.md | 2 + ...-the-barriers-to-organizational-agility.md | 2 +- .../2011-01-04-the-files-in-the-computer.md | 2 +- ...pying-content-in-the-internet-ecosystem.md | 2 +- ...ld-always-write-software-as-open-source.md | 2 +- ...sion-should-just-give-it-a-rest-already.md | 2 +- .../2012-12-26-securing-the-status-quo.md | 5 ++- src/content/posts/2014-07-29-fedramp.md | 2 +- ...pen-source-project-is-going-to-be-a-dud.md | 2 +- ...s-for-websites-and-open-source-projects.md | 2 +- .../posts/2015-06-22-merge-by-committee.md | 2 +- .../posts/2015-09-10-blog-style-tests.md | 2 +- ...18-tools-to-empower-open-collaboration.mdx | 2 +- ...unities-around-your-open-source-project.md | 2 +- ...t-add-a-cla-to-your-open-source-project.md | 2 +- ...ore-starting-or-interviewing-at-github.mdx | 2 +- .../2023-01-10-manage-like-an-engineer.md | 2 +- ...23-01-13-great-extended-leave-documents.md | 2 +- ...l-requests-are-a-form-of-documentations.md | 2 +- .../2026-05-31-ai-first-program-management.md | 2 +- 36 files changed, 255 insertions(+), 25 deletions(-) create mode 100644 .github/styles/AIPatterns/AITics.yml create mode 100644 .github/styles/AIPatterns/Antithesis.yml create mode 100644 .github/styles/AIPatterns/Flourishes.yml create mode 100644 .github/styles/AIPatterns/MetaCommentary.yml create mode 100644 .github/styles/AIPatterns/PerformativeEnthusiasm.yml create mode 100644 .github/styles/AIPatterns/RhetoricalQuestions.yml create mode 100644 .github/styles/AIPatterns/SetupPhrases.yml create mode 100644 .github/styles/AIPatterns/ThisConstructions.yml create mode 100644 .github/styles/AIPatterns/Transitions.yml create mode 100644 .github/styles/AIPatterns/VagueIntensifiers.yml create mode 100644 .github/styles/AIPatterns/WeakOpenings.yml diff --git a/.github/styles/AIPatterns/AITics.yml b/.github/styles/AIPatterns/AITics.yml new file mode 100644 index 000000000..f35822a65 --- /dev/null +++ b/.github/styles/AIPatterns/AITics.yml @@ -0,0 +1,27 @@ +extends: existence +message: "'%s' is an AI-like writing pattern. State the point directly." +ignorecase: true +level: error +tokens: + - It's important to note that + - It is important to note that + - It's worth mentioning that + - It is worth mentioning that + - It's worth noting that + - It is worth noting that + - It should be noted that + - It should be mentioned that + - As previously mentioned + - As mentioned earlier + - As noted above + - As discussed earlier + - As we discussed + - As we mentioned + - It bears mentioning + - It bears noting + - you might be wondering + - you may be wondering + - you may be asking yourself + - you might be asking yourself + - and that's okay + - and that's perfectly fine diff --git a/.github/styles/AIPatterns/Antithesis.yml b/.github/styles/AIPatterns/Antithesis.yml new file mode 100644 index 000000000..dc690b7e1 --- /dev/null +++ b/.github/styles/AIPatterns/Antithesis.yml @@ -0,0 +1,9 @@ +extends: existence +message: "'%s' is the AI negation-antithesis construction. Keep only if the contrast is earned; otherwise state the point directly." +ignorecase: true +nonword: true +level: suggestion +tokens: + - '(it''s|it is|that''s|that is) not (just |merely |simply |only )?(about )?[^.]{1,45}[—–-] ?(it''s|it is|that''s|they''re|they are)' + - 'not only (does|is|do|are|will|can|did) [^.,]{1,45}, but (also |it also |they also )' + - 'that''s where [^.]{1,40} comes? in' diff --git a/.github/styles/AIPatterns/Flourishes.yml b/.github/styles/AIPatterns/Flourishes.yml new file mode 100644 index 000000000..665ee978b --- /dev/null +++ b/.github/styles/AIPatterns/Flourishes.yml @@ -0,0 +1,13 @@ +extends: existence +message: "'%s' is a dramatic flourish AI writing leans on. Fine if it's earned; cut it if it's filler." +ignorecase: true +level: warning +tokens: + - Let that sink in + - Buckle up + - Spoiler alert + - Plot twist + - Here's the kicker + - Here is the kicker + - Here's the catch + - Here is the catch diff --git a/.github/styles/AIPatterns/MetaCommentary.yml b/.github/styles/AIPatterns/MetaCommentary.yml new file mode 100644 index 000000000..72cf2167a --- /dev/null +++ b/.github/styles/AIPatterns/MetaCommentary.yml @@ -0,0 +1,14 @@ +extends: existence +message: "Avoid meta-commentary like '%s'. Just do it directly." +ignorecase: true +level: error +tokens: + - Let's explore + - Let's dive into + - Let's take a look at + - Let's examine + - Let's consider + - Let's unpack + - Let's break down + - Let us explore + - Let us dive into diff --git a/.github/styles/AIPatterns/PerformativeEnthusiasm.yml b/.github/styles/AIPatterns/PerformativeEnthusiasm.yml new file mode 100644 index 000000000..31aad7ef7 --- /dev/null +++ b/.github/styles/AIPatterns/PerformativeEnthusiasm.yml @@ -0,0 +1,16 @@ +extends: existence +message: "'%s' sounds like performative enthusiasm. Keep a measured, authentic tone." +ignorecase: true +nonword: true +level: error +tokens: + - Great question! + - Excellent point! + - Excellent question! + - Great point! + - Fantastic approach + - Fantastic question + - Wonderful point + - Brilliant observation + - Absolutely right + - Couldn't agree more diff --git a/.github/styles/AIPatterns/RhetoricalQuestions.yml b/.github/styles/AIPatterns/RhetoricalQuestions.yml new file mode 100644 index 000000000..dc87b7398 --- /dev/null +++ b/.github/styles/AIPatterns/RhetoricalQuestions.yml @@ -0,0 +1,16 @@ +extends: existence +message: "Avoid formulaic rhetorical questions like '%s'. Trust the reader to draw conclusions." +ignorecase: true +nonword: true +level: suggestion +tokens: + - 'So what does this mean\?' + - 'So what does that mean\?' + - 'So why does this matter\?' + - 'Why does this matter\?' + - 'What does this look like in practice\?' + - 'What does that look like in practice\?' + - But what does this mean + - But why does this matter + - So how do we + - So how do you diff --git a/.github/styles/AIPatterns/SetupPhrases.yml b/.github/styles/AIPatterns/SetupPhrases.yml new file mode 100644 index 000000000..828cdf16d --- /dev/null +++ b/.github/styles/AIPatterns/SetupPhrases.yml @@ -0,0 +1,18 @@ +extends: existence +message: "'%s' is a setup phrase. Get to the point." +ignorecase: true +level: warning +tokens: + - When it comes to + - In terms of + - In the context of + - In today's + - In an era + - In the world of + - In the realm of + - At its core + - At its heart + - In essence + - Gone are the days + - Rest assured + - Look no further diff --git a/.github/styles/AIPatterns/ThisConstructions.yml b/.github/styles/AIPatterns/ThisConstructions.yml new file mode 100644 index 000000000..dac4a136d --- /dev/null +++ b/.github/styles/AIPatterns/ThisConstructions.yml @@ -0,0 +1,16 @@ +extends: existence +message: "'%s' is a common AI writing pattern. Rephrase for a more natural voice." +ignorecase: true +level: error +tokens: + - This ensures that + - This allows for + - This enables teams + - This enables you + - This enables organizations + - This provides a + - This creates a + - This helps ensure + - This helps to ensure + - This makes it easy + - This makes it possible diff --git a/.github/styles/AIPatterns/Transitions.yml b/.github/styles/AIPatterns/Transitions.yml new file mode 100644 index 000000000..510914bc2 --- /dev/null +++ b/.github/styles/AIPatterns/Transitions.yml @@ -0,0 +1,17 @@ +extends: existence +message: "'%s' is a formulaic transition. Use a natural transition or restructure." +ignorecase: false +nonword: true +level: warning +scope: sentence +tokens: + - Furthermore, + - Moreover, + - Additionally, + - In addition, + - That being said, + - That said, + - In conclusion, + - To summarize, + - In summary, + - Overall, diff --git a/.github/styles/AIPatterns/VagueIntensifiers.yml b/.github/styles/AIPatterns/VagueIntensifiers.yml new file mode 100644 index 000000000..e595c126e --- /dev/null +++ b/.github/styles/AIPatterns/VagueIntensifiers.yml @@ -0,0 +1,12 @@ +extends: existence +message: "'%s' is a vague intensifier. Be specific or provide evidence." +ignorecase: true +level: suggestion +tokens: + - very unique + - truly unique + - truly transformative + - incredibly important + - incredibly valuable + - incredibly powerful + - highly effective diff --git a/.github/styles/AIPatterns/WeakOpenings.yml b/.github/styles/AIPatterns/WeakOpenings.yml new file mode 100644 index 000000000..c6138f10e --- /dev/null +++ b/.github/styles/AIPatterns/WeakOpenings.yml @@ -0,0 +1,11 @@ +extends: existence +message: "'%s' is a weak opening. Start with a stronger, more specific statement." +ignorecase: true +level: suggestion +tokens: + - One of the most important + - One of the biggest + - One of the key + - An important thing to + - An important aspect of + - An important consideration diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c3ec423f..c99df9998 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,6 +95,22 @@ jobs: curl -fSL "https://github.com/Automattic/harper/releases/download/${HARPER_VERSION}/harper-cli-x86_64-unknown-linux-gnu.tar.gz" | tar xz sudo mv harper-cli /usr/local/bin/ + - name: Install Vale + env: + VALE_VERSION: 3.14.2 + run: | + curl -fSL "https://github.com/errata-ai/vale/releases/download/v${VALE_VERSION}/vale_${VALE_VERSION}_Linux_64-bit.tar.gz" | tar xz vale + sudo mv vale /usr/local/bin/ + + - name: Cache Vale styles + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 + with: + path: .github/styles + key: vale-styles-${{ hashFiles('.vale.ini', '.github/styles/AIPatterns/*.yml') }} + + - name: Sync Vale packages + run: vale sync + - name: script/cibuild-content run: script/cibuild-content diff --git a/.gitignore b/.gitignore index 3bdd6078d..1c750169f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ node_modules /tmp .github/styles/* +# Local Vale style is checked in; synced packages above are not +!.github/styles/AIPatterns .frontmatter assets/css/style.css assets/js/bundle.js diff --git a/.vale.ini b/.vale.ini index 334508af9..d1470607b 100644 --- a/.vale.ini +++ b/.vale.ini @@ -1,8 +1,11 @@ StylesPath = .github/styles -Packages = Microsoft, alex, proselint, Readability, write-good, https://github.com/benbalter/vale-styles/releases/download/v0.0.1/BenBalter.zip +Packages = Microsoft, alex, proselint, Readability, write-good, https://github.com/benbalter/vale-styles/releases/download/v0.0.2/BenBalter.zip -[*.md] -BasedOnStyles = Vale, Microsoft, alex, proselint, Readability, write-good, BenBalter +[formats] +mdx = md + +[*.{md,mdx}] +BasedOnStyles = Vale, Microsoft, alex, proselint, Readability, write-good, BenBalter, AIPatterns alex.Condescending = warn Microsoft.Adverbs = NO Microsoft.Avoid = warn @@ -15,4 +18,34 @@ Microsoft.Percentages = NO Microsoft.Quotes = NO Microsoft.Units = warn Microsoft.We = NO -Vale.Spelling = NO \ No newline at end of file +Vale.Spelling = NO + +# Stylistic rules demoted to warning so CI (--minAlertLevel=error) gates on +# genuine problems without re-litigating 15 years of conversational posts. +# Where two packages flag the same concept, one source is disabled outright. +proselint.Cliches = warning +proselint.Very = warning +proselint.Skunked = warning +proselint.Uncomparables = warning +proselint.GenderBias = warning +write-good.ThereIs = warning +write-good.So = NO +BenBalter.So = warning +proselint.But = NO +BenBalter.But = warning +proselint.CorporateSpeak = NO +BenBalter.CorporateSpeak = warning +BenBalter.FillerWords = warning +BenBalter.CulturalInclusion = warning +Microsoft.Plurals = warning +proselint.Typography = warning +proselint.Cursing = warning +proselint.Hyperbole = warning +proselint.Jargon = warning +proselint.Hedging = warning +proselint.DateSpacing = warning +Microsoft.Foreign = warning +Microsoft.DateOrder = warning +Microsoft.AMPM = warning +Microsoft.HeadingColons = warning +Microsoft.Auto = warning diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ee7725bb9..6ffaf8270 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to Ben.Balter.com +# Contributing to ben.balter.com Thank you for your interest in contributing to this project! This document provides guidelines and information for contributors. diff --git a/script/vale b/script/vale index 6de22d562..7ff1562ca 100755 --- a/script/vale +++ b/script/vale @@ -8,5 +8,10 @@ if ! [ -x "$(command -v vale)" ]; then echo "Vale provides additional prose style and grammar checking." else echo "Running Vale prose linter..." - vale ./*.md src/content/posts/*.md src/content/resume-positions/*.md --minAlertLevel=error + # Sync packages on first run (the local AIPatterns style is checked in) + if [ ! -d ".github/styles/proselint" ]; then + vale sync + fi + # Note: /bin/sh may be dash (no brace expansion) — keep globs explicit + vale ./*.md src/content/posts/*.md src/content/posts/*.mdx src/content/resume-positions/*.md --minAlertLevel=error fi diff --git a/src/content/CLAUDE.md b/src/content/CLAUDE.md index 6ae366af6..dba12ad01 100644 --- a/src/content/CLAUDE.md +++ b/src/content/CLAUDE.md @@ -35,6 +35,8 @@ These make writing feel machine-generated: **The coffee test**: read aloud — does it sound like something you'd actually say to a colleague? **The "anyone test"**: could this have been written by literally anyone? If there's no personality, rewrite it. +Many of these patterns are enforced mechanically by the custom `AIPatterns` Vale style (`.github/styles/AIPatterns/`), which runs in CI via `script/vale`. Unambiguous AI tells (hedging openers, meta-commentary, "This ensures…", performative enthusiasm) are errors and block CI; transitions and setup phrases are warnings; patterns that overlap with deliberate stylistic choices (em-dash antithesis, rhetorical questions) are suggestions. Run `vale --minAlertLevel=suggestion` to see everything. + ## Grammar and Mechanics - **Em dashes** (`—`): no spaces — "Remote work—when done right—transforms teams" diff --git a/src/content/posts/2010-11-06-removing-the-barriers-to-organizational-agility.md b/src/content/posts/2010-11-06-removing-the-barriers-to-organizational-agility.md index a065927eb..c5155bf9b 100755 --- a/src/content/posts/2010-11-06-removing-the-barriers-to-organizational-agility.md +++ b/src/content/posts/2010-11-06-removing-the-barriers-to-organizational-agility.md @@ -4,7 +4,7 @@ description: Recording of a GW Tech Alumni panel discussion on removing the barr archived: true --- -*Recorded at the [The George Washington University Tech Alumni Group](http://www.facebook.com/group.php?gid=154839957865223) Federal Executive Round Table, November 4, 2010.* +*Recorded at [The George Washington University Tech Alumni Group](http://www.facebook.com/group.php?gid=154839957865223) Federal Executive Round Table, November 4, 2010.* Photo of the panelists at the event diff --git a/src/content/posts/2011-01-04-the-files-in-the-computer.md b/src/content/posts/2011-01-04-the-files-in-the-computer.md index 795d9bc80..731ff9308 100755 --- a/src/content/posts/2011-01-04-the-files-in-the-computer.md +++ b/src/content/posts/2011-01-04-the-files-in-the-computer.md @@ -33,6 +33,6 @@ Notes: [^3]: Beyond the obvious (email, phone, contact, calendars), there's [dinner reservations](http://itunes.apple.com/us/app/opentable/id296581815?mt=8), [car rentals](http://www.zipcar.com/iphone/), [TV viewing habits](http://www.engadget.com/2010/11/15/comcast-xfinity-remote-app-for-iphone-ipad-launches-video-stre/), [financial data](http://www.mint.com/features/iphone/), [recent purchases](https://www.amazon.com/your-account), even [desktop browsing history](http://www.mozilla.com/en-US/mobile/home/) — it's like winning the lottery of personal information. -[^4]: It's worth noting that the word "server" is not mentioned once in the opinion, yet the phrase "storage capacity" is used no less than five times — a concept that [even as early as 2007 was considered a thing of the past](http://mashable.com/2007/05/14/yahoo-mail-unlimited/). +[^4]: The word "server" is not mentioned once in the opinion, yet the phrase "storage capacity" is used no less than five times — a concept that [even as early as 2007 was considered a thing of the past](http://mashable.com/2007/05/14/yahoo-mail-unlimited/). [^5]: A password may only delay the inevitable. *See* Gershowitz, Adam M., [*Password Protected? Can a Password Save Your Cell Phone from the Search Incident to Arrest Doctrine?*](http://ssrn.com/abstract=1669403) (August 31, 2010). diff --git a/src/content/posts/2011-04-27-fair-use-excerpting-and-copying-content-in-the-internet-ecosystem.md b/src/content/posts/2011-04-27-fair-use-excerpting-and-copying-content-in-the-internet-ecosystem.md index 80df2529c..65eadb630 100755 --- a/src/content/posts/2011-04-27-fair-use-excerpting-and-copying-content-in-the-internet-ecosystem.md +++ b/src/content/posts/2011-04-27-fair-use-excerpting-and-copying-content-in-the-internet-ecosystem.md @@ -49,7 +49,7 @@ The law aside, readers want you to digest and put ideas in your own voice. Take [^1]: Questions asked included: If there's no copyright symbol, is it still copyrighted?; If it's posted online, can I just copy it because its it's in the public domain?; Can I use it if I'm not selling it?; and It's okay to use if I credit the original author, right?. -[^2]: It should be noted that [I'm not an attorney](https://ben.balter.com/fine-print/) and my writing should not be substituted for qualified legal advice. +[^2]: [I'm not an attorney](https://ben.balter.com/fine-print/) and my writing should not be substituted for qualified legal advice. [^3]: This is a common misconception. While once true, under the [Berne Convention](http://en.wikipedia.org/wiki/Berne_Convention_for_the_Protection_of_Literary_and_Artistic_Works) the author of any content published today is assumed to retain copyright claims. diff --git a/src/content/posts/2012-06-26-why-you-should-always-write-software-as-open-source.md b/src/content/posts/2012-06-26-why-you-should-always-write-software-as-open-source.md index 3906b1ab4..d1c1677a3 100755 --- a/src/content/posts/2012-06-26-why-you-should-always-write-software-as-open-source.md +++ b/src/content/posts/2012-06-26-why-you-should-always-write-software-as-open-source.md @@ -26,4 +26,4 @@ Justice Brandeis is famous for noting that "sunlight is the best disinfectant." [^2]: [twitter.com/BenBalter/status/209356982983999488](https://twitter.com/BenBalter/status/209356982983999488) -[^3]: [coverity.com/library/PDF/coverity-scan-2011-open-source-integrity-report.PDF](http://www.coverity.com/library/pdf/coverity-scan-2011-open-source-integrity-report.pdf) +[^3]: [coverity.com/library/pdf/coverity-scan-2011-open-source-integrity-report.pdf](http://www.coverity.com/library/pdf/coverity-scan-2011-open-source-integrity-report.pdf) diff --git a/src/content/posts/2012-12-15-why-wordpress-next-version-should-just-give-it-a-rest-already.md b/src/content/posts/2012-12-15-why-wordpress-next-version-should-just-give-it-a-rest-already.md index 291751a95..c446785f1 100644 --- a/src/content/posts/2012-12-15-why-wordpress-next-version-should-just-give-it-a-rest-already.md +++ b/src/content/posts/2012-12-15-why-wordpress-next-version-should-just-give-it-a-rest-already.md @@ -27,7 +27,7 @@ At the least, lets expose all WordPress content in a machine readable format. Th 1. Create a new format ("feed" in WordPress parlance) called JSON, and add the necessary rewrite rules such that I can simply add `.json` to any post and retrieve the underlying information in a machine readable format. This should contain not only the content of the post and information that would normally be accessible via HTML, but all the fields of the posts table (for example, date published, date updated, etc.), all the post's metadata (custom, post-specific information), and all the associated term objects (tags, categories, etc.). Sure we'll need to add a filter or two in their to ensure information folks want private stays private, but from a technical standpoint, we're talking a handful of lines of code here. -2. Extend that format to indices (archives in WordPress terms). Again, just as above, every list of posts (by date, by associated term, search results) should have the capability to expose the list in that same machine-readable format. This allows for the programatic discovery of information. A little bit harder than #1, but again, nothing crazy here. Pretty basic stuff. +2. Extend that format to indices (archives in WordPress terms). Again, just as above, every list of posts (by date, by associated term, search results) should have the capability to expose the list in that same machine-readable format, so that information can be discovered programatically. A little bit harder than #1, but again, nothing crazy here. Pretty basic stuff. ## Walk diff --git a/src/content/posts/2012-12-26-securing-the-status-quo.md b/src/content/posts/2012-12-26-securing-the-status-quo.md index 32f40ea7e..db4e3348b 100644 --- a/src/content/posts/2012-12-26-securing-the-status-quo.md +++ b/src/content/posts/2012-12-26-securing-the-status-quo.md @@ -4,6 +4,9 @@ description: Federal agencies spend billions on IT security, yet rigid complianc tldr: "Federal agencies spend billions on IT security, yet rigid compliance frameworks often create a false sense of safety while stifling the innovation needed to address real threats." --- + + + ## The Effect of Federal IT Security Policies on Innovation The United States Federal Government is the single largest purchaser of information security products.[^1] In FY 2011 alone, a mere 24 agencies[^2] reported a combined IT security budget of $13.3 billion, employing the equivalent of some 84,426 full time employees with major responsibilities for information security.[^3] The gravity of the ongoing threat to our nations cybersecurity has been described in the starkest of terms at the highest levels of government. Describing our current situation, President Obama remarked that [t]he status quo is no longer acceptable[^4], members of congress from both parties have characterized the risk as a catastrophe in the making,[^5] and Secretary of Defense Leon Panetta warned of an imminent digital Pearl Harbor.[^6] @@ -42,7 +45,7 @@ NIST publishes its requirements as part of Federal Information Processing Standa The myriad guidance and labyrinthian requirements may do less to secure our nations information systems than policymakers hope. A number of critics have complained that the current security regime incentivizes agencies to perform a simple box checking paperwork exercise that does not keep up with an ever-expanding and ever-changing world of threats.[^41] This paperwork drill puts into place and measures paper-based processes, rather than technical processes, for implementing information security,[^42] and ultimately fails to address the root causes of network exploitation: inadequate software quality assurance.[^43] Even assuming 100% compliance with all FISMA requirements, many believe that agencies would fail short of bolstering actual information security.[^44] Tim Bennett, President of the Cyber Security Industry Alliance lamented that FISMA grades not how well agencies have increased their information security, but rather how well agencies increase their compliance with the FISMA mandated processes.[^45] The current FISMA reports say absolutely nothing about government security but rather is merely a measure of compliance with report generation.[^46] FISMA erroneously assumes an agency's compliance with largely reactionary standards is an objective measure of information security. Instead, such an assumption incentivizes agencies to expend efforts on reporting, rather than securing the underlying security threats the reports represent. [^47] By focusing on security audits, rather than the actual security of the systems, FISMA provides a framework for Federal Chief Information Officers (CIOs) to quantify their progress in ways a large, non-technical bureaucracy can easily digest. Rather than drill down on the number or nature of attacks deflected, CIOs could simply report that they have achieved a specified level of FISMA compliance, and thus could justify their various budgets.[^48] Put another way, FISMA provides little incentive to address any security metric outside those explicitly required of agencies by FISMA.[^49] -This focus on reporting requirements and audits, rather than actual information security may explain why cyber attacks increased some 250% between 2007 and 2009.[^50] The Community Emergency Response Team (CERT) estimates that 95% of intrusions exploited known software vulnerabilities to which counter measures were readily available.[^51] Given the fluid nature of the technology industry, and the reliance on cash flow to support operations, software manufacturers face increased pressure to rush their products to market to better capitalize on the product's innovation.[^52] This creates a race to the bottom in terms of software quality. Given strict budgets and timelines, agencies our forced to either cut desired functionality or skirt security requirements. +This focus on reporting requirements and audits, rather than actual information security may explain why cyber attacks increased some 250% between 2007 and 2009.[^50] The Community Emergency Response Team (CERT) estimates that 95% of intrusions exploited known software vulnerabilities to which counter measures were readily available.[^51] Given the fluid nature of the technology industry, and the reliance on cash flow to support operations, software manufacturers face increased pressure to rush their products to market to better capitalize on the product's innovation.[^52] The result is a race to the bottom in terms of software quality. Given strict budgets and timelines, agencies our forced to either cut desired functionality or skirt security requirements. Such a focus on reporting and managerial controls rather than on actual information security manifests itself on a near daily basis. Despite our nations best efforts at complying with codified security policy, thousands of computers on our military networks were infected by malware,[^53] unauthorized users in Iran were able to gain access to blueprints and other information about a helicopter in the Presidents fleet,[^54] and the State and Defense departments have lost more than six terabytes of information due to digital espionage, an amount equal to one-sixth of the information contained within the Library of Congress.[^55] As recently as last year, even, a single Army private was able to steal more than a quarter of a million classified State Department cables and nearly 100,000 intelligence reports.[^56] This deficiency however, is not limited to threats to national security. It is also personal. The Department of Defense was hit with a $4.9 billion class action suit as a result of the theft of the personal information of some 4.9 million uniform service members and their families,[^57] the Department of Veterans Affairs lost health records and other sensitive personal information for approximately 26.5 million veterans and their spouses, [^58] the Secretary of Defenses unclassified email was hacked,[^59] and the Navy CIO had his personal information compromised not once or twice, but on six distinct occasions.[^60] diff --git a/src/content/posts/2014-07-29-fedramp.md b/src/content/posts/2014-07-29-fedramp.md index c5234b027..3ac345684 100644 --- a/src/content/posts/2014-07-29-fedramp.md +++ b/src/content/posts/2014-07-29-fedramp.md @@ -73,7 +73,7 @@ In a time when government IT is trying to "do more with less", does every single Don't get me wrong. Government agencies shouldn't trust fly-by-night sites. Cloud services shouldn't just apply the "it fell off the back of a truck" level of service when given the public's trust, but common sense tells us the same standard can't apply to both building out a top-secret desert datacenter and clicking publish on a public-facing Facebook page. -Federal procurement has this same fatal flaw. The same multi-billion dollar process used to procure tanks and battleships is also used to get access to sub-thousand dollar industry standard services — a rounding error in any agency's budget. The difference being, petty purchases below a certain threshold — purchases that would require the government to spend more in man-hours doing paperwork than the thing itself costs — have a simplified process: you just buy it. This creates a federal marketplace to test good and services in a low risk, low cost way before ramping up the procurement dial to eleven. +Federal procurement has this same fatal flaw. The same multi-billion dollar process used to procure tanks and battleships is also used to get access to sub-thousand dollar industry standard services — a rounding error in any agency's budget. The difference being, petty purchases below a certain threshold — purchases that would require the government to spend more in man-hours doing paperwork than the thing itself costs — have a simplified process: you just buy it. The result is a federal marketplace to test goods and services in a low risk, low cost way before ramping up the procurement dial to eleven. ## No as the default diff --git a/src/content/posts/2015-02-11-why-your-first-open-source-project-is-going-to-be-a-dud.md b/src/content/posts/2015-02-11-why-your-first-open-source-project-is-going-to-be-a-dud.md index 98f66ee79..bd4f76b23 100644 --- a/src/content/posts/2015-02-11-why-your-first-open-source-project-is-going-to-be-a-dud.md +++ b/src/content/posts/2015-02-11-why-your-first-open-source-project-is-going-to-be-a-dud.md @@ -22,7 +22,7 @@ Almost without exception, up until this point, government has preferred to wait The most effective way to hedge the risk of too-big-to fail software is through iteration. Lean startup. Fail fast. Validated assumptions and all that. In the open source world, that means that when starting something new, you should :ship: version 0.1 (the minimum viable version of the thing you're trying to create), not 1.0 (what you're hoping to :ship: eventually). So long as you communicate the projects status (for example, "it's a prototype", "it's a proof-of-concept"), the community will respond accordingly. Once you've gotten real-world, production-grade feedback, you can add additional functionality in a 0.2, and eventually ship the 1.0 you originally set out to create. -The irony is that government agencies often initially ship software that would be called 0.1 any place outside government, but they give it the self-proclaimed badge of 1.0 quality, both internally and externally. Despite expectations or up-front planning, no matter how good your developers, no matter how good the project management, no matter how good the idea, humans are inherently imperfect, and thus so too are the tools they create. To paraphrase internet wisdom, waterfall approaches assume you can predict the future, open source assumes no one can can. The process of creating, releasing, and maintaining open source software is more art than science, and the only way to learn is by doing, not by planning, no matter how hard you try. +The irony is that government agencies often initially ship software that would be called 0.1 any place outside government, but they give it the self-proclaimed badge of 1.0 quality, both internally and externally. Despite expectations or up-front planning, no matter how good your developers, no matter how good the project management, no matter how good the idea, humans are inherently imperfect, and thus so too are the tools they create. To paraphrase internet wisdom, waterfall approaches assume you can predict the future, open source assumes no one can. The process of creating, releasing, and maintaining open source software is more art than science, and the only way to learn is by doing, not by planning, no matter how hard you try. ## Think small, then think even smaller diff --git a/src/content/posts/2015-06-03-copyright-notices-for-websites-and-open-source-projects.md b/src/content/posts/2015-06-03-copyright-notices-for-websites-and-open-source-projects.md index 767adeb7d..13945351a 100644 --- a/src/content/posts/2015-06-03-copyright-notices-for-websites-and-open-source-projects.md +++ b/src/content/posts/2015-06-03-copyright-notices-for-websites-and-open-source-projects.md @@ -42,7 +42,7 @@ In terms of sites, if you have a page that updates daily (think the front page o ## The copyright holder -As noted above, when an author creates an original work (be they a writer or developer), copyright automatically vests in the author. Think of that roughly like owning a building. If the author then wants others to be able to use that work, they may choose to grant them a license. Think of that license roughly like renting out an apartment in that building. The author retains ownership (the building), and the tenant has a lease saying they have the right to use it (a license). +When an author creates an original work (be they a writer or developer), copyright automatically vests in the author. Think of that roughly like owning a building. If the author then wants others to be able to use that work, they may choose to grant them a license. Think of that license roughly like renting out an apartment in that building. The author retains ownership (the building), and the tenant has a lease saying they have the right to use it (a license). When you use an open source project, you are analogous to the renter, but who's the building owner (copyright holder)? If the project only has a single author, things are clear: the copyright holder is the project creator. When you have multiple contributors, all authoring code for the same project, absent an explicit agreement to the contrary, they each retain copyright to their own contribution. diff --git a/src/content/posts/2015-06-22-merge-by-committee.md b/src/content/posts/2015-06-22-merge-by-committee.md index 3c5dd0997..db1498421 100644 --- a/src/content/posts/2015-06-22-merge-by-committee.md +++ b/src/content/posts/2015-06-22-merge-by-committee.md @@ -32,7 +32,7 @@ Instead, organizations wishing to transition from traditional, closed-source wor 1. **Decentralize governance** - Individual maintainers must be trusted and empowered to act in the project's best interest. If a user requests a new feature, project maintainers should provide feedback immediately, speaking as individuals, not on behalf of some semi-secret committee. If a contributor proposes a change, the code should be reviewed by a developer, and the merits discussed alongside the code, as it's submitted, and open to everyone involved. Naturally some issues, such as the project goals or roadmap, may warrant a broader discussion, for which more synchronous meetings (open to everyone) will be more appropriate, but whether technical or non-technical, individual maintainers should have the authority to run the project on a day-to-day basis. Delegate authority to the greatest extent possible, absent overriding policy or administrative concerns. Use your move to open source to adopt the ideal workflow, not the workflow your organization has used since the cold war. -2. **Minimize information imbalance** - The problem with maintaining a closed-source workflow, while working in the open, is that you end up duplicating much of your efforts. Organization's often have two classes of stakeholders (those inside the organization, and the rest of the world), two means of requesting new features, two means of discussing proposed changes, and two means of receiving project updates. This creates a significant imbalance, both in terms of information and the ability to contribute. Instead, your project should have one class of stakeholders, pushing internal discussions outside the firewall to the same tools external stakeholders use. Want to propose a feature? Open an issue. Think something's a bad idea? Comment on the pending pull request. If an external stakeholder doesn't have access to a given resource, internal stakeholders shouldn't use it until they do. Not only will this empower external stakeholders to contribute on equal footing as those inside your organization, it will simplify and modernize internal workflows, allow you to rely on best of breed tools, rather than century old management practices. +2. **Minimize information imbalance** - The problem with maintaining a closed-source workflow, while working in the open, is that you end up duplicating much of your efforts. Organization's often have two classes of stakeholders (those inside the organization, and the rest of the world), two means of requesting new features, two means of discussing proposed changes, and two means of receiving project updates. That's a significant imbalance, both in terms of information and the ability to contribute. Instead, your project should have one class of stakeholders, pushing internal discussions outside the firewall to the same tools external stakeholders use. Want to propose a feature? Open an issue. Think something's a bad idea? Comment on the pending pull request. If an external stakeholder doesn't have access to a given resource, internal stakeholders shouldn't use it until they do. Not only will this empower external stakeholders to contribute on equal footing as those inside your organization, it will simplify and modernize internal workflows, allow you to rely on best of breed tools, rather than century old management practices. ## Maintainer, not manager diff --git a/src/content/posts/2015-09-10-blog-style-tests.md b/src/content/posts/2015-09-10-blog-style-tests.md index 32196b222..3b2ab59cb 100644 --- a/src/content/posts/2015-09-10-blog-style-tests.md +++ b/src/content/posts/2015-09-10-blog-style-tests.md @@ -8,7 +8,7 @@ I've written in the past about how you should treat [prose with the same respect > Today, after months of effort, we're excited to announce our new wiz-bang feature… -Whereas traditionally a member of your company's marketing, copy, or editorial team may have needed to take the time to manually review the post before the author could get any feedback (a blocking and time-consuming operation), there are many machine-detectable improvements that an automated process could easily call out without requiring delay or human intervention, unblocking both the author and the editor to continue working unfettered. Let's take a look at a few examples of this idea and how you might implement them for your own team: +Whereas traditionally a member of your company's marketing, copy, or editorial team may have needed to take the time to manually review the post before the author could get any feedback (a blocking and time-consuming operation), there are many machine-detectable improvements that an automated process could easily call out without requiring delay or human intervention, unblocking both the author and the editor to continue working unfettered. Here are a few examples of this idea and how you might implement them for your own team: ## Don't use the word today diff --git a/src/content/posts/2015-11-18-tools-to-empower-open-collaboration.mdx b/src/content/posts/2015-11-18-tools-to-empower-open-collaboration.mdx index 0f011d426..752e47d93 100644 --- a/src/content/posts/2015-11-18-tools-to-empower-open-collaboration.mdx +++ b/src/content/posts/2015-11-18-tools-to-empower-open-collaboration.mdx @@ -74,7 +74,7 @@ The four qualities above are ideals. In practice, there are a handful of specifi ## Evaluating existing Tools -I began by noting that the phrase "everything should be on GitHub", doesn't necessitate a certain tool, but if you believe working the way described above is valuable, few of today's consumer collaboration tools encourage open source inspired workflows. Let's take a look at a few: +I began by noting that the phrase "everything should be on GitHub", doesn't necessitate a certain tool, but if you believe working the way described above is valuable, few of today's consumer collaboration tools encourage open source inspired workflows. Here are a few: | Tool | Open | Captures
Process | Linkable | Async | | :--------------------------------------------------------------------- | :------------------- | :--------------------- | :--------------------------------- | :------------------- | diff --git a/src/content/posts/2017-11-10-twelve-tips-for-growing-communities-around-your-open-source-project.md b/src/content/posts/2017-11-10-twelve-tips-for-growing-communities-around-your-open-source-project.md index dbfa3488d..c11211b29 100644 --- a/src/content/posts/2017-11-10-twelve-tips-for-growing-communities-around-your-open-source-project.md +++ b/src/content/posts/2017-11-10-twelve-tips-for-growing-communities-around-your-open-source-project.md @@ -46,7 +46,7 @@ In my experience expanded technical documentation is a positive feedback loop, i ## 5. Document how to contribute (and that you want contributions) -Every project has its own workflow, processes, and norms. Some require that each pull request have an associated issue, other require squashing commits or that commit messages be in a specific format. Whatever your community's practice, make it easy for first-time contributors to implement. This helps ensure that first-time contributors have a positive experience and become repeat contributors, but also means that maintainers will be able to spend less time on the busy work of enforcing process. +Every project has its own workflow, processes, and norms. Some require that each pull request have an associated issue, other require squashing commits or that commit messages be in a specific format. Whatever your community's practice, make it easy for first-time contributors to implement. That way, first-time contributors have a positive experience and become repeat contributors, and maintainers will be able to spend less time on the busy work of enforcing process. Think through the experience of going from a user to a first-time contributor to a regular contributor. How long does it take for that user to go from "I want to contribute" to "I have contributed"? I call that measure [friction](https://ben.balter.com/2013/08/11/friction/). When documenting your process, constantly ask yourself "how can you minimize that friction?" (or inversely, how can you maximize that conversion rate). How do you bootstrap a local development environment? How do you run tests? What are common pitfalls? Do you require a CLA? Whatever it is, try to make it as easy as possible to contribute, and more users will. diff --git a/src/content/posts/2018-01-02-why-you-probably-shouldnt-add-a-cla-to-your-open-source-project.md b/src/content/posts/2018-01-02-why-you-probably-shouldnt-add-a-cla-to-your-open-source-project.md index 8ba5c51f9..3bf84b828 100644 --- a/src/content/posts/2018-01-02-why-you-probably-shouldnt-add-a-cla-to-your-open-source-project.md +++ b/src/content/posts/2018-01-02-why-you-probably-shouldnt-add-a-cla-to-your-open-source-project.md @@ -48,7 +48,7 @@ CLAs are legal contracts contributors agree to prior to contributing to a projec Like many things in the legal world, in the world of digital contract formation, there's similarly a spectrum of options, depending on how much risk the maintainer is willing to accept that a contributor might later claim that they never agreed to the contract. Put another way, it's a question of how "signed" you want the CLA to be. At one end of the spectrum, it might be a link to the CLA with some sort of "by submitting you agree…" disclaimer ("browserwrap") or an explicit "I agree to the CLA" checkbox that enables the submit button ("clickwrap"). At the other extreme might be the requirement that developers print the CLA and submit a physical "wet" signature before they can contribute (sadly, still not uncommon among older projects). Most projects that have adopted CLAs land someplace in the middle, treating electronic signatures as sufficient, but even electronic signatures create lots of administrative overhead, both for the contributor and for the maintainer. -For the contributor, as mentioned earlier, CLAs require the contributor to parse an often dense and complex bespoke legal document. Even if they are able to do so, if they work for a company that produces software, there's a good chance that they'll need to get sign-off from their employer's lawyers, a non-trivial process. The reason being, CLAs require that developers certify they own the copyright to their code, and that their contribution does not infringe on the rights of others, two non-obvious determinations in the case of professional software developers. For one, depending on the time of day, computer used, type of contribution, or even employee handbook, the code may be the property of the employer. For another, the employee may have theoretical access to trade secrets and other confidential information, meaning they may inadvertently jeopardize a corporate patent or agreement, even if they didn't intend to do so. +For the contributor, CLAs require the contributor to parse an often dense and complex bespoke legal document. Even if they are able to do so, if they work for a company that produces software, there's a good chance that they'll need to get sign-off from their employer's lawyers, a non-trivial process. The reason being, CLAs require that developers certify they own the copyright to their code, and that their contribution does not infringe on the rights of others, two non-obvious determinations in the case of professional software developers. For one, depending on the time of day, computer used, type of contribution, or even employee handbook, the code may be the property of the employer. For another, the employee may have theoretical access to trade secrets and other confidential information, meaning they may inadvertently jeopardize a corporate patent or agreement, even if they didn't intend to do so. For the maintainer, the project needs to stand up a system to track every potential contributor that has signed the agreement, as well as a CI-like mechanism to ensure commits cannot be merged unless covered by the CLA. Yes, there are services out there like CLAHub, but in my experience, since CLAs are non-standard, so too are the processes required to implement them, meaning many projects will need to create their own acceptance experience. Regardless of the means, unlike say, a license, in almost all CLAs, assent isn't manifested by use (or in this case submission), meaning there's an additional system, custom or third-party, that maintainers must stand up and maintain, third-party or otherwise. diff --git a/src/content/posts/2021-02-01-what-to-read-before-starting-or-interviewing-at-github.mdx b/src/content/posts/2021-02-01-what-to-read-before-starting-or-interviewing-at-github.mdx index fa975cdfc..1656b1b81 100644 --- a/src/content/posts/2021-02-01-what-to-read-before-starting-or-interviewing-at-github.mdx +++ b/src/content/posts/2021-02-01-what-to-read-before-starting-or-interviewing-at-github.mdx @@ -53,7 +53,7 @@ These posts cover those foundational patterns—the habits, tools, and mental mo ## Role-specific guides -The posts above apply broadly, but if you're a Product Manager, Technical Program Manager, Chief of Staff, or Engineering Manager, you might be wondering what those roles look like in practice at a company where the defaults around hierarchy, process, and decision-making are a bit different from what you're used to. These go deeper. +The posts above apply broadly, but if you're a Product Manager, Technical Program Manager, Chief of Staff, or Engineering Manager, you might wonder what those roles look like in practice at a company where the defaults around hierarchy, process, and decision-making are a bit different from what you're used to. These go deeper. - [Twelve things a product manager does](https://ben.balter.com/2016/06/06/twelve-things-a-product-manager-does/) — What does a product manager actually do all day? Twelve responsibilities from user advocacy to strategic thinking. - [Nine things a (technical) program manager does](https://ben.balter.com/2021/03/26/nine-things-a-technical-program-manager-does/) — What a Technical Program Manager actually does day-to-day, from a PM who transitioned into the role. diff --git a/src/content/posts/2023-01-10-manage-like-an-engineer.md b/src/content/posts/2023-01-10-manage-like-an-engineer.md index 894a30139..32fd1ba2d 100644 --- a/src/content/posts/2023-01-10-manage-like-an-engineer.md +++ b/src/content/posts/2023-01-10-manage-like-an-engineer.md @@ -71,7 +71,7 @@ Today, I don't believe that a complete "deprecation" of management is possible, Managing like an engineer means using the same tools and workflows that engineers use to plan, track, and communicate their own work. It means making work visible, writing things down, and embracing collaboration. After all, if that's the best way to build software, should it not also be the best way to manage software development? -[^2]: Track tasks and their progress in issues, cc relevant teams, and cross reference relevant issues to naturally [capture and expose process](https://ben.balter.com/2015/11/18/tools-to-empower-open-collaboration/#2-captures-and-exposes-process). Issues bring the most value to teams when work happens on and around the issue, rather than holding important discussions in chat or over video with the issue being used merely as a "TODO" with tracking open and closed state or a broadcast medium for occasional formal updates to stakeholders (for which Discussions are better suited). +[^2]: Track tasks and their progress in issues, cc relevant teams, and cross reference relevant issues to naturally [capture and expose process](https://ben.balter.com/2015/11/18/tools-to-empower-open-collaboration/#2-captures-and-exposes-process). Issues bring the most value to teams when work happens on and around the issue, rather than holding important discussions in chat or over video with the issue being used merely as a `TODO` with tracking open and closed state or a broadcast medium for occasional formal updates to stakeholders (for which Discussions are better suited). [^3]: Long before the term "inner-source" became popular, GitHub had co-opted the workflows and communication patterns of the open source community for its own internal development. While much has been written over the years about "how GitHub uses GitHub to build GitHub", the concept of using GitHub to *manage* GitHub fell out of popularity as GitHub grew (and outgrew its own tools). Now that GitHub has native planning-and-tracking capabilities, it's the perfect tool for managers. diff --git a/src/content/posts/2023-01-13-great-extended-leave-documents.md b/src/content/posts/2023-01-13-great-extended-leave-documents.md index 5c4a846d0..6c9e14323 100644 --- a/src/content/posts/2023-01-13-great-extended-leave-documents.md +++ b/src/content/posts/2023-01-13-great-extended-leave-documents.md @@ -41,7 +41,7 @@ List any recurring meetings you normally run or attend, their frequency, and who | Meeting | Frequency | Responsibilities | Who | | ------------------------- | -------------- | --------------------- | ----- | -| Staff meeting | Mondays @ 10AM | Set agenda, run | Susie | +| Staff meeting | Mondays @ 10 AM | Set agenda, run | Susie | | 1:1s with directs | Weekly | Take notes, follow up | Danny | #### 👥 Rolodex diff --git a/src/content/posts/2023-05-19-pull-requests-are-a-form-of-documentations.md b/src/content/posts/2023-05-19-pull-requests-are-a-form-of-documentations.md index 39569950e..0afa73f5f 100644 --- a/src/content/posts/2023-05-19-pull-requests-are-a-form-of-documentations.md +++ b/src/content/posts/2023-05-19-pull-requests-are-a-form-of-documentations.md @@ -17,7 +17,7 @@ To that end, here are a few practices I follow when authoring pull requests to e - **Enough context** - So that others outside your team (or yourself years from now) can understand the change. Think of it as a time capsule or a message in a bottle to your future self and future contributors. - **@mention responsible team** - if not automatically requested via `CODEOWNERS`. Not only does this bring visibility to the PR, it also makes ownership clear by explicitly calling out the responsible team. Be sure to include why you're @mentioning the team (what action is requested, if any) so that it's surfaced in the notification. - **CC or [`fixes`](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests) related issues** - to create a trail of breadcrumbs to improve discoverability and allow others to opt-in to additional context. As an added bonus, it will auto close the tracking issue for you. -- **Task lists** - To reflect the current state of the PR - for example "TODO: add tests" and to capture process +- **Task lists** - To reflect the current state of the PR - for example `TODO: add tests` and to capture process - **Screenshots or animated GIFs** - to illustrate UI changes without requiring other to spin up a dev environment - **In-line documentation** - Linking back to the PR from the code itself for especially complex or nuanced changes - **Review your own PR** - Comment in line to highlight specific changes for reviewers that you're less confident on. diff --git a/src/content/posts/2026-05-31-ai-first-program-management.md b/src/content/posts/2026-05-31-ai-first-program-management.md index 00e3de8fd..00b38b2ea 100644 --- a/src/content/posts/2026-05-31-ai-first-program-management.md +++ b/src/content/posts/2026-05-31-ai-first-program-management.md @@ -8,7 +8,7 @@ When I first wrote about [the nine things a program manager does](/2021/03/26/ni That scramble hasn't gone away. But increasingly, I'm not doing it alone. ## From async to AI-augmented -I + The evolution makes sense in hindsight. I've argued that teams should [default to async communication](/2022/03/17/why-async/) — written, durable, discoverable artifacts over synchronous [meetings](/2023/04/20/meetings-are-a-point-of-escalation/). That managers should [use the same tools engineers use](/2023/01/10/manage-like-an-engineer/) — issues, pull requests, project boards — to plan and track their own work. And most recently, that [AI agents are extending the same patterns](/2026/03/18/agentic-workflows/) of transparency and code review that made open source successful. These ideas aren't disconnected. They're an evolution.