<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="/rss.xsl"?>
<rss version="2.0"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Grady Berry Ward — Projects, Essays, and Notes</title>
    <link>https://grady.dev/</link>
    <description>Projects, essays, and notes about technology, people, privacy, work, and the things worth caring about.</description>
    <language>en-US</language>
    <generator>Hugo</generator>
    <ttl>60</ttl>
    <copyright>Copyright © Grady Berry Ward</copyright>
    <atom:link href="https://grady.dev/index.xml" rel="self" type="application/rss+xml" />
    <atom:link href="https://grady.dev/" rel="alternate" type="text/html" />
    <image>
      <url>https://grady.dev/favicon-32x32.png</url>
      <title>Grady Berry Ward — Projects, Essays, and Notes</title>
      <link>https://grady.dev/</link>
      <width>32</width>
      <height>32</height>
    </image>
    <lastBuildDate>Sat, 30 May 2026 00:00:00 +0000</lastBuildDate><item>
      <title>The Iceberg of Work</title>
      <link>https://grady.dev/projects/iceberg/</link>
      <guid isPermaLink="true">https://grady.dev/projects/iceberg/</guid>
      <pubDate>Sat, 30 May 2026 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>writing</category>
      <category>ai</category>
      <category>labor</category>
      <description>A job is more than meets the eye - assume otherwise at your own peril</description>
      <content:encoded>&lt;h2 id=&#34;thesis&#34;&gt;Thesis&lt;/h2&gt;&#xA;&lt;p&gt;Proximity is a fantastic heuristic for authority. The trust you should have in someone&amp;rsquo;s opinion should generally be proportional to how well they understand the idea or problem they are engaging with. &lt;strong&gt;This is why I&amp;rsquo;m optimistic about how AI will reshape white-collar work.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve noticed that people tend to think AI will displace their coworkers but not themselves. This is because our interface to our teammates and their work is mediated through mechanical signals - pixels and keystrokes - but our understanding of our own work is far richer than what we express through those physical inputs and outputs. I&amp;rsquo;m a software engineer, and my work is experienced by others as chat messages and code changes, but the quality and importance of these isn&amp;rsquo;t the text itself. A coworker that sees my work as interchangable with text generation is demonstrating they do not understand my job. It would be silly to see this iceberg (the hidden mass that supports the whole) within my own work and fail to assume it about the work of others. Extrapolating from that principle:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;When I find myself thinking of fully replacing a human function with a machine to emulate it, I try to think through what pieces of that job aren&amp;rsquo;t encoded in inputs and outputs. Judgement, discretion, knowing when to break rules, etc.&lt;/li&gt;&#xA;&lt;li&gt;There are piece of my job I do think are automatable, and I&amp;rsquo;m sure this is true for others too. I deeply trust a laborer&amp;rsquo;s instincts about what pieces of their job could be automated, and which cannot.&lt;/li&gt;&#xA;&lt;li&gt;Companies should be optimistic about bottoms-up automations, and should be skeptical of top-down automation initiatives.&lt;/li&gt;&#xA;&lt;li&gt;While AI will make individuals in every field more efficient, I won&amp;rsquo;t worry about wholesale replacement of a field by AI until I hear the experts - the people who do that job - express that forecast.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;It would be idiotic of me to look at what a CEO does as text generation, yet many of them seem to see the rest of us as input-output text generation cost centers. I marvel at the arrogance it takes to assert &amp;ldquo;AI can replace this job&amp;rdquo; without having ever done that job.&lt;/p&gt;&#xA;&lt;h2 id=&#34;my-experience&#34;&gt;My Experience&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m a software engineer. I use AI in unfathomable volumes and varieties - it makes me radically more effective. Through that use, I&amp;rsquo;ve started to see clearly the pieces of my job that I expect AI systems will not be able to replace, they fall into a few categories:&lt;/p&gt;&#xA;&lt;h3 id=&#34;judgement&#34;&gt;Judgement&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Our profession oscillates between identifying as engineers and hackers. Much of what differentiates a good SWE from a great one is fluidity between these poles. The best engineers know when to go with the quick hack and when to build it right. Folks that haven&amp;rsquo;t paid the price for bad choices (in both directions) rarely have that insight.&lt;/li&gt;&#xA;&lt;li&gt;Similarly, much of software engineering is about balancing between goods, not achieving some maximal outcome along one dimension. Most of the time this means balancing complexity against some other goal like velocity, consistency, performance, or simplicity. LLMs may be great at lifting a concrete implementation into an abstraction, or decomposing an abstraction to concrete implementation, but they rarely demonstrate the prudence to know when to do each.&lt;/li&gt;&#xA;&lt;li&gt;Some of the biggest pieces of impact in my career have been pushing back on our leadership when our current prioritization and approach may lead to technical problems in sequencing, timeline, or bitrot, and knowing how forcefully to make the push. AI systems are good at doing, they rarely display strategic reasoning in &lt;em&gt;what&lt;/em&gt; to do or &lt;em&gt;when&lt;/em&gt; to do it.&lt;/li&gt;&#xA;&lt;li&gt;Though my job is profoundly technical, it often involves aesthetics - amorphous senses of what makes a UI, an algorithm, or an API beautiful. These fleeting moments of inspiration often end up being profoundly impactful on the trajectory of our products and teams. This is an area I have yet to see LLMs express sound judgement in, in large part (I suspect) because most of us rarely have the vocabulary to express and explain our aesthetic preferences in the thin pipe of language.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;human-management&#34;&gt;Human Management&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I mentor our junior engineers, which both helps them become more effective over time, and lets me more deeply understand and revisit our infrastructure, and learn new things from them and the experiences they bring with them. AI makes for a great tutor, but it&amp;rsquo;s unidirectional, and can only answer the questions you know to ask.&lt;/li&gt;&#xA;&lt;li&gt;I temper the instincts of our PMs and designers, often translating their vision through the lens of technical feasibility and maintenance - &amp;ldquo;if we are OK with slightly different functionality, it will be 10x easier to maintain&amp;rdquo; is a series of tokens I regularly emit by vibrating air, but is hard for agents to do precisely because they&amp;rsquo;re optimized to achieve the task as the user has asked for it.&lt;/li&gt;&#xA;&lt;li&gt;I conduct interviews, and have developed intuitions for where candidates should be challenged, assisted, and how a candidate&amp;rsquo;s internal model of the problem evolves over time. The mirrored state of the candidate&amp;rsquo;s mind that lives within mine gives me a much more reliable signal about how someone will perform in a job than externally visible signals.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;context&#34;&gt;Context&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;While solving problems in the codebase and infrastructure, I accumulate whiffs of unrelated data - sometimes it&amp;rsquo;s a log that looks out of place, sometimes its a file that looks too big, or a test that takes longer to run than I expect. It&amp;rsquo;s rarely the right choice for me to dive head-first into solving or understanding these surprising tidbits, but their accumulation is at the heart of my ability to hear about a customer complaint or strange failure mode and quickly identify hypotheses about how it might have come to be. LLMs can solve any problem that is specifically stated, but they don&amp;rsquo;t do well to make connections between sparse signals that cannot all fit into a context window.&lt;/li&gt;&#xA;&lt;li&gt;If I had a dollar for every time an LLM tried to reverse an architectural decision (or bug fix), I&amp;rsquo;d go out to a really nice dinner - one of those ones where the food is tiny. LLMs can be reminded to check git history, they can be given detailed explanations and admonitions, they can have documentation of everything, but at the end of the day, LLM performance is trained against task execution, and the fastest way of accomplishing task X is often deleterious to the thousand other tasks and goals that came before it. I hold more context in my head about bugs that I have fixed than can fit into 1M tokens.&lt;/li&gt;&#xA;&lt;li&gt;The experience that has given me the best insight into our customers has been visiting them in person. Spending two days on a family ranch in South Dakota taught me more about the needs of ranchers than had months of prior reading. Experiencing the frustrations of a vegetable farmer as we watched her click through her invoicing flow in her wash facility in Vermont gave me more insights about how to change the product than had months of playing with the website in my office. Embodied and interpersonal experience is at the heart of figuring out what product should be built.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Note: in these problems of context there are technical ways you could imagine scaffolding an agentic workstream such that they can mimic or even surpass human skill on these kinds of tasks. While the other two categories I&amp;rsquo;m fairly confident are not going away, I do think AI will find ways of chipping away at these advantages.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-gap-is-terrifying&#34;&gt;The Gap is terrifying&lt;/h2&gt;&#xA;&lt;p&gt;The thing I fear is not AI capable of these parts of my job, it&amp;rsquo;s the delusion that these gaps don&amp;rsquo;t exist or matter.&lt;/p&gt;&#xA;&lt;p&gt;That delusion ends poorly for the workers, who face unemployment and systematic de-valuing of their labor and humanity. It ends poorly for the companies - who will eventually fail or pay enormous costs for shortsighted layoffs and automations. It ends poorly for our culture, which further reduces the vibrancy and value of human life and thought to its measurable constituents.&lt;/p&gt;&#xA;&lt;p&gt;I fear our society will steer for this iceberg because it looks so small.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Corporate Extinction</title>
      <link>https://grady.dev/projects/corp-extinction/</link>
      <guid isPermaLink="true">https://grady.dev/projects/corp-extinction/</guid>
      <pubDate>Sat, 30 May 2026 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>writing</category>
      <category>ai</category>
      <category>labor</category>
      <description>AI will be a mass extinction event, but not in the ways that Twitter would have you believe</description>
      <content:encoded>&lt;p&gt;In corporate archeology, AI will be a mass extinction event, but not in the ways that Twitter would have you believe. Sure, some companies will die from not taking AI seriously enough: some will be overtaken by nimbler AI-powered competitors, some will implode from cybersecurity breaches, others will lose their best talent to self-employment. But most companies that die in the next five years will die by suicide, not by murder.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Occupational Cosplay.&lt;/strong&gt; AI empowers us to roles that we are not familiar with, and creates the impression of efficacy. Using AI, the CEO can ship code, the coder can write marketing copy, and the marketer can write an investor email. In each case, the employee is using AI in a domain where they can&amp;rsquo;t evaluate the quality of what they&amp;rsquo;re producing, and as a result, assume they&amp;rsquo;re now capable of a job that they never really understood. To crystalize this, think about a metric: the percent of human time spent making decisions in one&amp;rsquo;s areas of expertise. In well run organizations, this number is high. AI tanks this metric because it allows employees to jump into jobs they don&amp;rsquo;t understand. Organizational disfunction and error will result.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Productivity Dysmorphia.&lt;/strong&gt; Healthy organizations have a strong understanding for how all activities tie back to business outcomes. When an organization goes all-in on AI, every incentive pulls employees toward building the project that will demo well, toward blind automations, toward the huge first draft, and the visible signs of AI progress, mistaking use of AI for concrete business value. Employees, management chains, corporations, and markets are all buying into a distorted sense for what building value looks like, substituting the excitement for deployment of AI for genuine progress toward business objectives. Consider three facts that are benign individually, but braid into something lethal: AI is fun to play around with, management is all-in on AI, and AI makes many non-productive tasks feel productive.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Drowning in Content.&lt;/strong&gt; Corporate information systems are delicately balanced ecosystems, and AI is an invasive species, replicating at a pace that will quickly out-compete both human-generated content, and any system of meaningful informational consumption. How&amp;rsquo;s your inbox/slack looked recently? Mine is noisy as hell - filled with AI content - sometimes slop, sometimes insightful and useful. Even when AI outputs are valuable (which isn&amp;rsquo;t always the case), finite constraints on attention, execution, and resources are hard constraints that don&amp;rsquo;t have any easy answers. AI to sort and filter to the important messages? AI to route to other AIs for further summary? AI to react to and take action based on AI analysis? People will try everything, but I suspect all such attempts will treat the symptom of noise rather than it&amp;rsquo;s cause - which is a lack of focus and vision. Teams that turn a blind eye to these hard questions will eventually see the their cattywampus AI infrastructure collapse under the weight of its cost and impotence.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Token Cliff.&lt;/strong&gt; Today, frontier labs are heavily subsidizing token costs, as are the AI-powered venture backed startups running on their infrastructure. When those businesses shift toward making a profit, the cost of AI powered tooling is going to go up, probably a lot, and probably all at the same time. That shift will kill companies that baked unsustainable compute into their business models. For those that survive that cliff, there&amp;rsquo;s a famous saying about ad spend: half is wasted, but it&amp;rsquo;s impossible to know which half. Token costs will be like advertising expenses - generating real value, but spread out thinly over tons of waste, impossible to optimize because of the structure of value produced. Companies are rushing to ramp up a huge cost center without any tools for estimating the value of their expenditures.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Talent Disruptions.&lt;/strong&gt; AI is throwing a wrench in talent pipelines. Experienced employees working with AI can do far more than they could before - competition for senior talent will shorten tenure in ways that incentivize short-termism. On the other side of the pipeline, junior employees leaning on AI can appear more competent than before, but seem to be failing to develop the depth of understanding that inculcates the judgement needed to step into more senior roles. Many companies will die simply because their employees learn less, and don&amp;rsquo;t stick around as long.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Distraction from Competency.&lt;/strong&gt; AI allows companies to build far outside of their core competencies, and many companies will die because they decided to build infrastructure that they should have just paid someone else to build and maintain. Every software system looks like it&amp;rsquo;s just a database and a frontend until you get to know the challenges of its implementation, at which point you&amp;rsquo;ve paid large prices in time and tokens. Many companies will vibecode core pillars of their business, and then be typing into chat GPT &amp;ldquo;what is a race condition&amp;rdquo; when their shipment doesn&amp;rsquo;t show up, or &amp;ldquo;please implement withholding for all states make no mistakes&amp;rdquo; after the IRS sends them a letter. Successful companies have a strong and narrow thesis of how they generate value. Many companies will perish because they tried to solve problems that they were fundamentally not equipped to solve, but for which AI gave them a plausible first draft that gave them naive confidence.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Underinvesting in People.&lt;/strong&gt; The final way that companies will fail is that they&amp;rsquo;ll forget about people. They&amp;rsquo;ll under-invest in their employees - treating them like input/output cost centers. They&amp;rsquo;ll neglect their customers, using bots to mediate and summarize all conversations - keeping them at arms length. They&amp;rsquo;ll scorn craft and judgement, blindly asserting that AIs can replicate things outside of their understanding. They&amp;rsquo;ll pour money into tokens and software, and divert resources and attention and time away from people, and then one day they will wake up and realize that the people are the only piece of this that ever actually mattered.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ll close with an insight I like from someone I don&amp;rsquo;t. Besos advises that companies should build their long-term business strategy not based on what is changing, but on what will stay the same - Amazon wasn&amp;rsquo;t built based on assumptions of how the internet would evolve, but on the recognition that consumers will always want low prices, large variety, and quick delivery. AI is the quintescence of flux - nobody knows where the technology will be in ten years, and projecting forward is speculation, not forecasting. But I&amp;rsquo;d bet even after ten years of AI disruption, expertise will still be valuable, companies will still need to focus, and the economy will still serve on the needs and wants and preferences of people, not machines.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Age Based Congressional Districts</title>
      <link>https://grady.dev/projects/gerry/</link>
      <guid isPermaLink="true">https://grady.dev/projects/gerry/</guid>
      <pubDate>Sat, 30 May 2026 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>government</category>
      <category>brainstorm</category>
      <description>Fix gerrymandering gerontocracy with one tweak</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Federal congressional districts should be set based on age, not geography.&lt;/strong&gt; The idea is simple: take the birthdays of all eligible voters in a state, order them, and set boundary lines between districts so that each district has the same number of voters. When you go to the polls you would show your ID and have your birthday determine your ballot. Only one other rule: a candidate would not have to be from within an age bracket to run to represent it.&lt;/p&gt;&#xA;&lt;p&gt;This system has many advantages beyond breaking the Gerrymandering doom-loop:&lt;/p&gt;&#xA;&lt;h2 id=&#34;leaders-from-multiple-generations&#34;&gt;Leaders from Multiple Generations&lt;/h2&gt;&#xA;&lt;p&gt;Today, geographically defined districts bolster our ossified gerontocracy, because the wealthiest folks within every district wield the connections, power, and funding to sway its elections, and thus or politics is overly sensitive to the concerns of this group. Age based districts would force parties and candidates to appeal to multiple generations, and would likely elevate a congress that is much younger, less wealthy, and more diverse.&lt;/p&gt;&#xA;&lt;h2 id=&#34;different-generations-different-concerns&#34;&gt;Different Generations, Different Concerns&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;We have far more in common with people of our age than we do with people of our region.&lt;/strong&gt; Pocketbook interests cluster by age cohort - whether it&amp;rsquo;s social security or AI in the labor market - the most potent concerns have age-based constituencies that are today dispersed across districts, without cogent representation (you could even call this &amp;ldquo;cracking&amp;rdquo; of the youth vote in gerrymandering terms… all districting is a choice!). Furthermore, districts exist as a concept to allow for people to have representation for common interests (historically, agricultural and manufacturing, etc). Yet, age tends to be a better predictor than geography when it comes to a wide range of issues (including foreign conflict, climate change, tax policy, social mores, and public benefit structures), issues that have not seen serious public engagement or debate &lt;em&gt;in large part because the constituencies are dispersed.&lt;/em&gt; A politics that has to build cohorts across generations would be a politics that has to grapple with the preferences of people under 40, which today, I think you could argue are largely absent from national politics.&lt;/p&gt;&#xA;&lt;h2 id=&#34;congress-of-leaders-not-of-parties&#34;&gt;Congress of leaders, not of Parties&lt;/h2&gt;&#xA;&lt;p&gt;Many &amp;lsquo;solutions&amp;rsquo; to gerrymandering give more control to parties - encouraging party loyalty and diminishing the personal element of elections. I like personal politics - it brings forward leaders that inspire and ignite us - sometimes through virtue, sometimes through bombast. A congress even more tightly run by parties will weaken the institution, turning a proving ground for our leaders into an organ that only serves parties and their interests. A congress full of intergenerational strivers, personally motivated and branded, is a far more engaging and discursive vision of politics, and is actually much closer to what our founders intended.&lt;/p&gt;&#xA;&lt;h2 id=&#34;unimpeachable&#34;&gt;Unimpeachable&lt;/h2&gt;&#xA;&lt;p&gt;Any approach to districting that relies on discretion by politicians can be gamed. Even in proportional representation and various RCV proposals, there are core elements these plans that rely on the same act of drawing lines on maps, and that leaves the door open for manipulation. The brilliance of age based districting is that it is non-discretionary.&lt;/p&gt;&#xA;&lt;p&gt;Isn&amp;rsquo;t that a great idea? Wouldn&amp;rsquo;t that be a better world?&lt;/p&gt;&#xA;&lt;p&gt;How can we make it so?&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Manifesto</title>
      <link>https://grady.dev/projects/manifesto/</link>
      <guid isPermaLink="true">https://grady.dev/projects/manifesto/</guid>
      <pubDate>Mon, 16 Feb 2026 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>ai</category>
      <category>essay</category>
      <category>love</category>
      <category>writing</category>
      <category>tools</category>
      <description>Humans use tools, never the reverse, a compass for the future</description>
      <content:encoded>&lt;p&gt;Technology has summoned a virgin continent over the horizon, and reason alone cannot navigate us through through the terrain of this new world.&lt;/p&gt;&#xA;&lt;p&gt;We arrived twenty years ago, and began our exploration with the exuberance and arrogance of children - assuming our capacity to create and manipulate technology meant that we could understand and control it. As was developmentally inevitable, today we examine technology with the puerile hungers and fatalism of adolescence - we fantasize about it benefitting us personally, and conceptualize it as a force of nature - a wave to be ridden, its direction outside of our control. It is time for us to grow up - to cultivate the humility and principles of an adult.&lt;/p&gt;&#xA;&lt;p&gt;For we must now see that the terrain of technology that lies ahead of us is not a small island to be cartographed and catalogued - but a continent of profound abundance, unimaginable danger, and completely unknown boundaries. In such foreign terrain we need not a map but a compass - a pointer toward the indelible; toward truths too sacred to be justified by reason, and values inexchangeable for lesser virtues.&lt;/p&gt;&#xA;&lt;p&gt;For the first cornerstone of this project I volunteer the following: &lt;strong&gt;humans use tools, tools cannot use humans&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Software, a medium of infinite pliability, illuminates this distinction. When software is a tool, it can extend our capability, deepen our minds, and allows us to flex our volition. Tools empower the holder. They can be used for both constructive and destructive purposes - their use is not constrained by the maker, and does not serve any master but their wielder. Tools that enhance human capacity introduce risk but also profound possibility, beyond even the imagination of their manufacturer. A good tool allows every holder to extend themselves.&lt;/p&gt;&#xA;&lt;p&gt;Other software constrains the volition of individuals - it surveils, addicts, and manipulates. It treats human minds, means, and messages as substrates for its manufacturer to control, squeeze, and engineer. It substitutes the shallow desires of the coder for the diverse aims, preferences, and values of the individuals that it purportedly serves. Such software reduces people to users - a dehumanization in vocabulary that provides cover for profound thefts.&lt;/p&gt;&#xA;&lt;p&gt;We must call it so. We must scream it while we can. To capture the attention, distort the preferences of, or facilitate the addiction of another human is a theft. It steals not only time, money, and energy, but robs a person of the a defining element of their humanity - their agency. Software facilitates small crimes of this sort at unimaginable scale. We must decide that the small harm of billions is no less degrading to our common dignity than the immiseration or murder of few. Our creator endowed us with the pursuit of happiness, not to be traded away for trinkets of convenience, but as inalienable and inseparable right.&lt;/p&gt;&#xA;&lt;p&gt;We must proclaim that we humans are actors - wielders of tools. We must reject attempts to blur the distinction between principal and agent, between men and machines. We must destroy systems of mechanized manipulation and coercion. We must develop the language, intuition, and zeal to reflexively defend our volition against a wide range of insidious and subtle threats.&lt;/p&gt;&#xA;&lt;p&gt;Humans use tools. Tools may not use humans.&lt;/p&gt;&#xA;&lt;p&gt;This is magnetic north. It is not a sufficient to navigate without error, and we will not always go straight toward it. But we have a compass.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Vibecoding Tutorial</title>
      <link>https://grady.dev/projects/vibecoding/</link>
      <guid isPermaLink="true">https://grady.dev/projects/vibecoding/</guid>
      <pubDate>Sat, 01 Nov 2025 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>websites</category>
      <category>ai</category>
      <description>How to vibecode a personal site</description>
      <content:encoded>&lt;p&gt;Below is advice that I&amp;rsquo;ve given a few friends who have wanted to vibe-code their personal websites. It&amp;rsquo;s a good primer for how to use these tools for nontechnical audiences.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://docs.google.com/document/d/1BHHIVLnzkkMeR2aKLh3_ok4jpE2BmACatSZpO9VxUcw/edit?tab=t.0&#34;&gt;https://docs.google.com/document/d/1BHHIVLnzkkMeR2aKLh3_ok4jpE2BmACatSZpO9VxUcw/edit?tab=t.0&lt;/a&gt;&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>On the name Grady</title>
      <link>https://grady.dev/projects/on-grady/</link>
      <guid isPermaLink="true">https://grady.dev/projects/on-grady/</guid>
      <pubDate>Sun, 20 Jul 2025 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>love</category>
      <category>writing</category>
      <description>Family lore, resillience, and what matters</description>
      <content:encoded>&lt;p&gt;In 2025 I met another Grady, and had a welcome reason to revisit how I came by my name.&lt;/p&gt;&#xA;&lt;p&gt;When my mother was pregnant with me, my parents tentatively planned to name me William. It would have been a family name, and as the first boy born into my extended family, it was a strong contender. As my mother grew larger, they thought about other names, but &amp;ldquo;William&amp;rdquo; remained most likely.&lt;/p&gt;&#xA;&lt;p&gt;But every evening during pregnancy, as they had for a decade before, and at least a decade after, my parents watched the &amp;ldquo;News Hour&amp;rdquo; - the nonpartisan nightly news roundup on PBS. A few weeks before I was born, on July 15th 1994, the News Hour had a segment covering a dam failure in South Georgia, which included a quick interview of a retired couple whose home had been destroyed in the flood - Evelyn and Grady West:&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;EVELYN WEST&lt;/em&gt;: The water come up so fast it, well, it was floated from the top of my washing machine and busted the top off &amp;ndash; all my food &amp;ndash; my food scattered.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;MS. BOWSER (Reporter)&lt;/em&gt;: Evelyn West lost nearly everything. She and her husband, Grady, built this little brick house by the lake five years ago when he retired. It was supposed to be for their golden years. But now at the ages of 68 and 70, they are faced with starting over. They&amp;rsquo;re determined to make the best of it.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;GRADY WEST&lt;/em&gt;: I look at it this way, you know, there&amp;rsquo;s no use of grievin&amp;rsquo; over it, it&amp;rsquo;s a material thing, and it can be replaced, and I&amp;rsquo;ve always been a hard worker, and I think that we can &amp;ndash; between the two of us &amp;ndash; we can overcome this, and really that you haven&amp;rsquo;t got much choice.&lt;/p&gt;&#xA;&lt;p&gt;&lt;em&gt;MS. BOWSER (Reporter)&lt;/em&gt;: For 32 years, Grady West worked for the Crisp County Power Commission that built this nearby dam. It broke at 5:30 last Saturday morning, causing most of the flooding in the Lake Blackshear area. There had been one inch of rain an hour for more than a day. It was too much water, too quickly for the 65 year old earth dam and power station.&lt;/p&gt;&#xA;&lt;p&gt;From that short clip, my parents decided to add Grady to their list of names. My mom always said it was his smile and resilience that stuck with her. After I was born, they both thought (and the labor nurse confirmed) I looked more like a Grady than a William - and the rest is paperwork.&lt;/p&gt;&#xA;&lt;p&gt;So as not to lose this personal treasure to bit rot, I&amp;rsquo;ve recorded the snippet of it above and it&amp;rsquo;s available &lt;a href=&#34;https://drive.google.com/file/d/1XxtK_ZznkVUu3xH60I7Vp-AlkgZ1szbS/view?usp=sharing&#34;&gt;here&lt;/a&gt;.&#xA;At the time of this writing, you can find the full episode &lt;a href=&#34;https://americanarchive.org/catalog/cpb-aacip-507-zc7rn31636&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I have to admit that though I&amp;rsquo;ve heard the story a dozen times in my life, I always assumed it was apocryphal - lore passed down by telephone, rather than an accurate recounting of events. I first heard it when I was quite young, likely in the late nineties, and we wouldn&amp;rsquo;t get internet until well into the next decade. But in the year 2025, given a happy reason to find the source material, and an excellent public archive, I was able to find it in a few minutes.&lt;/p&gt;&#xA;&lt;p&gt;Right before I watched it, I realized that it didn&amp;rsquo;t matter to me whether it was true. The solace and pride I took in the name wasn&amp;rsquo;t based on its veracity, but what it stood for: capability, partnership, and disposition. That it happens to be true is just a bonus. My mother&amp;rsquo;s memory is (at least at times) as accurate and expansive as she claims.&lt;/p&gt;&#xA;&lt;p&gt;I was named for a smile in face of hardship, for a worker sure of his skills, for a man who knew that what really matters isn&amp;rsquo;t the material stuff, but the people. Seeing the clip today I&amp;rsquo;m also struck by the smile Grady and Evelyn seem to share as they stand with each other, the easy confidence they have that they will rebuild, and do so together.&lt;/p&gt;&#xA;&lt;p&gt;I know life is too full of contingency to attribute too much of anything to something as simple as a name, but I can think of times in my life where the name, and the lore, reminded me that I can do hard things, and that people are what&amp;rsquo;s important.&lt;/p&gt;&#xA;&lt;p&gt;Reflecting back a few weeks later, I&amp;rsquo;m also struck by how we can make meaningful impressions on each other even when our connections are fleeting and tenuous. I doubt Grady West will ever know that his ten second spot on the news ended up shaping the life of some unrelated Grady Ward a dozen states away. But disposition and attitude is like that - it has a surprising way of echoing far beyond ourselves.&lt;/p&gt;&#xA;&lt;p&gt;With that in mind: find people that you love, develop your skills, and build something with both.&lt;/p&gt;&#xA;&lt;p&gt;After all, we haven&amp;rsquo;t got much choice.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Zina Ward Website</title>
      <link>https://grady.dev/projects/zina_b_ward/</link>
      <guid isPermaLink="true">https://grady.dev/projects/zina_b_ward/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>websites</category>
      <category>design</category>
      <description>My sister’s professional profile</description>
      <content:encoded>&lt;p&gt;Over christmas break, I got frustrated with my sister&amp;rsquo;s incredibly specific asks from a wordpress template, so I &lt;a href=&#34;http://zinabward.com/index.html&#34;&gt;built her a website instead&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;After a brief period of haggling over the acceptable level of bells and whistles (I wanted more), we came to a reasonable design consensus, and I implemented the site and fine tuned it with its owner in about five hours.&lt;/p&gt;&#xA;&lt;p&gt;Scroll down past the menu to see some fun. At some point I&amp;rsquo;ll learn non-vanilla JavaScript, but it wasn&amp;rsquo;t for this project.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>WSMD - What should Maddie Do?</title>
      <link>https://grady.dev/projects/wsmd/</link>
      <guid isPermaLink="true">https://grady.dev/projects/wsmd/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>websites</category>
      <category>design</category>
      <category>tools</category>
      <description>A sprint-written tool for the indecisive</description>
      <content:encoded>&lt;p&gt;Maddie Dollins is a dear friend who is frequently frustratingly indecisive.&lt;/p&gt;&#xA;&lt;p&gt;One night at dinner she asked if she should have chocolate milk - to which I said “I do not care”. She then asked if she should have regular milk. This broke the camel’s back, and in a rush of an hour, I built and published WSMD - &lt;a href=&#34;http://gbdubs.github.io/whatshouldmaddiedo/&#34;&gt;What Should Maddie Do&lt;/a&gt; - a simplified magic-eight-ball that simply returns a yes or no.&lt;/p&gt;&#xA;&lt;p&gt;No frills, basic code, cute styles. Introductory and fun!&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Wingspan Deck Generation</title>
      <link>https://grady.dev/projects/wingspan/</link>
      <guid isPermaLink="true">https://grady.dev/projects/wingspan/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>art</category>
      <category>birds</category>
      <category>tools</category>
      <category>gifts</category>
      <description>Learn about the birds in your local area through a game</description>
      <content:encoded>&lt;p&gt;One of my favorite board games is Wingspan - an engine building game&#xA;where you collect different species of birds. The game instilled an appreciation&#xA;for our avian friends in me, and was my introduction to the wonderful world of birding.&lt;/p&gt;&#xA;&lt;p&gt;As anyone who loves something desperately, the flaws in the wingspan game were more&#xA;obvious to me than to most. The nest types were often incorrect. The clutch sizes capped&#xA;out at six. Some of the powers within the game were too much, others were too little. The&#xA;maps only showed their geographic proximity in terms of continents.&lt;/p&gt;&#xA;&lt;p&gt;Most importantly, the birds were from all across the world, making them not very useful&#xA;for fine-tuning your skills on your local bird populations. I can&amp;rsquo;t tell you the number&#xA;of times I thought I saw a Dunnock in Colorado, only to learn much later that they&amp;rsquo;re only&#xA;found in Europe! I needed to have a wingspan deck that just had my local birds in it, so I&#xA;could become an expert at identifying at home.&lt;/p&gt;&#xA;&lt;p&gt;So I coded.&lt;/p&gt;&#xA;&lt;p&gt;And I coded.&lt;/p&gt;&#xA;&lt;p&gt;And I coded.&lt;/p&gt;&#xA;&lt;p&gt;Too.&lt;/p&gt;&#xA;&lt;p&gt;Much.&lt;/p&gt;&#xA;&lt;p&gt;Code.&lt;/p&gt;&#xA;&lt;p&gt;I had to build infrastructure&#xA;for scraping sites which were hostile to it (sorry Cornell ornithology lab, All About Birds, Avibase,&#xA;and others). I built infrastructure for coorelating sources, only including a fact like a wingspan&#xA;in the deck if it could be corroborated between two sources to within 10%. I built infrastructure&#xA;for finding creative-commons licensed images of the birds, AI to find the bird in the image and crop it&#xA;well, and build complicated infrastructure for&#xA;keeping detailed records of sources and methods, both for debugging, and appropriate attribution.&#xA;So far I&amp;rsquo;ve written 39k lines of code to tackle this problem.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/wingspan_1.png&#34; alt=&#34;A card of an American Golden Plover, generated by the first generation of my code.&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve now gone through three generations of these cards, and they&amp;rsquo;ve changed over time significantly&#xA;in response to play-test feedback from my friends and family.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/wingspan_2.png&#34; alt=&#34;A card of a Blue-headed Vireo, generated by my code.&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;In the third generation of the cards, I started to use AI to generate the images, both because finding good images in the creative commons is hard, and because the uniform style lended itself to it.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/wingspan_3.png&#34; alt=&#34;A card of a Blue-headed Vireo, generated by my code + generative AI.&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;I expect this project will never be fully done. There are too many small things I&amp;rsquo;d like to improve.&#xA;Instead, I suspect I&amp;rsquo;ll continue to make small changes every six-ish months when I gift a deck to a&#xA;friend.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Ward Lab</title>
      <link>https://grady.dev/projects/ward_lab/</link>
      <guid isPermaLink="true">https://grady.dev/projects/ward_lab/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>websites</category>
      <category>design</category>
      <category>education</category>
      <description>An academic profile for my father’s lab work</description>
      <content:encoded>&lt;p&gt;My father is a professor at UVM, where he studies microbiology and molecular genetics.  In 2017 as a birthday present, I made him a website using Hugo, and the Academic theme. The theme I used was superb at providing most of the functionality required, but it took a few months of tinkering with my father to get everything exactly the way he wanted (publications ordered in certain ways, display settings configuration based, etc.)&lt;/p&gt;&#xA;&lt;p&gt;The end result is lovely, and supremely updatable.  I wrote some scripts so that he can easily publish his work to the site (with two clicks) and veiw local edits as they happen (all without ever touching the command line).&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>VOAT - Interactive</title>
      <link>https://grady.dev/projects/voat_2/</link>
      <guid isPermaLink="true">https://grady.dev/projects/voat_2/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>art</category>
      <category>education</category>
      <category>websites</category>
      <description>Learn CSS while generating creative patterns</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;This project is a work in progress, it still has lots of work to be done.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;A few years ago, I created a project called &lt;a href=&#34;https://grady.dev/projects/voat/&#34;&gt;VOAT&lt;/a&gt;, in which I used a simple space filling algorithm, alongside a variety of different CSS properties to generate gorgeous patterns. I recently revisited this project with the intent on showing folks how it was made, and introducing folks to CSS.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/voat_2_1.png&#34; alt=&#34;The interactive voat editor&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;The result is a new site, &lt;a href=&#34;https://voat.app&#34;&gt;voat.app&lt;/a&gt;, which houses an interactive editor for the underlying algorithm in VOAT, and has a UI friendly way of modifying the CSS properties that shape and influence the pattern. If you like a pattern, you can &amp;ldquo;share&amp;rdquo; it, and it will be recorded in a&#xA;library of creations (which you can peruse via an infinite scroll in the library tab).&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/voat_2_2.png&#34; alt=&#34;A collection of patterns in the voat libarary&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;This project has a ton more to go before it&amp;rsquo;s ready for general release. My goal for the project is now significantly broader than when I first got started. I want to come up with a few other CSS-only&#xA;backing patterns and algorithms (not just the original one), implement inheritance and priority effectively, and give folks the ability to create and name their own patterns.&lt;/p&gt;&#xA;&lt;p&gt;However, given that this is a lower priority than some other projects I&amp;rsquo;ve been working on recently, It&amp;rsquo;s getting pushed to the wayside. I&amp;rsquo;ll update this site when VOAT App is ready for public consumption.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/voat_2_3.png&#34; alt=&#34;One of my favorites - is it a grid or a funky groove? Oh it&amp;rsquo;s both my friend, it&amp;rsquo;s both.&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;UPDATE (2023): You can now play around with many derivative algorithms (and see the many beautiful images created through them) at &lt;a href=&#34;https://abound.art&#34;&gt;ABOUND.art&lt;/a&gt;.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>VOAT</title>
      <link>https://grady.dev/projects/voat/</link>
      <guid isPermaLink="true">https://grady.dev/projects/voat/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>art</category>
      <category>algorithms</category>
      <category>tools</category>
      <description>Variations on a Theme (Elgar) meets a classic by Frank Stella</description>
      <content:encoded>&lt;p&gt;TL;DR: With a fun algorithm, slight parameter tweaks lead to really different results, as I show in a &lt;a href=&#34;https://gbdubs.github.io/voat/&#34;&gt;work&lt;/a&gt; based on Elgar&amp;rsquo;s enigma variations.&lt;/p&gt;&#xA;&lt;p&gt;A good piece of art compells you to understand the process that created it, whether it is the emotion of the composer, or the logic of the painter. A revlation while looking at a piece by Frank Stella made me understand the fundamental mechanism that was generating the work, and gave me confidence that I could recreate it.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/voat_1.png&#34; alt=&#34;An output of the VOAT program&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Squares (with side of size 1), with two quarter-circles in opposite corners (with radius one-half), in both configurations, with space filling between regions, forms the basis of this work by stella.&lt;/p&gt;&#xA;&lt;p&gt;After more time than I would like to admit, I was able to recreate stella’s work in the browser.  There were so many minutia and little tricks that if even slightly off in any function, the code would mis-render the full piece.  I came to enjoy these mis-renderings more than I enjoyed the final piece, so once it was completed, I looked to see if I could alter the rules slightly and capture different feelings/emotions with the results.&lt;/p&gt;&#xA;&lt;p&gt;The results were so varried and interesting that I had to share them.  Each had a personality I could never have tried to design.  The overall impression each left was distinct, and the commonalites between them felt just as important as their many differences.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/voat_2.png&#34; alt=&#34;An output of the VOAT program&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/voat_3.png&#34; alt=&#34;An output of the VOAT program&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/voat_4.png&#34; alt=&#34;An output of the VOAT program&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;I ended up publishing a set of them as “VOATCSS” - Variations on a theme - a reference to Edward Elgar’s piece by the same name, where he paints portraits of his close friends through the stroke of a common musical theme. Similarly, each of the components of this collection were given a color scheme and parameterization that reminds me of a person that I cared deeply for.&lt;/p&gt;&#xA;&lt;p&gt;UPDATE (2023): You can now play around with many derivative algorithms (and see the many beautiful images created through them) at &lt;a href=&#34;https://abound.art&#34;&gt;ABOUND.art&lt;/a&gt;.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Trees</title>
      <link>https://grady.dev/projects/trees/</link>
      <guid isPermaLink="true">https://grady.dev/projects/trees/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>algorithms</category>
      <category>tools</category>
      <description>Invertible enumeration of the set of possible Binary Trees</description>
      <content:encoded>&lt;p&gt;Recursively enumerating all possible sparse binary trees is easy.  Far harder is coming up with a stable mapping between the integers and this set of trees. I was able to do this after a lot of thought.&lt;/p&gt;&#xA;&lt;p&gt;The code is here, but it is from like four years ago, so please be warned.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Terry v. Ohio &#43; Bulk Infringement</title>
      <link>https://grady.dev/projects/terry/</link>
      <guid isPermaLink="true">https://grady.dev/projects/terry/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>privacy</category>
      <category>writing</category>
      <category>government</category>
      <description>Case level analysis generates poor precedent</description>
      <content:encoded>&lt;p&gt;&lt;em&gt;Terry v. Ohio&lt;/em&gt; is known for it&amp;rsquo;s implications on the probable cause requirement of the fourth amendment, but something else jumped out at me when I put myself in the shoes of the Warren court: given the fact pattern, they were doing their best to encourage good policework, and in the case of stop and frisk the differentiation between &amp;lsquo;good&amp;rsquo; and &amp;lsquo;bad&amp;rsquo; policing hinges on the quality of the officer&amp;rsquo;s decision making (the only proxy for which we have is the outcome of the individual choices weighed in the decision):&lt;/p&gt;&#xA;&lt;p&gt;The majority tries to write narrowly. I&amp;rsquo;d guess that they thought that the correct outcome was to uphold the search and they were grasping for a reason why the stop could be justified without destroying probable cause. If so, I see where they are writing from. I&amp;rsquo;m at all concerned with Terry&amp;rsquo;s fate, but I definitely care about supporting the McFaddens of the world. McFadden made a judgement call to stop and frisk Terry and his coconspirators, and out of this individual decision, an agreeable outcome arose. Were McFadden less perceptive, more suspicious, or less discriminating we wouldn&amp;rsquo;t be talking about &lt;em&gt;Terry&lt;/em&gt;. But as it happened, the case that justifies Stop and Frisk is a &lt;em&gt;true positive&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Zoom back for a second. An officer&amp;rsquo;s decision on whether to Stop and Frisk (S+F) a civilian has four outcomes, based on whether the officer decides to stop (STOP) or not (PASS), and whether the civilian is actually in possession of illegal goods or arms (GUILTY) or not (INNOCENT):&lt;/p&gt;&#xA;&lt;p&gt;(1) True Negative (PASS, INNOCENT)&#xA;(2) False Negative (PASS, GUILTY)&#xA;(3) False Positive (STOP, INNOCENT)&#xA;(4) True Positive (STOP, ARREST)&lt;/p&gt;&#xA;&lt;p&gt;There are clear downsides to False Positives and False Negatives. &lt;strong&gt;False positives&lt;/strong&gt; seriously intrude on basic liberties to be secure in person and posession, tend to be racially biased, and create mistrust between law enforcement and civilians. &lt;strong&gt;False negatives&lt;/strong&gt; likely increase crime rates and embolden criminals. A city&amp;rsquo;s choice on how and if to conduct S+F &lt;strong&gt;should probably be based on a concious tradeoff between the relative incidence of false positives and false negatives&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;p&gt;But thats now how courts operate. In &lt;em&gt;Terry&lt;/em&gt;, we only see a single instance, a True Positive. Were the circumstances in front of the Warren court not that of McFadden and Terry, but, say, Sandra Bland and Brian Encinia (a &lt;em&gt;False Positive&lt;/em&gt;), the court might arrive at a different outcome. Heck, if Officer McFadden had stopped 100 innocent people before stopping Terry, I&amp;rsquo;d argue that should change the outcome, but we don&amp;rsquo;t get to know that context in deciding this case. The problem with &lt;em&gt;Terry v. Ohio&lt;/em&gt; is not (as some argue) that the fact pattern sits at the peak of the watershed &amp;lsquo;probable&amp;rsquo; divide (though it does). Instead, the problem with &lt;em&gt;Terry&lt;/em&gt; is that it is a single case.&lt;/p&gt;&#xA;&lt;p&gt;When constitutional rights are in conflict, courts perform our balancing. When the parties with competing constitutional claims are on opposite benches, performing this balancing is easier than when no single case can capture both of the claims. In thinking about S+F, the fact pattern in front of us heavily influences our intuition: true positives show that there are occasions when we want to defer to officer discretion, and false positives show that officer discretion should not be unlimited.&lt;/p&gt;&#xA;&lt;p&gt;It would be impractical and unwise to conclude based on this sentiment that case by case analysis can yield just outcomes (in this case certainly, and in light of the procedural barriers to justice - in the abstract too). Repairing 4th amendment violations is fraught. Instead, we should take a wholistic approach to justice, outside of the confines of a fact pattern to bias our intuition. It is feasible to evaluate the actual numbers of the four outcomes above in any given city. The Positives just need record keeping, and the Negatives  need a few dozen (fully random) stops per day as controls (ignoring the clear constitutional problems with that practice). From there we could evaluate the harms of both groups in direct comparison (consider targeting a 4:1 FalsePositive to FalseNegative ratio).&lt;/p&gt;&#xA;&lt;p&gt;What if a city is above this target ratio? Then officers should exercice more discretion before making a stop: instruct officers to have a higher degree of confidence before chosing to S+F! Rotate cops off of S+F if their ratio is bad! Provide more training on differentiating between suspicious and atypical behavior! Provide pay incentives for good ratios! Similar remedies could be imagined for a ratio below the target (not volumes, ratios!).&lt;/p&gt;&#xA;&lt;p&gt;These are all specific recommendations to a very general and very hard problem: how do you improve the results (say S+F ratio) of a blackbox system (such as the brain of an officer) that can&amp;rsquo;t be reliably inspected? &lt;strong&gt;You define a cost function, and instruct the system to self-optimize&lt;/strong&gt;. Officers know how to police far better than I (or most judges) do. Rather than defining a set of operational rules (that would be near impossible to enforce or evaluate) for how an officer should decide whether to perform a S+F, I&amp;rsquo;d rather we be honest about the aggregated harms of over or under stopping, and encode our relative thoughts about both in a function that can then be actualized by the experts.&lt;/p&gt;&#xA;&lt;p&gt;More broadly, re-reading &lt;em&gt;Terry&lt;/em&gt; I&amp;rsquo;m reminded that cases are instructive, but single-case rulings will typically miss the rights of people outside of the case. This has me thinking about a ton of topics: incremental rights and incremental infringement, actor driven optimization, and the boundaries of case law for achieving social justice.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Sunrise</title>
      <link>https://grady.dev/projects/sunrise/</link>
      <guid isPermaLink="true">https://grady.dev/projects/sunrise/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>art</category>
      <category>algorithms</category>
      <category>animation</category>
      <description>The best time of the day - faithfully reproduced</description>
      <content:encoded>&lt;p&gt;The colors of this site are copied from nature - they&amp;rsquo;re the colors&#xA;of the sunrise of June 19th, 2025, viewed from RMNP. It was a good one.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-i-built-this&#34;&gt;Why I built this&lt;/h2&gt;&#xA;&lt;p&gt;I love mornings - they&amp;rsquo;re the best time of the day.&#xA;As a new day starts, nothing has yet been decided,&#xA;nature hums with anticipation - tension and potential bound up in stillness.&#xA;I also love sunrises - you get to lay claim to one bookend of the day,&#xA;and if seeing it being born doesn&amp;rsquo;t allow you to sieze it, I can&amp;rsquo;t imagine what could.&lt;/p&gt;&#xA;&lt;p&gt;For several years I had the idea of trying to build a webpage that would capture my&#xA;love for this moment - I knew it would be the fourth iteration of my personal site,&#xA;and would soften my decade-old &lt;a href=&#34;https://grady.dev/destijl/&#34;&gt;V3 de-stijl aesthetic&lt;/a&gt;.&#xA;I wanted it to feel like &lt;a href=&#34;https://www.jambase.com/article/cory-wong-trail-songs-dusk-acoustic-album&#34;&gt;Cory Wong&amp;rsquo;s &amp;ldquo;Trail Songs&amp;rdquo; Albums&lt;/a&gt;, both Daybreak and Dusk sides.&lt;/p&gt;&#xA;&lt;p&gt;I tried many approaches without success.&#xA;I tinkered around with building gradients by hand in Inkscape.&#xA;I tried to build an algorithm for simulating a sunrise based off of photonic refraction&#xA;for &lt;a href=&#34;https://grady.dev/projects/abound/&#34;&gt;Abound&lt;/a&gt;. I played around in SVGator to try to figure out an animation scheme.&#xA;The problem with each approach was I could never get the colors right by eye - even when&#xA;I was sampling from an image of a sunrise, the colors always felt either sterile or&#xA;gaudy. I realized that to emulate the real thing I needed data from the real thing.&#xA;After searching youtube for videos that might suffice (without success), I&#xA;decided:&#xA;&lt;strong&gt;I needed to get a timelapse of the sky on the morning of a perfect sunrise.&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;data&#34;&gt;Data&lt;/h2&gt;&#xA;&lt;p&gt;It took me four tries. Three times I found myself up before&#xA;dawn, perched in the foothills in Colordao, looking westward into the black.&#xA;But the sunrise is tricky - you have to get in position before&#xA;&lt;a href=&#34;https://www.timeanddate.com/sun/usa/boulder&#34;&gt;Astronomical Twilight&lt;/a&gt;&#xA;in order to catch it from black (which nescessarily implies doing so on a non-work day).&#xA;You have to have a timelapse setup that is sturdy - and hardest of all, you get at&#xA;most one shot per day. My first attempt failed when my phone was blown over by wind.&lt;/p&gt;&#xA;&lt;p&gt;But the problem that thwarted the next two times was clouds. Clouds are tricky. They&#xA;totally skew the data on colors because they introduce huge dips in saturation and&#xA;skew toward bluer hues (even at sunrise). They&amp;rsquo;re also ubiquitious.&#xA;If you look out to the horizon from a high vantage, only very rarely will there&#xA;truly be no clouds in the sky. When visibility is good, you need sometimes hundreds&#xA;of miles of clear sky in front of you to fully capture the color of the true horizon&#xA;during a sunrise. Twice I found myself thwarted in the wee hours of the morning by&#xA;clouds.&lt;/p&gt;&#xA;&lt;p&gt;But then, the day before Juneteenth 2025 (the Federal holiday most worthy of celebration for other reasons)&#xA;the &lt;a href=&#34;https://opensnow.com/news/post/cloud-cover-forecast-map&#34;&gt;cloud cover forecast on Open Snow&lt;/a&gt; indicated the holiday might be the day.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;I set an alarm for 12:55 AM.&lt;/li&gt;&#xA;&lt;li&gt;I packed a bag and hit the road by 1:30 AM.&lt;/li&gt;&#xA;&lt;li&gt;By 2:30AM I reached &lt;a href=&#34;https://www.nps.gov/index.htm&#34;&gt;Rocky Mountain National Park&lt;/a&gt;,&#xA;and was briefly delayed because none of their automated payment machines were working&#xA;(sorry for not paying NPS, I tried).&lt;/li&gt;&#xA;&lt;li&gt;By 3:10AM I was in position at &lt;a href=&#34;https://maps.app.goo.gl/iSXNUcLnHZg3B8fC9&#34;&gt;Rainbow Curve&lt;/a&gt; on Trail Ridge Road.&#xA;I setup the ersatz tripod (a laptop stand with a phone ductaped to it, reinforced by books - see image below),&#xA;pointing to the northeast, and slept fitfully from 3:30AM through howling winds&#xA;&lt;ul&gt;&#xA;&lt;li&gt;During setup, I used a compass to point the camera due east, not thinking about the fact that&#xA;Juneteenth is very close to the summer solstice, and thus the sun would be coming from the furthest&#xA;north it ever does.&lt;/li&gt;&#xA;&lt;li&gt;Luckily, while still dark, the moon was rising to the east, and the crescent on the moon pointed&#xA;toward the north strongly enough that I realized my error and was able to salvage the angle in time.&lt;/li&gt;&#xA;&lt;li&gt;I&amp;rsquo;d chosen Rainbow Curve because it points due east through the foothills, giving me a sunrise over the&#xA;plains. However, because of this error, the sunrise happened over the mountains.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-tripod.jpg&#34; alt=&#34;The ersatz tripod&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;When I crawled out of my car to bask in the warm glow of morning, I was thrilled to see that the&#xA;timelapse was perfect - you can see it &lt;a href=&#34;https://grady.dev/img/sunrise-video.mp4&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;building-the-gradient&#34;&gt;Building the Gradient&lt;/h2&gt;&#xA;&lt;p&gt;I got to work a few days later trying to build the CSS that could replicate the perfection of that video.&lt;/p&gt;&#xA;&lt;p&gt;First, I used Google Photos to stabilize the result, which made subsequent analysis much easier.&lt;/p&gt;&#xA;&lt;p&gt;Then, I created a mask which only included the sky (by hand in GIMP), and ran a bash script&#xA;to extract each frame of the image and apply that mask to it. I also put any of the frames&#xA;that happened after the sun poked over the horizon into a different folder. I had quickly realized it was going to be&#xA;hard to solve both the pre-and-post sunrise with the same algorithm.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-mask-1.png&#34; alt=&#34;An example of how I constructed a mask pixel by pixel to capture only the sunrise.&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Using the data to create the output ended up being relatively simple.&#xA;Using Claude Code I tried out 4-5 different algorithms that I sketched out to try to&#xA;achieve the subtle curvature you see in sunrises, including:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Using Iso-Color bands to try to identify the center of a radial gradient based on curvature&lt;/li&gt;&#xA;&lt;li&gt;Using a loss function (of comparison with an original frame) to try to come up with an idealized gradient for each frame&lt;/li&gt;&#xA;&lt;li&gt;Using a vertical color sample from the middle and edges of the image to estimate the eccentricity and center of an elipse we could use as a radial gradient.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;All of these proved unworkable, and while I got some fun failure modes (below), I didn&amp;rsquo;t feel like I was getting much closer.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-radial.png&#34; alt=&#34;A failed experiment&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;But the more I played around with it, the more it felt like maybe a linear gradient (a far simpler approach)&#xA;could be sufficient - I realized that if you add a foreground of mountains, you don&amp;rsquo;t mind the ways the light doesn&amp;rsquo;t&#xA;bend as much near the horizon.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-algorithm&#34;&gt;The Algorithm&lt;/h2&gt;&#xA;&lt;p&gt;So the actual algorithm is dead simple: &lt;strong&gt;In each frame F, select N rows evenly spaced through the frame (20-50 worked well). For each row R, average the color of every pixel in the row. This gives you an F-by-N matrix with a single color value for each cell (Row). This matrix can then be used as keyframes for the resulting linear gradient (with F being the keyframe steps).&lt;/strong&gt; Super simple!&lt;/p&gt;&#xA;&lt;p&gt;There are only a small number of additional effects I added after that basic algorithm. The first was recognizing that the&#xA;sampling of individual rows meant that the matrix it generated wasn&amp;rsquo;t &amp;ldquo;smooth&amp;rdquo; - both in the time&#xA;dimension and in the vertical dimension there was a lot of &amp;ldquo;roughness&amp;rdquo; in that the colors would jitter about&#xA;and you could see the bands clearly at keyframes. I solved this through the standard &lt;a href=&#34;https://en.wikipedia.org/wiki/Box_blur&#34;&gt;box blurring algorithm&lt;/a&gt; (applied to the breakpoint colors, not the pixels!) - just&#xA;average each breakpoint within each keyframe value with the 8 adjacent values in the matrix (2 in the same frame, 3 in the next and 3 in the prev).&#xA;This reduced the amount of noise dramatically.&lt;/p&gt;&#xA;&lt;p&gt;The second realization was that averaging RGB values yields colors that tend toward greys - (visualize the&#xA;3-space of the RGB cube to reason about why). &lt;a href=&#34;https://en.wikipedia.org/wiki/HSL_and_HSV&#34;&gt;HSL&lt;/a&gt; on the other hand doesnt suffer from this proprety (because it&amp;rsquo;s cylindrical), so I converted&#xA;the logic to average based on HSL, and that dramatically improved the color fidelity. In the image below,&#xA;the still frame from the video is on the left, the RGB averaged image is in the center, and the HSL averaged image (no other changes)&#xA;is on the right - what a difference that makes eh!?&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-color-averaging.png&#34; alt=&#34;Three side by side images&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Throughout this iteration process, I built out (or rather described to Claude) a comparison tool to enable me to more&#xA;effectively debug and analyze gradients. It worked great, until&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-comparison-tool.png&#34; alt=&#34;The gradient tool that gives statistics on where an image differs from the ccreated gradient, both numerically and visually&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;While Claude was very helpful through this iterative process, I eventually realized there was a serious issue with the&#xA;color interpretation process early in the pipeline stemming from PNG color profiles somehow corrupted by my processing.&#xA;Additionally, the code had become total spaghetti, there were hardcoded ideas about gamma correction, and the code was&#xA;littered with the detritus of past failed experiments. I started from scratch, and built in programmatic checks at each step&#xA;that the colors being generated matched (or were close to) the raw colors sampled from the image, using a different approach&#xA;to image encoding and sampling, and only using HSL colors throughout, rather than doing conversions back and forth (which,&#xA;it turned out were another source of lossy colors). You can see the compounded color errors most clearly in frames like this&#xA;one, where the blues on the left have hues of ~219, and the blues on the right have hues closer to 201. Huge differences!&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-color-error.png&#34; alt=&#34;A demonstration of the compounded color errors&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;This also allowed me to rebuild the comparison tool, enabling me to quickly iterate on different approaches to averaging&#xA;the pixels across a row, which I realized was the crux of the algorithm after fixing the color correction issues.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-grid-comparison.png&#34; alt=&#34;A 3x3 grid showing 9 different frames of the sunrise and the different algorithms suggestions projected on each&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;The winning algorithm is shown below, labeled as 1. It takes all of the pixels in a row and then does the following to&#xA;decide the color most represenative of that row:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;The core of the algorithm is a function called &amp;ldquo;bucketize_colors&amp;rdquo;, which takes in the pixel data in the row, a&#xA;&amp;ldquo;bucket_width&amp;rdquo;, and a &amp;ldquo;bucket_offset&amp;rdquo;. HSL colors represent hues as an angle between 0 and 360 degrees, like a&#xA;color wheel. This algorithm would construct ranges of hues that cover the full color wheel in equal spacings,&#xA;and then assign each pixel to the bucket that contains it. So for example, a bucket_width of 3 and bucket_offset&#xA;of 2 would yield hue buckets like ([2, 5],[5, 8]&amp;hellip;[359-2]), and a pixel with hue 6.22 would get put into the second&#xA;bucket.&lt;/li&gt;&#xA;&lt;li&gt;Then, starting off with buckets of size 1, it gradually increases the bucket size until a single bucket&#xA;contained more than 15% of all of the pixels in the row, searching all bucket_offsets for a given&#xA;bucket_width to find the best fit if more than one offered 15% capture of the pixels.&lt;/li&gt;&#xA;&lt;li&gt;The pixels in this bucket were then taken as the most representative pixels in the set, and we just returned&#xA;the average of their Hues, Saturations, and Lightnesses as the HSL value for the row.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;You can see this algorithm in action below. #1 is this &amp;ldquo;Hue Bucketed Mean&amp;rdquo; method that I described, while #2 is a&#xA;pure HSL averaging approach.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-better-correction.png&#34; alt=&#34;A frame demonstrating the better color correction of the winning algorithm&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-css&#34;&gt;The CSS&lt;/h2&gt;&#xA;&lt;p&gt;After finishing the algorithm and finding the right sets of gradients for each frame, I needed to figure out how&#xA;to render it on a website in a way that is pleasant.&lt;/p&gt;&#xA;&lt;h3 id=&#34;landing-page&#34;&gt;Landing Page&lt;/h3&gt;&#xA;&lt;p&gt;For the landing page, there was the small matter of tricking CSS into being willing to render an animated gradient,&#xA;because the &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient&#34;&gt;specs will tell you&lt;/a&gt;&#xA;that &lt;strong&gt;linear gradients aren&amp;rsquo;t animatable&lt;/strong&gt;. Because of this I started out by using SVG&#xA;animations, which worked great, but wasn&amp;rsquo;t easy to pause or replay using Javascript, and that felt important to get right.&lt;/p&gt;&#xA;&lt;p&gt;Well, it turns out if you use CSS&amp;rsquo; &lt;code&gt;@property&lt;/code&gt; declarations with type color, and then animate&#xA;&lt;strong&gt;all of the properties that impact the linear gradient in the same set of keyframes&lt;/strong&gt;,&#xA;CSS is willing to render a linear gradient as if it is animated. Many thanks to&#xA;&lt;a href=&#34;https://dev.to/afif/we-can-finally-animate-css-gradient-kdk&#34;&gt;Temani Afif&lt;/a&gt; for this very nifty hack.&lt;/p&gt;&#xA;&lt;h3 id=&#34;project-pages&#34;&gt;Project Pages&lt;/h3&gt;&#xA;&lt;p&gt;For the project page, while talking with my dad I realized that I could use the height of the page to represent&#xA;time, and try to show the transition between frames as the user scrolls down the page, just like projects tend&#xA;to become clearer the further you get into them.&lt;/p&gt;&#xA;&lt;p&gt;Implementing this was relatively simple: the page is divided into sections (per paragraph, heading, etc), and&#xA;each section has two linear gradients that go from left to right. The first is a solid background, which corresponds&#xA;to the linear gradient at the top of the block. The second is a linear gradient from the next block (the top of the&#xA;next block) which increases in opacity from zero at the top of the block to one at the bottom of the block, so that&#xA;we get a smooth color transition within each block, and because the top of one block is the same as the bottom of the&#xA;next block, the transition is relatively seamless.&lt;/p&gt;&#xA;&lt;h3 id=&#34;list-pages&#34;&gt;List Pages&lt;/h3&gt;&#xA;&lt;p&gt;I&amp;rsquo;m not satisfied with any of my current approaches to the list page - I expect I&amp;rsquo;ll iterate on it for a while until&#xA;I find something I like.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-real-author&#34;&gt;The Real Author&lt;/h2&gt;&#xA;&lt;p&gt;One big disclosure I need to make about this project is that I didn&amp;rsquo;t write much code for it - mostly just describing and debugging algorithms.&#xA;Though I described how they should work, Claude&#xA;built all of the&#xA;algorithms in several thousand lines of Golang without much assistance. If I had to build it from scratch myself, building the image processing toolkit&#xA;would have taken me much more time and I would have had many more bugs than if I hadn&amp;rsquo;t relied on Claude (though, Claude still had a variety of bugs that required me to dive deep and understand its code, and in the more than one case, start from scratch).&#xA;As a result, the site was quick to build, and I think it looks really nice, but under the hood it&amp;rsquo;s quite grotesque - code that&#xA;carries the scars of dozens of substantial revisions by multiple authors (me and Claude) without much continuity of thought. An instructive co-programming session.&lt;/p&gt;&#xA;&lt;p&gt;One key finding from the project is that if you&amp;rsquo;re vibe coding, you need to build out (or have Claude build out)&#xA;robust processes for validating the work that it tries to do. I found building out this algorithm comparison tool&#xA;was the key to making consistent progress and evaluating &amp;ldquo;success&amp;rdquo;&#xA;(check out a sample output by clicking below).&#xA;As we start to rely more on LLMs, have clearer ideas of what we want, and better tools to evaluate how we&amp;rsquo;re doing&#xA;against those goals is going to be more and more important,&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-final-debugger.png&#34; alt=&#34;A visual debugger where I could see the gradients generated by multiple, distinct algorithms at once and compare the results&#34;&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-end-result&#34;&gt;The End Result&lt;/h2&gt;&#xA;&lt;p&gt;I really like it. I like watching it. It&amp;rsquo;s a personal brand I feel connected to and proud of. It feels thoughtful - not overdone, not sloppy. Purposeful, data-driven, gorgeous. Even so, I felt ambivalent making it my new homepage - I really liked the &lt;a href=&#34;https://grady.dev/destijl/&#34;&gt;old site&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I have a list of things I&amp;rsquo;d like to try to get working in the future, including a true radial gradient&#xA;(in particular to capture the 3-5 second range of the original video &lt;a href=&#34;https://grady.dev/img/sunrise-video.mp4&#34;&gt;here&lt;/a&gt;), getting the same view later in the year&#xA;(when the sun will rise in the gap in the mountains instead of over them), and trying a different angle/vantage&#xA;to capture the impact of alpenglow on the atmosphere.&lt;/p&gt;&#xA;&lt;p&gt;But this is good for now. The day is young and there is much to do!&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/sunrise-happy.jpg&#34; alt=&#34;Me, happy and smiling after the successful data capture&#34;&gt;&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Student Union (In Line)</title>
      <link>https://grady.dev/projects/in_line/</link>
      <guid isPermaLink="true">https://grady.dev/projects/in_line/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>websites</category>
      <category>design</category>
      <category>education</category>
      <description>A multi-owner distributed WYSIWYG editor with CDN hosting</description>
      <content:encoded>&lt;p&gt;In my time at Brandeis University, I spent 3 years working hard for the Brandeis Student Union as a Student Representative to the Board of Trustees, and an Executive Board member. Over those three years, we had three different computer science students as “web-master”, and three politicos as “communications director”.  The problem was that each web-master would build a beautiful website that was never able to be updated because the communications director never had the technical expertise to update the HTML or use the static site generator.&lt;/p&gt;&#xA;&lt;p&gt;As college was coming to an end, I was frusturated because my time with the board of trustees had not been as productive as I had originally hoped. Looking for a place I could have a lasting legacy and impact, I found it in the Student Union’s website.&lt;/p&gt;&#xA;&lt;p&gt;At its heart, the problem is one of distributed data management and editing.  Students within the union should have different access to edit different data, but the site should be rendered in a way that does not reflect this multiple authorship - components should be rigid enough that an author&amp;rsquo;s style does not bleed into a unifying presence.  In addition, a distributed ownership model for content needed to be (A) version controlled (B) auditable (C) completely non-technical.&lt;/p&gt;&#xA;&lt;p&gt;So I built it! The source code is &lt;a href=&#34;https://github.com/gbdubs/StudentUnion&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/in_line_edit_me.png&#34; alt=&#34;A photo of where users could edit the site&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;The end product is pretty sweet, and uses some smart optimizations to minimize hosting costs and page serving.  I took advantage of Github’s “pages” platform to serve the static HTML rendered by the site.  A change in one of the underlying sets of data would trigger a re-render of the HTML generated by the data, and then would be written out to Github pages.  This had two main benefits - Github automatically maintains version control history, which enabled auditing of who wrote what and when, and Github stores its HTML files in pages in a blazing fast CDN. This meant that lookups to the webpage were infinitely scalable and cheap (from my perspective), and meant that there were not “read” server costs.&lt;/p&gt;&#xA;&lt;p&gt;The server that processed writes was built on AppEngine, using JSTL templating over datastore objects to render the HTML to write to Github pages.  More exciting than that was the group strucuture that I made so that sub-groups of the Student Union could have access to different sets of permissions for editing. This formed the basis of Committee pages, and organization pages, which were only editible by their members.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/in_line_distributed.png&#34; alt=&#34;User Management controls&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Additionally, the data was reused between pages for common elements (for example, all committees should have the names and bios of their members, even if each member is in 10 committees).&lt;/p&gt;&#xA;&lt;p&gt;On the front end, I used a “Medium”-esque visual markdown editor to enable the construction of HTML elements from a given set of supported ones (which I provided a cohesive design language for on the rendering side).&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/in_line_editor.png&#34; alt=&#34;WISYWIG Editor&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;The result is &lt;a href=&#34;http://union.brandeis.edu&#34;&gt;gorgeous&lt;/a&gt;, and far more importantly, meets the needs of the Union. I left Brandeis two years ago (writing this from 2018), and it has been used effectively by three Student Unions since.  I do occasional performance upgrades and feature requests, but I&amp;rsquo;ve seen the site updated by several dozen Union Members without any technical knowledge.&lt;/p&gt;&#xA;&lt;p&gt;I’m quite proud of this project because it stands solidly at the intersection of technical simplicity and client needs. I have confidence that the Union will be using this product long after anyone remembers me at Brandeis.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Sniff</title>
      <link>https://grady.dev/projects/sniff/</link>
      <guid isPermaLink="true">https://grady.dev/projects/sniff/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>privacy</category>
      <category>writing</category>
      <category>government</category>
      <description>Why Florida v. Harris should be the minimum bar for surveillance</description>
      <content:encoded>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;: I wrote this essay many years ago. The evolution of technology over the early 2020s has changed my perspective on some of the ideas presented in this post.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;In &lt;em&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Florida_v._Harris#Decision&#34;&gt;Florida v. Harris&lt;/a&gt;&lt;/em&gt; (2012) a unanimous Supreme Court held that statistically derived evidence of efficacy of a drug sniffing dog was not a requirement for establishing probable cause for evaluating fourth amendment claims. I think this misses the mark from one of my favorite cases &lt;em&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/United_States_v._Place&#34;&gt;US v. Place&lt;/a&gt;&lt;/em&gt; (1983), in which O&amp;rsquo;Connor issued this gem of straightforward and balanced reasoning:&lt;/p&gt;&#xA;&lt;p&gt;&amp;ldquo;A &amp;ldquo;canine sniff&amp;rdquo; by a well-trained narcotics detection dog, however, does not require opening the luggage. It does not expose noncontraband items that would otherwise remain hidden from public view, as does, for example, an officer&amp;rsquo;s rummaging through the contents of the luggage. Thus, the manner in which information is obtained through this investigative technique is much less intrusive than a typical search. Moreover the sniff discloses only the presence or absense of narcotics, a contraband item. Thus, despite the fact that the sniff tells the authorities about the contents of the luggage, the information obtained is limited. &amp;hellip; We are aware of no other investigative procedure that is so limited both in the manner in which the information is obtained and in the content of the information revealed by the procedure.&amp;rdquo;&lt;/p&gt;&#xA;&lt;p&gt;I really like this passage both because it provides an aspirational goal for law-enforcement, and because it articulates a clear requirement: that the decision procedure used must be found to be accurate to be reasonable (a fact not contended at the Supreme Court, but critical to O&amp;rsquo;Connor&amp;rsquo;s reasoning.) It&amp;rsquo;s worthwhile extracting a few lessons from the court&amp;rsquo;s reasoning in considering the design of what makes a dog&amp;rsquo;s nose, in contrast to most digital technology, such a satisfying balance of rights and state interests.&lt;/p&gt;&#xA;&lt;p&gt;A key consideration that the court tangentially addresses in &lt;em&gt;Place&lt;/em&gt; is that of &lt;em&gt;statistically derived reliability&lt;/em&gt; as assessed through false-positive rate. There must be some threshold of false positive/negative at which a search becomes unjustified (or at which the decision procedure falls out of constructive use toward totality of the circumstances). This is easy to see in the case of a drug sniffing dog because we have no other means by which to reason about the dog&amp;rsquo;s judgement. Outcomes are all that we get to see for a dog, so the question of &amp;ldquo;well-trained&amp;rdquo; is a throwaway line, rather than a core holding.&lt;/p&gt;&#xA;&lt;p&gt;This ties into my thoughts on &lt;a href=&#34;https://grady.dev/projects/terry/&#34;&gt;Terry&lt;/a&gt;: a balancing act of competing harms in 4th amendment law can&amp;rsquo;t be effectively assessed by an individual case.&lt;/p&gt;&#xA;&lt;p&gt;Unfortunately we shed this common sense when answering the same questions about to human judgement. Judges are not blinded by the personhood and autonomy of the dog in evaluating it&amp;rsquo;s impact on competing rights claims. Dogs can&amp;rsquo;t perform post-hoc rationalization, a dog&amp;rsquo;s thought process cannot be interrogated by the law. There&amp;rsquo;s no sensible way of looking at probable cause (a question of prior knowledge) that relies solely on whether the dog is correct in their indication of drugs (knowledge derived after search).&lt;/p&gt;&#xA;&lt;p&gt;By talking about the dog&amp;rsquo;s perception in terms of accuracy, O&amp;rsquo;Conner implies that explanation is &lt;em&gt;not a necessary component of an acceptable test for a decision criterion that results in search or seizure&lt;/em&gt;. This is in stark contrast to the way that the court looks at officer discretion in Terry stops. In that case, because we can ask a human for an explanation, we put extensive weight on the explanation, without falling back or ever examining the far more compelling indication of rights-balancing - statistically derived accuracy.&lt;/p&gt;&#xA;&lt;p&gt;In &lt;em&gt;Harris&lt;/em&gt;, Kagan misses an argument about the dog that we should be making about any tool of law enforcement discernment (whether it is a drug sniffing dog, a thermal imager, or a cop&amp;rsquo;s judgement). All decision criteria used to inform choices of search and seizure should be held against a rights balancing framework that analyzes real world statistical performance. Human judgement is a force that is better inspected from the cold evidence of outcomes, rather than the squishy (and time-skewed) process of post-hoc rationalization.&lt;/p&gt;&#xA;&lt;p&gt;The second component that makes me love O&amp;rsquo;Connor and this decision is the concept of &lt;em&gt;targeted information isolation&lt;/em&gt;. A drug sniffing dog is processing information about a wide array of olfactory inputs, but only is expressing a verdict on a narrow set of targeted criteria. It&amp;rsquo;s likely that a dog can smell a wide array of contents in the baggage of passengers, but the only information it expresses is that of the query &lt;em&gt;does this bag contain drugs&lt;/em&gt;. This is supremely privacy preserving, because the only data that the system outputs (or even has the &lt;em&gt;capacity&lt;/em&gt; to output) is the question of interest, and the test is one the state has a compelling interest in. If dogs could talk, they could tell us a wide array of information about the contents of passerby&amp;rsquo;s suitcases. In that instance, the dog would serve as a broader means of surveillance than is proscribed by a legitimate law enforcement purpose. Good law enforcement tooling should fit this principle: limit the potential output of the system to the outcomes that are of explicit and compelling state interest.&lt;/p&gt;&#xA;&lt;p&gt;The third and final thought that &lt;em&gt;Place&lt;/em&gt; and &lt;em&gt;Harris&lt;/em&gt; bring up is the concept of interaction between tool and law. A consistent frustration for groups that try to combat stop-and-frisk policing is how officers adapt to court rulings about what constitutes articulable/reasonable suspcicion, and start to use that terminology in their reports. &amp;ldquo;The odor of Marijuana&amp;rdquo; is a powerful phrase. One additional (unarticulated) benefit of a drug dog (or more generally, a non-human system) is that it is more immune from this interaction pattern. Dogs will be biased by their training, but their individualized decisions are &amp;ldquo;individualized&amp;rdquo; in the words of &lt;em&gt;Terry&lt;/em&gt; in a way that human&amp;rsquo;s thought processes can never really be. An officer&amp;rsquo;s awareness of the law will always color both their decisions and how they describe their decisions. Man&amp;rsquo;s best friend does not suffer from either of these defects.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Shoe Rack 2</title>
      <link>https://grady.dev/projects/shoe_rack_2/</link>
      <guid isPermaLink="true">https://grady.dev/projects/shoe_rack_2/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>crafts</category>
      <category>gifts</category>
      <category>design</category>
      <description>A shoe rack made as a gift - that had to fit in a suitcase</description>
      <content:encoded>&lt;p&gt;After seeing the shoe rack I made for my partner, my sister asked for one for her apartment as a&#xA;Christmas gift. More precisely, I asked her what I could make her and she allowed me to make another&#xA;shoe rack.&lt;/p&gt;&#xA;&lt;p&gt;The major design constraint on this project was that the end result had to be transported from Colorado to Pennsylvania, which as I figured out by looking at shipping costs, would be fairly significant if the piece was fully assembled when shipped. I happened to have some old luggage lying around, and came up with the idea of designing the rack to collapse and fit inside of a suitcase.&lt;/p&gt;&#xA;&lt;p&gt;Unlike other projects I&amp;rsquo;ve worked on, this one was fun primarily because of how much went &lt;em&gt;wrong&lt;/em&gt;. I mismeasured/miscounted a half a dozen times. I got snowed in and couldn&amp;rsquo;t go out to get a drill press vice. I ultimately built something that was too dense to put shoes on (until I made some modifications). Despite all of these little hiccups, what I love about woodworking shone through - I was able to overcome most of the hurdles placed by my lack of foresight, and produce something that was still interesting, beautiful and functional.&lt;/p&gt;&#xA;&lt;p&gt;Finished photo first, obviously.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_0_.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_1.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_2.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_3.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_4.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_5.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_6.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_7.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_8.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_9.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_10.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_11.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_12.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_13.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_14.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_15.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_16.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_17.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_18.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_19.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2_20.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Shoe Rack</title>
      <link>https://grady.dev/projects/shoe_rack/</link>
      <guid isPermaLink="true">https://grady.dev/projects/shoe_rack/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>crafts</category>
      <category>gifts</category>
      <category>design</category>
      <description>A simple and fun shoe rack that fits exactly 3x4 pairs of shoes</description>
      <content:encoded>&lt;p&gt;My partner and I really both like building things, which makes anniversaries both an occasion for expression of caring through mutal gift giving, and a bit of a self-indulgent excuse to carve out time to make stuff. It only took him noting once that the width of our shoe rack was exactly 2.5 shoes for me to think through how I could build something better.&lt;/p&gt;&#xA;&lt;p&gt;Over weeks of sketches, a trip to IKEA, and a trip to John Houston&amp;rsquo;s Kennebunkport workshop (unrelated), I was inspired by the idea of sneaky intersections - of furniture that has non-standard joints and that provides standard functionality in non-standard ways.&lt;/p&gt;&#xA;&lt;p&gt;Planes are the foundation of furniture, but the way they are constructed is usually unimaginative. This idea was to try to construct planes through convoluted connections that rely on planning (rather than clear joints) to accomplish the surfaces on which the shoes would rest. This would be in contrast to the dominant feature of the rack - an elegant top portion of wood that would be both planar, simple and elevated above the constructed planes below.&lt;/p&gt;&#xA;&lt;p&gt;Finished photo first, obviously.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_0.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;I bought a bunch of pine because apparently it was purported easy to work with and cheap. After compleing this project I can affirm both of these characteristics.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_1.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;First step was cutting the pieces to length. Lots and lots of this.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_2.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Next was sanding. Each prisim has 6 planes and 12 edges that all needed sanding. This, in combo with 30 pieces of wood meant 540 sanding planes/lines&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_3.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;The oscillating sander takes a lot of the brunt of this project. My hands got a nice massage though! Went through three disks like this one.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_4.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Assembling the first set of three rungs of the rack.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_5.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;All three assembled rungs.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_6.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;It took me a while to figure out how to attach these to the top. This was probably where I spent like 1 day in the garage scribbling. This is the start of me prototyping what ended up being the solution.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_7.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Attached two vertical columns to the center most rung.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_8.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;I made a relatively grave miscalculation with the way the three rungs were going to attach (hint, screws in perpendicular directions to each other can&amp;rsquo;t work). Instead I decided to do the attachment at random staggers. Turned out to be a good idea, but I executed it in the wrong order and had to do FAR too much manual hand-turning of screws.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_9.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Two rungs attached! In this photo you can see what my partner made for me - some lovely shuffleboard boards! This was past the anniversary because I wasn&amp;rsquo;t able to finish mine in time (due to an unfortunate concussion.)&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_10.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Attachers on the middle rung.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_11.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Rungs fully attached&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_12.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Initial attachment of the top (using hand screws and some pre drilled holes) looked like it was going well&amp;hellip;&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_13.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_14.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;What these photos miss, however, is how incredibly off center the result was! Solidly 5 degrees off of alignment.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_15.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_16.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Time to undo some skrews, and try again&amp;hellip;&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_17.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;The prestain made the wood look GOREGOUS particularly on the top. Very happy.&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_18.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;The stain turned this pine into a really gorgeous shade of maple. This is unfortunatley the only photo I have of it!&#xA;&lt;img src=&#34;https://grady.dev/img/shoe_rack_19.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;Finished product!&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_20.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_21.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/shoe_rack_22.jpg&#34; alt=&#34;Shoe Rack Photo&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;It nicely fits our shoes, though certainly not all of them (as we are shoe folk). My partner was quite happy with it, and I am too, despite its slight wobbles!&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Senior Thesis</title>
      <link>https://grady.dev/projects/senior_thesis/</link>
      <guid isPermaLink="true">https://grady.dev/projects/senior_thesis/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>algorithms</category>
      <category>education</category>
      <category>tools</category>
      <description>Senior thesis on the graph isomorphism (GI) problem</description>
      <content:encoded>&lt;p&gt;I wrote my undergraduate thesis on the &lt;a href=&#34;http://mathworld.wolfram.com/IsomorphicGraphs.html&#34;&gt;Graph Isomorphism&lt;/a&gt; (GI) problem, and several topics within that space. My work was &lt;a href=&#34;https://github.com/gbdubs/thesis&#34;&gt;version controlled on github&lt;/a&gt;, and the final result is &lt;a href=&#34;https://github.com/gbdubs/thesis/blob/master/Documentation%20%2B%20Reports/THESIS/thesis.pdf&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I was first interested in the “Paths” invariant, which is incredibly powerful test for discerning between potentially isomorphic graphs in cubic (and fully paralellizable) time, and was originally theorized to be a solution to GI. The primary findings of my thesis were that:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;[Computational Wrangling] Unlike was theorized, copaths graphs do exist, and finding them is easily done brute force calculations on today&amp;rsquo;s standard GPUs.&lt;/li&gt;&#xA;&lt;li&gt;[Theoretical Proof] Paths uniquely determines the chromatic polynomial of a graph.&lt;/li&gt;&#xA;&lt;li&gt;[Analytical Algorithms] Measuring discriminatory power to value ratio of invariants within graph isomorphism is possible and can help us devise better algorithms for practical isomorphism detection, and the paths invariant is well weighted in an analysis of discriminatory power.&lt;/li&gt;&#xA;&lt;li&gt;[Theoretical Proof] Paths as an invariant does not need to be calculated past N vertices.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Since I answered most questions I was interested in  paths stuff earlier than expected, I started working on Random Graph theory and found that:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;[Literature Review] Random Graph generators almost all are random matrix generators. This understates the frequency of highly auto-isomorphic graphs by one-to-factorial odds.&lt;/li&gt;&#xA;&lt;li&gt;[Coding] We can create a better random graph generator to evaluate random graph algorithms.&lt;/li&gt;&#xA;&lt;li&gt;[Analytical Proof] Many algorithms are evaluated across &amp;ldquo;matrix random&amp;rdquo; graphs, and their amortized running time can be exponentially higher when using a true random graph generator.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I defended this thesis was successfully defended in May of 2016, and recieved highest honors in Computer Science.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Personal Website V3</title>
      <link>https://grady.dev/projects/website_v3/</link>
      <guid isPermaLink="true">https://grady.dev/projects/website_v3/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>websites</category>
      <category>design</category>
      <description>The site you find yourself on right now</description>
      <content:encoded>&lt;p&gt;When I tried to update my website in December of 2017, I couldn&amp;rsquo;t find the files anywhere on my laptop or github. This was a surprise, but one that I took as an opportunity to recreate the site from scratch, using best practices from the start, and making some design changes. Luckily I later found these files, and posted them as V2 on this page.&lt;/p&gt;&#xA;&lt;p&gt;The result was a nice site with a detailed portfolio section, some nice hugo-templated HTML, and the cute animations (which are NOT generated via draw-me-css). In this version of the site, I attempted to focus on how I could go beyond the original circut-board design of V2.&lt;/p&gt;&#xA;&lt;p&gt;It has since been replaced by V4 (Sunrise), but you can still see the V3 version &lt;a href=&#34;https://grady.dev/destijl/&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The result is a playful mix of formats that tries to stand out by being simple in design and complex in implementation.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Personal Website V2</title>
      <link>https://grady.dev/projects/website_v2/</link>
      <guid isPermaLink="true">https://grady.dev/projects/website_v2/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>websites</category>
      <category>design</category>
      <category>art</category>
      <description>The deprecated version of my personal portfolio</description>
      <content:encoded>&lt;p&gt;I took an architecture class in my Senior Year at Brandeis that awoke an aesthetic sense I had not previously identified or listened to. In particular, the de-stijl primitive of intersecting planes struck a resonant chord in my sense of beauty.&lt;/p&gt;&#xA;&lt;p&gt;That new asthetic, in combination with “draw me CSS” was the inspiration for V2 of my website - meant to resemble something in between a circut board, the maurader’s map, and the de-stijl classic “Composition in black, red, yellow and blue”.&lt;/p&gt;&#xA;&lt;p&gt;Notable: the code that generates the site went through a series of refactors to try to make it more consistent across browsers and screen sizes. Underlying these problems was the fact that draw-me-css is too generalizable to be able to produce elegant code.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Personal Website V1</title>
      <link>https://grady.dev/projects/website_v1/</link>
      <guid isPermaLink="true">https://grady.dev/projects/website_v1/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>websites</category>
      <category>design</category>
      <description>The very deprecated version of my personal portfolio</description>
      <content:encoded>&lt;p&gt;In my original website, I wanted to play with the fundamental assumption of what a webpage renders as - a series of nested boxes.  The idea of an expanding button that becomes the page fascinated me, particularly since the new page had buttons for the old one (I was reading all about golden-braids in GEB at the time).&lt;/p&gt;&#xA;&lt;p&gt;This isn’t great work, but it reflects where I was at at the time - having fun, experimenting, and learning Javascript.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Parley</title>
      <link>https://grady.dev/projects/parley/</link>
      <guid isPermaLink="true">https://grady.dev/projects/parley/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>websites</category>
      <category>design</category>
      <category>online spaces</category>
      <description>Recursive annotations as a counter-proposal to the comment thread</description>
      <content:encoded>&lt;p&gt;Comment threads are an inherently flawed way to have a discussion, because they are strictly linear.  In recent years, large organizations like facebook have realized this and have tried to reconcile it with a binary tree pattern of &lt;em&gt;deeper&lt;/em&gt; or &lt;em&gt;next&lt;/em&gt;. This only partially solves the problem. Far more frequently, if I want to respond to a comment, there are multiple pieces of it that I want to respond to, and some may already be addressed further down the thread.  The heart of the matter is that a meaningful static discussion is not best facilitated by a linear progression of strings.&lt;/p&gt;&#xA;&lt;p&gt;Parley was my idea on how to change this. It views a document as something which is not responed to in whole, but which can be annotated with comments by different authors.  The comments (in turn) become top level objects which are just as open to annotation and further comment. The recursive, n-ary tree nature of this structure has multiple advantages, but the big one is that you can dive deep on a given line of argument naturally, by clicking through and understanding the points as made in isolation.&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://grady.dev/img/parly.png&#34; alt=&#34;A Photo of the parley interface.&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;This idea in and of itself is not revolutionary, but I wanted to see if I could make a demo where this is implemented in a way that is comprehensible and intuitive.  I half succeeded here.  The parley interface used the Draw Me CSS pattern to create a right-left layout where the content is displayed with underlines corresponding to annotations, and the text of the annotation is displayed in a scrolling left hand column.  The interface is flexible, relatively intuitive, and fairly simple.&lt;/p&gt;&#xA;&lt;p&gt;Where I ran into problems was in the minutia &amp;ndash; what about really long annotations? What about annotations stacked 15 high? How do you link effectively (as links cannot then be annotated)?&lt;/p&gt;&#xA;&lt;p&gt;The backend is lame (an app engine hack), but I stand behind the fundamental idea (recursive comment sections, rather than linear ones), and I stand behind the UI for what it is - a proof of concept.&lt;/p&gt;&#xA;&lt;p&gt;To use the system, go to &lt;a href=&#34;http://parly.us&#34;&gt;parly.us&lt;/a&gt;, and be aware that the AppEngine backend takes up to a minute to spin up - so allow a minute to pass after a first page access, then reload the page to interact with the software.&lt;/p&gt;&#xA;</content:encoded>
    </item><item>
      <title>Narratives</title>
      <link>https://grady.dev/projects/narratives/</link>
      <guid isPermaLink="true">https://grady.dev/projects/narratives/</guid>
      <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
      <dc:creator>Grady Berry Ward</dc:creator>
      <category>privacy</category>
      <category>writing</category>
      <category>essay</category>
      <description>Thoughts on how privacy and identity are related.</description>
      <content:encoded>&lt;p&gt;I&amp;rsquo;ve started thinking about how to define privacy. Though I haven&amp;rsquo;t made any traction on that overall question, it&amp;rsquo;s helped me better understand the relationship between privacy and how we manufacture our identity.&lt;/p&gt;&#xA;&lt;p&gt;To avoid exclusively speaking in intellectualisms, I&amp;rsquo;ll describe the circumstances of my morning, which can illustrate the point I&amp;rsquo;m trying to make.&lt;/p&gt;&#xA;&lt;p&gt;I went out to get coffee. I usually make coffee at home, but my french press shattered, so  I ordered a new one and it was slated for delivery a few days ago. However, Amazon informed me that it was damaged in transit, and directed me to purchase a replacement if I still wanted it. I made that purchase, but the replacement wasn&amp;rsquo;t slated to arrive until tomorrow. Thus, to get my daily coffee, I walked myself and my dog to the closest McDonalds (a business I rarely frequent) to get a $1 medium coffee.&lt;/p&gt;&#xA;&lt;p&gt;On the way back, a bee started attacking my dog (for an unknown reason) without his knowledge: it was furiously trying to burrow under his fur to get at his skin. I couldn&amp;rsquo;t have that, so I set down the coffee on the sidewalk and swatted it away using my McDonalds receipt. The bee then directed it&amp;rsquo;s animus toward me, and I spent the remainder of the walk intermittently jogging, swearing and stopping to swat the bee off of myself or my dog, until we were safely back in the confines of my apartment, a pane of glass now between us and the angry insect. I sipped my medium coffee in triumph, my dog and I unscathed.&lt;/p&gt;&#xA;&lt;p&gt;Any subset of the facts above, taken without narrative or broader context could paint a picture that doesn&amp;rsquo;t fit with the narrative that I&amp;rsquo;ve just laid out.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A stranger who only observed me swatting at my dog&amp;rsquo;s fur could have mistaken my concern for abuse.&lt;/li&gt;&#xA;&lt;li&gt;A passing policeman who saw me flustered, erratically waving my arms about, swearing, and unpredictably sprinting may have interpreted these as signs of a mental crisis.&lt;/li&gt;&#xA;&lt;li&gt;McDonalds may have interpreted my  transaction as a sign of a newfound customer.&lt;/li&gt;&#xA;&lt;li&gt;Visa may have interpreted my purchase of two french presses in a week and a coffee at McDonalds as interest in further coffee goods and services.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;The construction of each of those narratives could be supported by the same facts I used to create my own anecdote, but none are true. This is why privacy is related to narrative building.&lt;/p&gt;&#xA;&lt;p&gt;The activity that we engage in at each moment in our lives is a piece of information. These data are collected (both in our memories and by external observers) and used to construct narratives that form cohesive stories: what happened, what we want, and who we are. We construct our understanding and model of our&amp;quot;selves&amp;quot; by distilling the facts of our lives into a narrative that that forms our identity and the self that we project to others.&lt;/p&gt;&#xA;&lt;p&gt;The creation of data that occurs as you move through the world makes it easy for others to construct their own counter-narratives of your life. The more data that others have about your actions, the more convincing they can be in painting a picture of who you are. Even an external observer with perfect information about you might describe you differently than you would, either through the omission of information in their depiction, or by including information about you that that you omit from your own.&lt;/p&gt;&#xA;&lt;p&gt;Full information of this morning&amp;rsquo;s events could either paint me as a environmentally concerned animal lover, or a prodigal waster. I use a french press because it avoids the marginal waste of filters. However, I also did appear to purchase two french presses (wasteful), and my purchase of a McDonalds coffee demonstrates a willingness to use disposable cups. Perfect information paints a muddled profile, even though I would consider myself a staunch environmentalist.&lt;/p&gt;&#xA;&lt;p&gt;As this illustrates, there is a deep freedom in having control over your personal narrative, choosing the facts you consider to be illustrative of the person that you are. When you have the power and capacity to influence how others interpret and construe the data points that describe your existence, you have self ownership even in the external representations of you in the minds and systems of others.&lt;/p&gt;&#xA;&lt;p&gt;This is one reason privacy matters.&lt;/p&gt;&#xA;&lt;p&gt;Retailers collect information about your actions in order to construct a &amp;ldquo;consumer profile&amp;rdquo;, a dataset describing who you are as a consumer, what and when you like buy goods, how much cash and debt you hold, etc. Strangers use the information they can immediately glean about you from your external presentation to create a model of what they should expect from you, and how they should react to you. Law enforcement uses data about your criminal history, your zip code, your demography and your public actions to evaluate your likelihood of rule-breaking. Juries are fundamentally trying to decide which narrative best fits the facts presented in a trial. In each of these cases, data about your existence is used to construct a narrative over which you have no direct control. Certainly, you may be able to influence these portraits by deliberately changing your zip code, your purchasing habits or your external presentation, but doing so does not reclaim the authority over your reduction (your characterization in the mind of the officer, the stranger, or the database).&lt;/p&gt;&#xA;&lt;p&gt;In reality, our actions are not wholly consistent with any single narrative. Narratives are less information dense than the facts that go into producing them. The construction of a narrative is inherently a lossy compression - it distills aggregated data into a imperfect (though useful) abstraction. I&amp;rsquo;m certainly not arguing that all such constructions are bad, nor that each should be  within the full control of the person being described. But it seems important to identify that the more information about an individual in the minds, databases and metrics of others, the less power they hold over their identity, and in a way, their personhood.&lt;/p&gt;&#xA;</content:encoded>
    </item>
  </channel>
</rss>
