<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Josh Lane — Writing</title><link>https://lanej.io/</link><description>Writing by Josh Lane on software, systems, and technology leadership.</description><language>en-us</language><atom:link href="https://lanej.io/index.xml" rel="self" type="application/rss+xml"/><item><title>How You Do It Is Part of the Decision</title><link>https://lanej.io/writing/how-you-do-it-is-part-of-the-decision/</link><guid isPermaLink="true">https://lanej.io/writing/how-you-do-it-is-part-of-the-decision/</guid><pubDate>Fri, 11 Sep 2026 00:00:00 +0000</pubDate><description>Hard decisions reveal our character and shape the trust we will need for the next one.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;The necessity of an outcome does not justify every method used to reach it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Leadership sometimes requires decisions that leave people worse off. Avoiding those decisions can be a failure of responsibility. But so can treating their necessity as permission to stop examining our choices.&lt;/p&gt;
&lt;p&gt;Establishing that something must change answers only part of the question. We still have to justify the approach, account for the people who bear its costs, and take responsibility for what follows. Those are not matters to settle after the decision. They are part of what we are deciding.&lt;/p&gt;
&lt;p&gt;That is where our standards become more than statements of intent. Integrity has to govern choices that are costly and contested, not only choices that are easy to defend. The goal is not to avoid hard decisions. It is to remain accountable for the whole decision.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="you-do-not-get-to-delegate-the-weight"&gt;You do not get to delegate the weight&lt;/h2&gt;
&lt;p&gt;The person who passes judgment should swing the sword.&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The authority to impose a consequence comes with a responsibility to answer for it. That responsibility does not depend on who delivers the news.&lt;/p&gt;
&lt;p&gt;You can ask someone to coordinate a transition. You can rely on people with the right expertise to carry it out. But you still owe the people affected an explanation you are willing to give yourself. You still have to own the consequences, including the ones that make your decision harder to defend.&lt;/p&gt;
&lt;p&gt;A leader can attend every conversation and still evade responsibility. Another can appropriately delegate those conversations while setting the standard, providing resources, and correcting failures. The test is whether we remain answerable for what happens.&lt;/p&gt;
&lt;p&gt;“I made the decision; someone else can deal with the people” is not a complete account of leadership. Distance can remove precisely the information that should inform our judgment: what the plan actually asks of someone, and where it leaves them.&lt;/p&gt;
&lt;p&gt;The minute you start delegating away the hard part—not because someone else is better equipped to do the work, but because you do not want to face it—you start dying as a leader.&lt;/p&gt;
&lt;figure class="sc-figure" data-essay-diagram="decision-responsibility" aria-labelledby="decision-responsibility-0-title decision-responsibility-0-caption"&gt;
&lt;p class="sc-figure-title" id="decision-responsibility-0-title"&gt;Delegate the work, not the weight&lt;/p&gt;
&lt;div class="decision-track"&gt;
&lt;ol class="decision-stages"&gt;
&lt;li&gt;&lt;svg class="decision-stage-icon" viewBox="0 0 32 32" aria-hidden="true" focusable="false"&gt;&lt;rect x="5" y="3" width="22" height="26" rx="2"/&gt;&lt;path d="m9 10 2 2 3-4m3 3h6m-14 8 2 2 3-4m3 3h6"/&gt;&lt;/svg&gt;&lt;strong class="sc-node-label"&gt;Decide&lt;/strong&gt;&lt;span class="sc-node-detail"&gt;Make the call.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;svg class="decision-stage-icon" viewBox="0 0 32 32" aria-hidden="true" focusable="false"&gt;&lt;path d="M3 4h19v15H11l-6 5v-5H3Zm19 8h7v15h-5l-5 3v-3h-5v-8"/&gt;&lt;/svg&gt;&lt;strong class="sc-node-label"&gt;Explain&lt;/strong&gt;&lt;span class="sc-node-detail"&gt;Face the consequences.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;svg class="decision-stage-icon" viewBox="0 0 32 32" aria-hidden="true" focusable="false"&gt;&lt;path d="m13 3 6 0 1 4 4 2 4-1 3 5-3 3v4l2 3-3 5-4-1-4 2-1 2h-6l-1-4-4-2-4 1-3-5 3-3v-4l-2-3 3-5 4 1 4-2Z" transform="translate(1 0) scale(.92)"/&gt;&lt;circle cx="16" cy="16" r="5"/&gt;&lt;/svg&gt;&lt;strong class="sc-node-label"&gt;Carry out&lt;/strong&gt;&lt;span class="sc-node-detail"&gt;Delegate the work.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;svg class="decision-stage-icon" viewBox="0 0 32 32" aria-hidden="true" focusable="false"&gt;&lt;circle cx="16" cy="8" r="4"/&gt;&lt;path d="M8 29v-6a8 8 0 0 1 16 0v6ZM5 11a3 3 0 1 0 0 6m22-6a3 3 0 1 1 0 6M5 20a5 5 0 0 0-4 5v4h4m22-9a5 5 0 0 1 4 5v4h-4"/&gt;&lt;/svg&gt;&lt;strong class="sc-node-label"&gt;Follow through&lt;/strong&gt;&lt;span class="sc-node-detail"&gt;Remain accountable.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="responsibility-rail"&gt;&lt;span&gt;Responsibility&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;figcaption class="sc-caption" id="decision-responsibility-0-caption"&gt;The work can change hands. Responsibility for the decision does not.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="be-precise-about-what-was-necessary"&gt;Be precise about what was necessary&lt;/h2&gt;
&lt;p&gt;“We had no choice” deserves a more specific question: no choice about what?&lt;/p&gt;
&lt;p&gt;Ending an investment? Acting before a deadline? Giving people little information? Leaving them to work out the consequences themselves?&lt;/p&gt;
&lt;p&gt;A necessary objective is not the same as a necessary intervention. Needing to reduce costs does not establish that a particular staffing reduction is the right plan. We still have to compare it with other ways of meeting the need.&lt;/p&gt;
&lt;p&gt;Consider a project that no longer warrants its investment. Continuing would consume resources needed elsewhere. Stopping it may be the right call.&lt;/p&gt;
&lt;p&gt;That does not tell us when to inform the team, how to represent their work, or how to handle commitments made to customers. It does not tell us what support people need to move to their next responsibilities. Those choices face their own constraints and need their own justification.&lt;/p&gt;
&lt;p&gt;The standard cannot be that nobody is upset. Someone may understand a decision and still strongly oppose it. Their disappointment does not establish that the decision was wrong; their acceptance does not establish that it was handled well.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Crucial Conversations&lt;/em&gt; calls the supposed choice between honesty and respect a “Fool’s Choice.”&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; We can be clear about what has been decided without dismissing what it costs the person hearing it. A gentle but evasive answer can leave someone unable to plan.&lt;/p&gt;
&lt;p&gt;Support costs money. A transition takes time. Some information cannot yet be shared. We should weigh those constraints before approving the change, with a dependable standard for how people will be treated.&lt;/p&gt;
&lt;p&gt;Avoidable harm is not always unjustified harm. One consequence may be avoidable only by imposing a greater cost elsewhere. The obligation is to examine the alternatives, make defensible tradeoffs, and own their costs. Calling the overall decision necessary does not make every choice about its execution inevitable.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="composure-is-not-indifference"&gt;Composure is not indifference&lt;/h2&gt;
&lt;p&gt;Experience should make us better at carrying the responsibility, not more willing to disregard it. You may become less anxious before a difficult conversation, more precise in your explanation, and better able to listen without becoming defensive. You may stop confusing your discomfort with evidence that the decision is wrong.&lt;/p&gt;
&lt;p&gt;Personal distress is not evidence that we acted well. A composed leader can take another person&amp;rsquo;s loss seriously; an anguished one can still treat them carelessly. Someone else&amp;rsquo;s loss should carry moral weight without making the event about our own feelings.&lt;/p&gt;
&lt;p&gt;In &lt;em&gt;Meditations&lt;/em&gt; 5.20, Marcus Aurelius describes turning an impediment into material for action. In 6.30, he puts kindness alongside disciplined action.&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt; I take those ideas together: the difficult conversation is part of the work of leadership. Here, the obstacle to overcome is our temptation to avoid responsibility, not the person affected by our decision.&lt;/p&gt;
&lt;p&gt;That gives us something to practice: explaining the reasoning, hearing an angry response without retaliating, and correcting a consequence we could reasonably have prevented. Composure helps us do that work. Indifference gives us permission to skip it.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="character-is-in-the-choices"&gt;Character is in the choices&lt;/h2&gt;
&lt;p&gt;Character shows in what we choose when we have room to choose differently.&lt;/p&gt;
&lt;p&gt;It is relatively easy to speak well of people while their work serves our needs. The more demanding test comes when our interests diverge. Their contribution does not disappear because their project, role, or agreement no longer fits our plans. People should not have to remain useful to us to be treated with care.&lt;/p&gt;
&lt;p&gt;Epictetus argues in &lt;em&gt;Discourses&lt;/em&gt; 2.18 that our actions strengthen the corresponding habits.&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt; Each decision is practice for the next one. Facing consequences and arranging not to face them are both things we can become practiced at. Experience alone does not tell us which we are learning.&lt;/p&gt;
&lt;p&gt;The pattern matters as much as the individual call. If urgency repeatedly becomes our reason to break a commitment or refuse to hear the consequences, we should question what we are practicing. Expedience cannot become a standing permission to abandon our standards.&lt;/p&gt;
&lt;p&gt;Those choices become evidence for other people, too. Do we keep an inconvenient commitment? Acknowledge an error? Apply a standard consistently when the circumstances are comparable? People see whether our account of ourselves survives contact with a difficult situation.&lt;/p&gt;
&lt;p&gt;A colleague can dislike my decision and still have reason to trust my conduct. Earning that trust requires more than being agreeable. It requires judgment they can rely on and commitments that hold under pressure.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="resolve-is-not-hostility"&gt;Resolve is not hostility&lt;/h2&gt;
&lt;p&gt;A leader can end an argument by making disagreement unpleasant. That does not establish that the decision improved. Even when aggression secures a concession, the concession does not account for what happened to cooperation or the information available next time.&lt;/p&gt;
&lt;p&gt;James Detert and Ethan Burris found that managerial openness was associated with employees speaking up with suggestions for improvement, with perceived safety helping explain the relationship.&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt; My concern is the reverse incentive: when bringing a problem means inviting a confrontation, silence can become the easier choice. A meeting with fewer objections may contain less information.&lt;/p&gt;
&lt;p&gt;In three experiments, Christine Porath and Amir Erez found that rudeness reduced task performance and helpfulness.&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt; Contempt can carry an immediate cost to the work. I want the person who sees a flaw in the plan to bring it forward while we still have time to act.&lt;/p&gt;
&lt;p&gt;We can set demanding targets, negotiate firmly, stop failed investments, and terminate employment when the reasons warrant it. Listening does not give someone a veto; correcting an error does not mean abandoning the goal. The work still has to meet the requirement.&lt;/p&gt;
&lt;p&gt;A successful outcome does not establish that aggression caused it, let alone that aggression was necessary. We have to ask what a different approach might have achieved and what information or cooperation we sacrificed along the way.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="play-the-long-game"&gt;Play the long game&lt;/h2&gt;
&lt;p&gt;A business needs capable people who will choose to join, stay, and do difficult work together. Losing people can disrupt execution; attracting replacements depends on more than having a vacancy. Turnover and recruiting research give us reason to include the people needed for continued execution in the business case for change.&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Enjoying our colleagues matters, but trust asks more than whether we like them. The distinction between ability, benevolence, and integrity is useful here: can you do the work, do you care about my interests, and do you follow principles I can accept?&lt;sup id="fnref:8"&gt;&lt;a href="#fn:8" class="footnote-ref" role="doc-noteref"&gt;8&lt;/a&gt;&lt;/sup&gt; A demanding colleague can earn that confidence while making decisions I dislike.&lt;/p&gt;
&lt;p&gt;Research associates trust in leadership with commitment, job performance, and lower intention to quit.&lt;sup id="fnref:9"&gt;&lt;a href="#fn:9" class="footnote-ref" role="doc-noteref"&gt;9&lt;/a&gt;&lt;/sup&gt; Pay, workload, growth, and the work itself still matter. Trust belongs among the conditions that make staying worthwhile; it cannot stand in for all of them.&lt;/p&gt;
&lt;p&gt;A layoff makes this concrete. Research on layoff survivors found worse reactions among remaining employees who identified with departing colleagues and perceived the departing employees&amp;rsquo; compensation as inadequate.&lt;sup id="fnref:10"&gt;&lt;a href="#fn:10" class="footnote-ref" role="doc-noteref"&gt;10&lt;/a&gt;&lt;/sup&gt; Removing an expense leaves a team that still has to believe it can work effectively together.&lt;/p&gt;
&lt;p&gt;Adam Grant&amp;rsquo;s &lt;em&gt;Give and Take&lt;/em&gt; describes how generosity can build trust and reputation, and how givers can burn out or be exploited without boundaries.&lt;sup id="fnref:11"&gt;&lt;a href="#fn:11" class="footnote-ref" role="doc-noteref"&gt;11&lt;/a&gt;&lt;/sup&gt; The longer horizon includes both what others learn from our conduct and what we practice through our choices. That is the practical sense in which I think about karma: we carry those relationships and habits into the next decision.&lt;/p&gt;
&lt;p&gt;Decency deserves no less consideration when its return is uncertain. Integrity cannot guarantee commercial success. It can help preserve conditions the business needs to succeed, while meeting obligations that matter in their own right.&lt;/p&gt;
&lt;figure class="sc-figure" data-essay-diagram="decision-carry-forward" aria-labelledby="decision-carry-forward-1-title decision-carry-forward-1-caption"&gt;
&lt;p class="sc-figure-title" id="decision-carry-forward-1-title"&gt;What carries forward&lt;/p&gt;
&lt;div class="carry-forward"&gt;
&lt;div class="sc-node carry-endpoint"&gt;A decision&lt;/div&gt;
&lt;div class="sc-flow-connector" aria-hidden="true"&gt;&lt;/div&gt;
&lt;div class="carry-paths" role="group" aria-label="Two parallel consequences of the same decision"&gt;
&lt;div class="carry-path"&gt;&lt;span class="carry-direction"&gt;Outward&lt;/span&gt;&lt;strong class="sc-node-label"&gt;Relationships&lt;/strong&gt;&lt;p&gt;What others learn from our conduct&lt;/p&gt;&lt;p class="carry-result"&gt;The trust they bring next time&lt;/p&gt;&lt;/div&gt;
&lt;div class="carry-path"&gt;&lt;span class="carry-direction"&gt;Inward&lt;/span&gt;&lt;strong class="sc-node-label"&gt;Character&lt;/strong&gt;&lt;p&gt;What we practice through our choices&lt;/p&gt;&lt;p class="carry-result"&gt;The habits we bring next time&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sc-flow-connector" aria-hidden="true"&gt;&lt;/div&gt;
&lt;div class="sc-node carry-endpoint"&gt;The next decision&lt;/div&gt;
&lt;/div&gt;
&lt;figcaption class="sc-caption" id="decision-carry-forward-1-caption"&gt;We carry forward both the trust we leave with others and the habits we build in ourselves.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="finish-the-decision"&gt;Finish the decision&lt;/h2&gt;
&lt;p&gt;Before approving a consequential change, we should be able to explain why this approach is justified, who bears its costs, and which alternatives we considered. That includes choices about timing, communication, and support. Where a responsible approach costs more or takes longer, that belongs in the proposal.&lt;/p&gt;
&lt;p&gt;When a proposal only works because we have left out the costs of carrying it out responsibly, the proposal is not finished.&lt;/p&gt;
&lt;p&gt;For a reduction in staff, I would want a plan for the business that remains: what work stops, which commitments continue, and who has the capacity to meet them. The plan should specify how people will be told and what transition support is reasonably possible. Someone needs the authority and resources to carry that work through.&lt;/p&gt;
&lt;p&gt;Then judge the result beyond the announcement. Did the savings materialize after transition costs? Can the remaining team meet its commitments? Are important risks still raised early? Are we losing effective people the plan depended on retaining? Retaining everyone is not the objective; sustaining the capabilities the business needs is.&lt;/p&gt;
&lt;p&gt;We must remain available to hear consequences we failed to anticipate and correct what we can. An explanation that was defensible at approval does not relieve us of responsibility for how the plan works in practice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How you do it is part of the decision. Being willing to face what you decided is part of the job.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.penguinrandomhouse.com/books/108336/a-game-of-thrones-by-george-r-r-martin/"&gt;A Game of Thrones&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
George R. R. Martin · 1996, Bran&amp;rsquo;s first chapter&lt;/p&gt;
&lt;p&gt;The sentence adapts Ned Stark&amp;rsquo;s maxim about passing sentence and swinging the sword. Its application here concerns accountability, not literal punishment. The opening image evokes a different story: in Cicero&amp;rsquo;s &lt;a href="https://www.attalus.org/cicero/tusc5A.html#61"&gt;Tusculan Disputations, Book Five, §§61–62&lt;/a&gt;, the suspended sword reveals the peril accompanying power. Neither metaphor establishes the essay&amp;rsquo;s business claims.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.mheducation.com/highered/mhp/product/crucial-conversations-3e.html"&gt;Crucial Conversations: Tools for Talking When Stakes Are High&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Joseph Grenny, Kerry Patterson, Ron McMillan, Al Switzler, and Emily Gregory · Third edition, 2021&lt;/p&gt;
&lt;p&gt;The “Fool’s Choice” rejects treating honesty and respect as incompatible; see also &lt;a href="https://cruciallearning.com/glossary/"&gt;Crucial Learning’s glossary&lt;/a&gt;. This supports the distinction between candor and disrespect, not a guarantee that painful decisions can leave relationships unchanged. Applying it to the responsibilities around a decision is the argument made here.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://classics.mit.edu/Antoninus/meditations.5.five.html"&gt;Meditations, Book Five, §20&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Marcus Aurelius · Translated by George Long&lt;/p&gt;
&lt;p&gt;In 5.20, an impediment to action can become material for an appropriate response. &lt;a href="https://classics.mit.edu/Antoninus/meditations.6.six.html"&gt;Book Six, §30&lt;/a&gt; places kindness and social duty alongside disciplined action. The application to difficult leadership conversations is mine, not a claim that Marcus wrote about modern employment decisions or promised commercial success.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://en.wikisource.org/wiki/The_Discourses_of_Epictetus;_with_the_Encheiridion_and_Fragments/Book_2/Chapter_18"&gt;Discourses, Book Two, Chapter 18&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Epictetus · Translated by George Long&lt;/p&gt;
&lt;p&gt;Actions maintain and strengthen their corresponding habits; Epictetus specifically warns that repeatedly acting in anger reinforces anger. This is the philosophical basis for the character-formation argument, not empirical evidence of a financial return or a doctrine of guaranteed reward and punishment.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://doi.org/10.5465/amj.2007.26279183"&gt;Leadership Behavior and Employee Voice: Is the Door Really Open?&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
James R. Detert and Ethan R. Burris · 2007&lt;/p&gt;
&lt;p&gt;A two-phase field study in a restaurant chain linked managerial openness with improvement-oriented employee voice, with perceived psychological safety mediating the relationship. This is evidence about speaking up, not a randomized test of leadership styles or a direct estimate of company profits. The author&amp;rsquo;s &lt;a href="https://www.researchgate.net/publication/255576931_Leadership_Behavior_and_Employee_Voice_Is_The_Door_Really_Open"&gt;full-text copy&lt;/a&gt; is also available.&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://doi.org/10.5465/amj.2007.20159919"&gt;Does Rudeness Really Matter? The Effects of Rudeness on Task Performance and Helpfulness&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Christine L. Porath and Amir Erez · 2007&lt;/p&gt;
&lt;p&gt;Three experiments found reduced routine and creative task performance and reduced helpfulness under rude treatment. The findings concern rudeness in experimental settings, not firm standards, lawful terminations, or a quantified effect on long-term business performance.&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://research.polyu.edu.hk/en/publications/turnover-rates-and-organizational-performance-a-meta-analysis/"&gt;Turnover Rates and Organizational Performance: A Meta-Analysis&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Tae Youn Park and Jason D. Shaw · 2013&lt;/p&gt;
&lt;p&gt;Turnover rates were negatively associated with organizational performance on average, with differences by turnover type and context. This does not establish that every departure harms performance or that necessary terminations should be avoided.&lt;/p&gt;
&lt;p&gt;Derek S. Chapman and colleagues&amp;rsquo; &lt;a href="https://pubmed.ncbi.nlm.nih.gov/16162065/"&gt;Applicant Attraction to Organizations and Job Choice&lt;/a&gt; (2005) synthesizes 71 studies. Recruiting outcomes were associated with job and organizational characteristics, recruiter behavior, process perceptions, and perceived fit. Connecting these findings to how consequential decisions are implemented is the essay&amp;rsquo;s inference, not a measured effect of a particular layoff on hiring.&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:8"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://doi.org/10.5465/amr.1995.9508080335"&gt;An Integrative Model of Organizational Trust&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Roger C. Mayer, James H. Davis, and F. David Schoorman · 1995&lt;/p&gt;
&lt;p&gt;This conceptual model distinguishes perceived ability, benevolence, and integrity as contributors to trustworthiness. Trust involves willingness to accept vulnerability; it is distinct from liking, cooperation, or a guaranteed outcome.&amp;#160;&lt;a href="#fnref:8" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:9"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://ink.library.smu.edu.sg/lkcsb_research/675/"&gt;Trust in Leadership: Meta-Analytic Findings and Implications for Research and Practice&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Kurt T. Dirks and Donald L. Ferrin · 2002&lt;/p&gt;
&lt;p&gt;The meta-analysis draws on 106 samples. It reports associations with outcomes including commitment, job performance, and intention to quit. Intentions are not actual departures, and the findings do not establish that integrity causes retention or financial success through the entire chain proposed here.&amp;#160;&lt;a href="#fnref:9" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:10"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://researchers.mq.edu.au/en/publications/survivors-reactions-to-layoffs-we-get-by-with-a-little-help-for-o/"&gt;Survivors&amp;rsquo; Reactions to Layoffs: We Get By with a Little Help for Our Friends&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Joel Brockner, Steven Grover, Thomas Reed, Rocki DeWitt, and Michael O&amp;rsquo;Malley · 1987&lt;/p&gt;
&lt;p&gt;The strongest negative reactions occurred when survivors identified with those laid off and perceived the departing employees&amp;rsquo; compensation as inadequate. Outcomes were work performance in a laboratory study and organizational commitment in a field study. The result supports considering treatment of departing colleagues, not a universal severance amount, a guaranteed return on support, or a claim that all layoffs have identical effects.&amp;#160;&lt;a href="#fnref:10" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:11"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://adamgrant.net/book/give-and-take/"&gt;Give and Take: A Revolutionary Approach to Success&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Adam Grant · 2013&lt;/p&gt;
&lt;p&gt;Grant describes both the long-term value of trust and reputation and the risk of burnout or exploitation. His &lt;a href="https://knowledge.wharton.upenn.edu/podcast/knowledge-at-wharton-podcast/givers-vs-takers-the-surprising-truth-about-who-gets-ahead/"&gt;Wharton interview&lt;/a&gt; discusses those mechanisms and the importance of boundaries. This informs the long-game argument; it is not evidence that every act of generosity earns a return.&amp;#160;&lt;a href="#fnref:11" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title>Systems That Remember</title><link>https://lanej.io/writing/systems-that-remember/</link><guid isPermaLink="true">https://lanej.io/writing/systems-that-remember/</guid><pubDate>Tue, 08 Sep 2026 06:15:00 -0700</pubDate><description>Failure becomes useful when its lesson stops depending on memory.</description><content:encoded>&lt;p&gt;On August 27, a deployment briefly degraded EasyPost&amp;rsquo;s Core APIs. At 10:26 AM, the change was identified and rolled back. By 10:40, the APIs were back to normal.&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The interesting part is that rollback was already available.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;EasyPost deploys through a system built around canary traffic, retained previous versions, and immediate rollback.&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt; Those mechanisms did not make failure impossible. They changed what happened after failure.&lt;/p&gt;
&lt;p&gt;They show what durable learning looks like once it has been encoded into the system, regardless of whether a particular mechanism came from an incident or deliberate design.&lt;/p&gt;
&lt;p&gt;What matters after 10:40 is whether this incident leaves another durable change behind.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="start-with-the-system"&gt;Start with the system&lt;/h2&gt;
&lt;p&gt;When something goes wrong, my starting assumption is that the person nearest the failure is giving me evidence about the system around them.&lt;/p&gt;
&lt;p&gt;That does not mean people never make mistakes, judgment does not matter, or performance problems should be ignored. It means that blaming the person who happened to trigger a failure is usually a poor way to understand why the failure was possible.&lt;/p&gt;
&lt;p&gt;A deploy reaches too much traffic before anyone can see the effect. A dependency can stall every request thread. An operator has to remember an unusual recovery sequence. A dangerous state is technically valid because nothing rejects it.&lt;/p&gt;
&lt;p&gt;The person is visible. The conditions that made the failure likely are less visible.&lt;/p&gt;
&lt;p&gt;Google&amp;rsquo;s SRE practice makes blamelessness part of the mechanics of learning, not just a preference about tone. Its postmortem guidance starts from the assumption that people acted in good faith with the information available to them, then looks for changes to systems, procedures, and training that reduce recurrence.&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;I like that framing because blame distorts signal. If surfacing a mistake is personally expensive, people become rationally selective about which mistakes they surface. Near misses stay private. Ambiguous evidence gets cleaned up before it is shared. The organization learns less because it has made learning risky.&lt;/p&gt;
&lt;p&gt;Blamelessness is useful because it makes the system easier to investigate honestly.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="a-postmortem-can-still-forget"&gt;A postmortem can still forget&lt;/h2&gt;
&lt;p&gt;Writing down what happened is better than relying on memory. It is not the end state.&lt;/p&gt;
&lt;p&gt;A postmortem can explain that a rollout needed better isolation. Six months later, a new engineer can ship without reading it. A runbook can explain the recovery sequence. At 3 AM, somebody can miss step seven. A document can say that a particular configuration is unsafe while the API continues to accept it.&lt;/p&gt;
&lt;p&gt;The lesson still depends on a person remembering the lesson.&lt;/p&gt;
&lt;p&gt;When possible, I want the learning to move closer to the place where the failure occurred.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What we learned&lt;/th&gt;
&lt;th&gt;What the system can remember&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;We could not see the failure early enough&lt;/td&gt;
&lt;td&gt;Instrumentation, alerting, health checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A change could affect too much traffic at once&lt;/td&gt;
&lt;td&gt;Canarying, staged rollout, blast-radius controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recovery depended on a person remembering what to do&lt;/td&gt;
&lt;td&gt;Automated rollback or recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A dependency can fail in a predictable way&lt;/td&gt;
&lt;td&gt;Timeout, retry, fallback, isolation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;An invalid state was allowed&lt;/td&gt;
&lt;td&gt;Validation, invariant, test, policy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A procedure was repeatedly performed by hand&lt;/td&gt;
&lt;td&gt;Automation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The interface made the wrong action easy&lt;/td&gt;
&lt;td&gt;A simpler interface&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Not every lesson belongs in code. Some failures expose ambiguous goals, bad incentives, missing expertise, or genuinely contextual decisions. Those still require judgment.&lt;/p&gt;
&lt;p&gt;But repeated mechanical corrections are a smell. If the same failure keeps producing the same reminder, the reminder is probably living at the wrong layer.&lt;/p&gt;
&lt;p&gt;A postmortem records what happened. A system change records what was learned.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="learning-changes-tools"&gt;Learning changes tools&lt;/h2&gt;
&lt;p&gt;Encoding a lesson changes more than the implementation. It changes the environment the next person operates inside.&lt;/p&gt;
&lt;p&gt;A deployment tool that defaults to a canary makes gradual rollout ordinary. An API that rejects an unsafe configuration removes a decision somebody previously had to remember. Better instrumentation puts evidence in front of an operator before they have to remember to go looking for it.&lt;/p&gt;
&lt;p&gt;The important mechanism is the default. People tend to take the path a system makes easiest, especially when they are busy, unfamiliar with it, or operating under pressure. A safer procedure that requires remembering an exception is weaker than a tool that makes the safer procedure ordinary.&lt;/p&gt;
&lt;p&gt;This is the same idea behind a pit of success: do not merely tell people what the right action is. Shape the environment so that the right action is the natural action, and make the dangerous path harder or impossible when you can.&lt;/p&gt;
&lt;p&gt;A postmortem can say, “canary this kind of change.” A deployment system can canary it by default. Training can say, “check this signal before proceeding.” A workflow can put that signal directly in the decision path. Documentation can say, “never create this state.” An API can refuse to create it.&lt;/p&gt;
&lt;p&gt;The lesson changes the tool, and the tool changes the behavior that follows from it.&lt;/p&gt;
&lt;p&gt;That gives me a useful test for whether an organization has really retained a mechanical lesson:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A system remembers when someone who never learned the lesson still behaves differently because of it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The next engineer does not need to know which incident produced a guardrail. They inherit the accumulated judgment embedded in the interface, the defaults, the automation, and the constraints around them.&lt;/p&gt;
&lt;p&gt;Over time, the operating environment becomes a record of what the organization has learned.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="reliability-is-accumulated-memory"&gt;Reliability is accumulated memory&lt;/h2&gt;
&lt;p&gt;This is the part of incident response that compounds.&lt;/p&gt;
&lt;p&gt;A perfectly monotonic uptime graph would be nice, but it is not how complex systems usually improve. Systems change, traffic changes, dependencies change, and new failure modes appear. A better system can still have an incident tomorrow.&lt;/p&gt;
&lt;p&gt;What I want to see is accumulation.&lt;/p&gt;
&lt;p&gt;EasyPost&amp;rsquo;s release history includes repeated work on shipment-purchase performance, database-query performance, connection stability, USPS fallback handling, carrier timeout behavior, and other reliability or latency paths.&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Not every change is incident-driven. The important pattern is the accumulation of small changes to the mechanisms that determine how the system behaves when reality differs from the happy path.&lt;/p&gt;
&lt;p&gt;The rollback path from the August incident shows the other side of that accumulation. The important fact is not that rollback was invented during the outage. It was already there. Some earlier decision had made recovery a capability of the system instead of an improvisation by the operator.&lt;sup id="fnref1:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The capability was part of the system before anyone needed it that morning.&lt;/p&gt;
&lt;p&gt;That is the operational version of the learning loop I described in &lt;a href="https://lanej.io/writing/close-the-loop/"&gt;Close the Loop&lt;/a&gt;: failure produces evidence, but the loop is not really closed until that evidence changes future behavior.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="make-the-lesson-durable"&gt;Make the lesson durable&lt;/h2&gt;
&lt;p&gt;Incidents already cost something: customer trust, engineering attention, interrupted work, lost sleep, sometimes money.&lt;/p&gt;
&lt;p&gt;Restoring service stops the immediate cost. It does not recover it.&lt;/p&gt;
&lt;p&gt;The return comes from learning something that changes the next failure. Maybe the next incident is detected earlier. Maybe its blast radius is smaller. Maybe recovery takes one action instead of twelve. Maybe the entire class of failure becomes impossible.&lt;/p&gt;
&lt;p&gt;That is why I care more about the action that survives the postmortem than the postmortem itself.&lt;/p&gt;
&lt;p&gt;People forget. Systems do not have to.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;EasyPost, &lt;a href="https://www.easypoststatus.com/"&gt;status page&lt;/a&gt;, incident history for August 27, 2026.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;EasyPost, &lt;a href="https://www.easypost.com/blog/easypost-api-reliability-guide/"&gt;Shipping API Reliability Guide&lt;/a&gt;, July 14, 2025.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;Google SRE, &lt;a href="https://sre.google/sre-book/postmortem-culture/"&gt;Postmortem Culture: Learning from Failure&lt;/a&gt; and the &lt;a href="https://sre.google/workbook/postmortem-culture/"&gt;SRE Workbook chapter on postmortem culture&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;EasyPost, &lt;a href="https://docs.easypost.com/releases"&gt;release history&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title>Minimum Effective Dose</title><link>https://lanej.io/writing/minimum-effective-dose/</link><guid isPermaLink="true">https://lanej.io/writing/minimum-effective-dose/</guid><pubDate>Sun, 06 Sep 2026 18:42:54 -0700</pubDate><description>Do enough to learn what matters. Build one complete path, resist speculative scope, and let evidence determine the next investment.</description><content:encoded>&lt;p&gt;Suppose a customer asks for a report every Monday morning.&lt;/p&gt;
&lt;p&gt;Before anyone sends it, the work expands. We need configurable schedules. Different file formats. Saved views. A place to manage all of it. Each addition is reasonable if we are building a reporting product.&lt;/p&gt;
&lt;p&gt;But we do not yet know whether the report helps the customer make a better decision.&lt;/p&gt;
&lt;p&gt;That is the question I want answered first. Not whether we can build a reporting system. Whether this particular information, delivered to this person at this time, changes something worth changing.&lt;/p&gt;
&lt;p&gt;I want the smallest intervention that gives us a credible answer, then I want the answer to determine the next investment.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That is what I mean by minimum effective dose: enough intervention to resolve the uncertainty that matters, without accumulating obligations around an answer we do not yet have.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The thing to minimize is the cost of reaching the next informed decision, not the ambition of the eventual result.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="information-that-changes-a-decision"&gt;Information that changes a decision&lt;/h2&gt;
&lt;p&gt;A team can learn a great deal without getting any closer to deciding what to do.&lt;/p&gt;
&lt;p&gt;Benchmarking databases might be useful. It does not answer whether anyone needs the report. Interviews might establish that people dislike their current process. They do not establish that our integration can obtain the required data before Monday morning.&lt;/p&gt;
&lt;p&gt;I care about decision-relevant information: what we need to know to choose the next action.&lt;/p&gt;
&lt;p&gt;Dan North&amp;rsquo;s &lt;em&gt;Deliberate Discovery&lt;/em&gt; frames engineering work around identifying the ignorance constraining progress and deliberately reducing it.&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt; Wes Kao uses &lt;em&gt;minimum effective dose&lt;/em&gt; for a closely related business idea: do enough work to obtain the insight needed for the decision.&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Before starting, I want three things to be clear: what we do not know, which decision that prevents us from making, and what we would do differently depending on the result.&lt;/p&gt;
&lt;p&gt;For the report, we might be deciding whether to invest in recurring delivery. The first useful evidence is whether the customer can use the information, in time, to make the decision they described.&lt;/p&gt;
&lt;p&gt;An enthusiastic response is not the same as use. Use is not the same as a better outcome. One customer&amp;rsquo;s result is not proof of a market. Each observation justifies a different next step.&lt;/p&gt;
&lt;p&gt;If every possible result leads to “continue building the original plan,” we are not really running an experiment.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="a-path-through-positive-space"&gt;A path through positive space&lt;/h2&gt;
&lt;p&gt;A project can become an inventory of everything that might eventually be required. Every customer, exception, dependency, failure mode, and future extension gets a place in the design before we have established a useful path through any of them.&lt;/p&gt;
&lt;p&gt;I think of &lt;em&gt;positive space&lt;/em&gt; as the part of the problem where we have evidence that useful action is possible: a concrete route from a need to an outcome under conditions we understand.&lt;/p&gt;
&lt;p&gt;For the Monday report, that route might be one data source, one agreed calculation, one recipient, and one decision. It gives us somewhere to stand. We can then ask what prevents that path from being dependable, repeatable, or useful to someone else.&lt;/p&gt;
&lt;p&gt;A failed attempt can locate the path too. If the customer receives correct information and does nothing differently, perhaps the report answers the wrong question, arrives too late, or reaches someone who cannot act.&lt;/p&gt;
&lt;p&gt;Positive space is not positive results. It is evidence about where useful action is possible.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="narrow-does-not-mean-incomplete"&gt;Narrow does not mean incomplete&lt;/h2&gt;
&lt;p&gt;A steel thread is a useful implementation pattern here: build a narrow slice through the relevant parts of the real system rather than building each component extensively and connecting them later.&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;For the report, the thread runs from source data to customer decision. A working query is only part of it. So is an email arriving on time. We need enough of the real path to find out whether the information can do the job.&lt;/p&gt;
&lt;figure class="essay-diagram" data-essay-diagram="minimum-dose-thread" aria-labelledby="minimum-dose-thread-caption"&gt;
&lt;div class="formalization-panel"&gt;
&lt;p class="diagram-label"&gt;One report. One decision. A complete path.&lt;/p&gt;
&lt;p class="diagram-description"&gt;Test whether the information is useful before building a reporting platform.&lt;/p&gt;
&lt;ol class="formalization-steps"&gt;
&lt;li&gt;&lt;span class="flow-node"&gt;&lt;strong&gt;Real input&lt;/strong&gt;&lt;span&gt;One relevant data source&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Use correct data with appropriate access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="flow-node"&gt;&lt;strong&gt;Delivery&lt;/strong&gt;&lt;span&gt;One report, on time&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Reach the person who needs to act.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="flow-node"&gt;&lt;strong&gt;Decision&lt;/strong&gt;&lt;span&gt;One intended use&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Observe whether the information changes the decision.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="flow-node flow-node-accent"&gt;&lt;strong&gt;Result&lt;/strong&gt;&lt;span&gt;Evidence, not a demo&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Decide what to continue, change, or stop.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;figcaption id="minimum-dose-thread-caption"&gt;&lt;span&gt;Figure 1.&lt;/span&gt; Narrow across use cases; complete across the path needed to answer the question. A useful result for one customer does not prove general demand or scalable delivery.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This does not require every report format or a scheduling interface. It does require correct data, appropriate access, intelligible output, and delivery early enough to matter. We also need to observe what happens after delivery.&lt;/p&gt;
&lt;p&gt;Choose the thread for the uncertainty it encounters, not because it is easy to demonstrate. If the external source is the risk, replacing it with a convenient stub avoids the question. If customer value is the risk, perfecting the integration before anyone sees the result may be the wrong order.&lt;/p&gt;
&lt;p&gt;Sometimes the minimum intervention is not software. A manually prepared report can test whether the information is useful. It cannot establish that an automated service is reliable or inexpensive to operate. A technical thread can establish integration behavior without demonstrating willingness to pay.&lt;/p&gt;
&lt;p&gt;The test has to reach the thing we claim to be testing.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="follow-the-constraint"&gt;Follow the constraint&lt;/h2&gt;
&lt;p&gt;Once a path produces a useful result, what prevents it from doing so reliably or at the required scale?&lt;/p&gt;
&lt;p&gt;Goldratt&amp;rsquo;s Theory of Constraints gives a useful rule for choosing the next intervention: improve what limits the system&amp;rsquo;s objective rather than whichever component is easiest to optimize.&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Suppose the report proves useful but repeatedly arrives after the customer&amp;rsquo;s decision. Tracing the path suggests that corrections and a shared review queue cause the delay.&lt;/p&gt;
&lt;p&gt;The next dose could be a bounded trial with clearer input requirements and checks that prevent avoidable rework before review. That uses the reviewer&amp;rsquo;s existing capacity better and changes the work upstream. It does not justify a reporting platform or a faster query.&lt;/p&gt;
&lt;p&gt;Then measure the path again. Did usable reports reach decisions sooner without worsening errors or delaying other necessary work? Moving this report to the front of the queue may simply transfer the delay.&lt;/p&gt;
&lt;p&gt;A steel thread makes the path observable. Constraint thinking helps choose where to intervene. Minimum effective dose keeps that intervention proportionate to what the evidence can justify.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="scope-creep-spends-the-answer-before-we-have-it"&gt;Scope creep spends the answer before we have it&lt;/h2&gt;
&lt;p&gt;Adding custom schedules to the first report is not just another task. It postpones the value question and commits more effort to an assumption the report was supposed to test.&lt;/p&gt;
&lt;p&gt;Martin Fowler&amp;rsquo;s account of YAGNI includes the carrying cost of speculative capability: even before it is useful, its complexity makes later changes harder.&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt; Here there is another cost too: speculative scope delays the evidence that could redirect the work altogether.&lt;/p&gt;
&lt;p&gt;I use a simple test for proposed additions:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Does this help us answer the question in front of us, or is it something we expect to need after that question is answered?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Correctness checks may be necessary to interpret the result. Access controls may be necessary to run the trial responsibly. Instrumentation may be necessary to know whether anything changed. Those belong in the minimum when the experiment depends on them.&lt;/p&gt;
&lt;p&gt;Multiple export formats, a configuration interface, and support for other departments need a different argument. “We will probably need them eventually” is not enough.&lt;/p&gt;
&lt;p&gt;The boundary protects the question long enough to answer it. It should not protect the original solution from what we discover.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="keep-the-machinery-movable"&gt;Keep the machinery movable&lt;/h2&gt;
&lt;p&gt;Kent Beck&amp;rsquo;s “make it run, make it right, make it fast” is useful to me as an ordering rule, especially when paired with small slices and short feedback cycles.&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;For the report, establish one useful path. Make it dependable enough for the commitment being tested. Then invest where the evidence says improvement matters.&lt;/p&gt;
&lt;p&gt;I think of this as keeping the machinery movable while the requirements are still moving. In software, we can bolt an unsettled answer down with a public interface, a deep dependency chain, or a general-purpose framework. In a business, we can do it with a service promise, a specialized team, or a contract built around the current process.&lt;/p&gt;
&lt;p&gt;The implementation may be small while the commitment is large.&lt;/p&gt;
&lt;p&gt;That is why the dose includes the cost of changing our minds. A narrow boundary around an uncertain integration, tests around the behavior we need, and enough observability to understand failures can all make the next change cheaper. They may be part of the minimum rather than overhead to remove.&lt;/p&gt;
&lt;p&gt;Reducing breadth does not reduce the standard. If the result arrives too late to be useful, performance is already a requirement. If the trial handles sensitive data or moves money, the relevant safeguards belong in the trial.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="the-business-needs-a-complete-path-too"&gt;The business needs a complete path too&lt;/h2&gt;
&lt;p&gt;The engineering path might end with a correct response. The business path usually does not.&lt;/p&gt;
&lt;p&gt;If we are testing a paid service, we may also need to know whether the customer understands the offer, can adopt it, receives the promised benefit, and will pay enough to justify delivering it. Those are separate uncertainties.&lt;/p&gt;
&lt;p&gt;For an initial trial, an existing sales process, a straightforward agreement, a standard invoice, and explicit manual work may be enough. There is no reason to build a new commercial system around the first customer.&lt;/p&gt;
&lt;p&gt;But count the manual work. If every report needs an hour of intervention, the trial has demonstrated delivery with an hour of labor attached. Hiding that effort does not establish good economics.&lt;/p&gt;
&lt;p&gt;Minimum effective dose becomes local cost-cutting when complexity is merely moved into Operations or onto the customer. A system has not become simpler because the obligation changed owners.&lt;/p&gt;
&lt;p&gt;Manual delivery may still be the cheapest credible way to test usefulness. Once delivery is understood and recurring, automation may become the smaller continuing burden. The dose changes as the evidence changes.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="make-the-next-commitment-earn-its-place"&gt;Make the next commitment earn its place&lt;/h2&gt;
&lt;p&gt;In &lt;a href="https://lanej.io/writing/lead-with-problems/"&gt;Lead With Problems&lt;/a&gt;, I argued for a named owner accountable for the outcome, with functions supplying the capabilities needed to achieve it.&lt;/p&gt;
&lt;p&gt;That owner also needs to sequence the learning. Otherwise each function can build its part of the imagined final system while nobody resolves the uncertainty that could invalidate the whole effort.&lt;/p&gt;
&lt;p&gt;I want the owner to explain what currently limits the outcome, the evidence behind that diagnosis, and the next test. What commitments does it require? What would the result justify? What would cause us to stop?&lt;/p&gt;
&lt;figure class="essay-diagram" data-essay-diagram="minimum-dose-decision" aria-labelledby="minimum-dose-decision-caption"&gt;
&lt;div class="formalization-panel"&gt;
&lt;p class="diagram-label"&gt;Earn the next commitment&lt;/p&gt;
&lt;p class="diagram-description"&gt;Each intervention should change what we are justified in doing next.&lt;/p&gt;
&lt;ol class="formalization-steps"&gt;
&lt;li&gt;&lt;span class="flow-node"&gt;&lt;strong&gt;Question&lt;/strong&gt;&lt;span&gt;What blocks the decision?&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Name the uncertainty and the outcome that matters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="flow-node"&gt;&lt;strong&gt;Test&lt;/strong&gt;&lt;span&gt;What would resolve it?&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Choose the smallest credible test, including necessary safeguards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="flow-node"&gt;&lt;strong&gt;Evidence&lt;/strong&gt;&lt;span&gt;What actually happened?&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Account for the result, limitations, and all the work involved.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="flow-node flow-node-accent"&gt;&lt;strong&gt;Commitment&lt;/strong&gt;&lt;span&gt;What does this justify?&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Continue, change, or stop. Expansion is not automatic.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;figcaption id="minimum-dose-decision-caption"&gt;&lt;span&gt;Figure 2.&lt;/span&gt; The next intervention starts from the evidence, not the unbuilt portion of the original plan.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;After the test, return to the claim. What changed? What remains uncertain? What is the strongest conclusion the evidence supports? What did the intervention cost, including work done by other people?&lt;/p&gt;
&lt;p&gt;That is where &lt;a href="https://lanej.io/writing/close-the-loop/"&gt;closing the loop&lt;/a&gt; matters. The result has to change the next action: stop, strengthen the path, or move attention to a different limitation.&lt;/p&gt;
&lt;p&gt;This is not a license for endless experiments. Once the relevant uncertainty is sufficiently resolved, act. The rigor of the evidence should follow the consequences of the decision: one reversible trial may justify another, while a broad customer promise or difficult-to-reverse architecture needs stronger evidence.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="concentration-not-austerity"&gt;Concentration, not austerity&lt;/h2&gt;
&lt;p&gt;Minimum effective dose does not mean permanently doing less. It means refusing to make every possibility a prerequisite for progress.&lt;/p&gt;
&lt;p&gt;Once the original outcome is achieved, additional investment may be worthwhile. Greater reliability, lower operating cost, or a broader offering can justify substantial work. But that work needs an argument of its own.&lt;/p&gt;
&lt;p&gt;I want a steel thread through the problem, not a miniature version of every system we might eventually need. Enough of the real path to obtain credible evidence. Enough care to meet the standard of the commitment. Little enough speculative machinery that the answer can still change what we do.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Start narrow. Finish the path. Expand for a reason.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://dannorth.net/blog/introducing-deliberate-discovery/"&gt;Introducing Deliberate Discovery&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Dan North · 2010&lt;/p&gt;
&lt;p&gt;Identifies and reduces the specific ignorance constraining delivery. The decision-oriented scope test here is my application of that principle.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.weskao.com/blog/use-the-minimum-effective-dose"&gt;Use the minimum effective dose&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Wes Kao · 2020&lt;/p&gt;
&lt;p&gt;Applies the phrase directly to doing enough work to obtain the insight needed for a business decision.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.rubick.com/steel-threads/"&gt;Steel threads are a technique that will make you a better engineer&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Jade Rubick · 2023&lt;/p&gt;
&lt;p&gt;Describes thin, integrated slices through important use cases.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.goldrattresearchlabs.com/introduction-to-toc"&gt;Introduction to Theory of Constraints&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Goldratt Research Labs&lt;/p&gt;
&lt;p&gt;Explains Goldratt&amp;rsquo;s system-level focus and five focusing steps.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://martinfowler.com/bliki/Yagni.html"&gt;Yagni&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Martin Fowler · 2015&lt;/p&gt;
&lt;p&gt;Explains the build, delay, carrying, and repair costs of speculative capability.&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://newsletter.kentbeck.com/p/mastering-programming"&gt;Mastering Programming&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Kent Beck · 2024&lt;/p&gt;
&lt;p&gt;Includes “make it run, make it right, make it fast” alongside slicing and feedback-oriented programming practices.&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title>Socrates: Before I Say ‘Go Build It’</title><link>https://lanej.io/writing/socrates/</link><guid isPermaLink="true">https://lanej.io/writing/socrates/</guid><pubDate>Sun, 06 Sep 2026 17:45:00 -0700</pubDate><description>I built a Claude skill to challenge the request, preserve the decisions, and make the handoff executable.</description><content:encoded>&lt;p&gt;I originally told Socrates to ask me fewer questions.&lt;/p&gt;
&lt;p&gt;Socrates is a &lt;a href="https://github.com/lanej/dotfiles/blob/e48e4f0f3cc72f8f6ab7a0c025bd5304be24fb2d/claude/commands/socrates.md"&gt;Claude skill&lt;/a&gt; I use before planning a piece of work. An earlier version had what sounded like a good rule: read the code, inspect the configuration, look through prior decisions, and try to answer every question before interrupting me. If the agent found a plausible answer, it should record the assumption and move on.&lt;/p&gt;
&lt;p&gt;That worked well for facts. It was a bad rule for decisions.&lt;/p&gt;
&lt;p&gt;Which language does this repository use? Research it. Does an old restriction still serve a purpose? The repository can tell me that the restriction exists. It cannot tell me whether I still want it.&lt;/p&gt;
&lt;p&gt;I had optimized the skill to reduce conversation at exactly the point where the conversation was useful. I did not need a faster requirements form. I wanted the agent to help me think through the work before an implementation gave one interpretation momentum.&lt;/p&gt;
&lt;p&gt;So I changed the rule: &lt;a href="https://github.com/lanej/dotfiles/commit/39048c0f3cc72f8f6ab7a0c025bd5304be24fb2d"&gt;research should arm the question, not eliminate it&lt;/a&gt;. Bring me what you found. Explain why it might matter. Then ask the question that the evidence cannot answer for us.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="why-socrates-title"&gt;Why Socrates&lt;/h2&gt;
&lt;p&gt;The part of the &lt;a href="https://plato.stanford.edu/entries/plato-ethics-shorter/#2"&gt;Socratic method&lt;/a&gt; I’m borrowing is not “keep asking why.” It is the examination of a claim against the rest of what we think we know. A question exposes an assumption; another commitment puts pressure on it; the contradiction or missing premise becomes visible.&lt;/p&gt;
&lt;p&gt;That matters because a request to an AI is not necessarily a correct specification of the problem. I may arrive with a preferred solution and a lot of confidence. The model may have an equally plausible interpretation. Neither deserves to become the plan merely because it was stated first.&lt;/p&gt;
&lt;p&gt;The useful outcome is sometimes less certainty, not more. We discover the hole in an answer we were already prepared to act on.&lt;/p&gt;
&lt;p&gt;That is different from endless debate. Socrates still has to converge. The current dialogue loop works one consequential topic at a time: research it, ask one informed question, judge the answer, follow up when it is vague or contradictory, and stop when the relevant issue is stable enough to proceed. There is no question quota to satisfy and no prize for making a small task ceremonial.&lt;/p&gt;
&lt;p&gt;The useful thing is making the assumption visible before either of us builds on it, not getting the agent to agree with me.&lt;/p&gt;
&lt;figure aria-labelledby="method-title" class="sc-figure sc-method-figure" data-essay-diagram="socrates-method" id="method-figure"&gt;
&lt;h3 class="sc-figure-title" id="method-title"&gt;Examining the approval claim&lt;/h3&gt;
&lt;div aria-label="A claim is questioned, pressure-tested against evidence, and revised into a better statement of the problem." class="sc-method-loop" role="group"&gt;
&lt;div class="sc-cycle-node sc-question flow-node" data-node&gt;&lt;span class="sc-node-label"&gt;Initial claim&lt;/span&gt;&lt;span class="sc-node-detail"&gt;This removes the agent’s ability to approve its own spending.&lt;/span&gt;&lt;/div&gt;
&lt;div aria-hidden="true" class="sc-cycle-connector sc-turn-one"&gt;&lt;svg preserveAspectRatio="none" viewBox="0 0 100 100"&gt;&lt;path d="M6 50 C50 50 50 50 50 92"&gt;&lt;/path&gt;&lt;path class="sc-arrowhead" d="m46 86 4 6 4-6"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span class="sc-vertical-arrow"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="sc-cycle-node sc-examine flow-node" data-node&gt;&lt;span class="sc-node-label"&gt;Question&lt;/span&gt;&lt;span class="sc-node-detail"&gt;Which routes to the costly tools does this approval actually control?&lt;/span&gt;&lt;/div&gt;
&lt;div aria-hidden="true" class="sc-cycle-connector sc-turn-two"&gt;&lt;svg preserveAspectRatio="none" viewBox="0 0 100 100"&gt;&lt;path d="M50 6 C50 50 50 50 8 50"&gt;&lt;/path&gt;&lt;path class="sc-arrowhead" d="m14 46-6 4 6 4"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span class="sc-vertical-arrow"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="sc-cycle-node sc-test flow-node" data-node&gt;&lt;span class="sc-node-label"&gt;Tension&lt;/span&gt;&lt;span class="sc-node-detail"&gt;The prompt guards one interface. The agent retains other access to the tools.&lt;/span&gt;&lt;/div&gt;
&lt;div aria-hidden="true" class="sc-cycle-connector sc-turn-three"&gt;&lt;svg preserveAspectRatio="none" viewBox="0 0 100 100"&gt;&lt;path d="M94 50 C50 50 50 50 50 8"&gt;&lt;/path&gt;&lt;path class="sc-arrowhead" d="m46 14 4-6 4 6"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span class="sc-vertical-arrow"&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div class="sc-cycle-node sc-revise flow-node" data-node&gt;&lt;span class="sc-node-label"&gt;Revised understanding&lt;/span&gt;&lt;span class="sc-node-detail"&gt;Keep deliberate human approval in the guarded workflow. State the limit of that control.&lt;/span&gt;&lt;/div&gt;
&lt;div aria-hidden="true" class="sc-cycle-connector sc-turn-four"&gt;&lt;svg preserveAspectRatio="none" viewBox="0 0 100 100"&gt;&lt;path d="M50 94 C50 50 50 50 92 50"&gt;&lt;/path&gt;&lt;path class="sc-arrowhead" d="m86 46 6 4-6 4"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;
&lt;/div&gt;&lt;figcaption class="sc-caption"&gt;Examining the claim established where the approval could be relied on.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="request-to-clarity-title"&gt;From request to clarity&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;What the lock actually stops&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I wanted an AI agent to ask before spending more money. An expensive query or a long analysis session could run past the budget I had in mind. The proposed fix was a biometric approval gate: when the work needed approval, I would authorize it with Touch ID.&lt;/p&gt;
&lt;p&gt;The feature’s description went further: it would remove the agent’s ability to approve its own spending.&lt;/p&gt;
&lt;p&gt;During review, that claim ran into the rest of the design. The agent retained shell access and other routes to the underlying tools. Requiring a fingerprint in one interface did not put those routes behind the same approval. The useful question became whether the gate was still worth building with that limitation.&lt;/p&gt;
&lt;p&gt;I kept it. There was a specific behavior I wanted to stop in the normal workflow: an agent reaching a budget limit, retrying with a larger allowance, and treating its own answer to a confirmation prompt as my permission. Requiring my fingerprint made that approval step mine. It remained useful even though it could not control every action available to the agent.&lt;/p&gt;
&lt;p&gt;That gave the specification a narrower, testable promise. Within the guarded interface, denying approval or letting it time out must stop the operation. An option that automatically answers yes must not count as authorization. The agent’s access outside that interface remained an explicit limitation.&lt;/p&gt;
&lt;p&gt;The gate shipped with that narrower purpose. The review changed what I was prepared to rely on it for. I could require deliberate approval in this workflow without mistaking the prompt for control over all the agent’s spending.&lt;/p&gt;
&lt;figure aria-labelledby="comparison-title" class="sc-figure sc-comparison-figure" data-essay-diagram="socrates-comparison" id="comparison-figure"&gt;
&lt;h3 class="sc-figure-title" id="comparison-title"&gt;How the acceptance criteria changed&lt;/h3&gt;
&lt;div class="sc-comparison"&gt;
&lt;section aria-labelledby="without-label" class="sc-path sc-path-without"&gt;&lt;h4 class="sc-path-label" id="without-label"&gt;Initial proposal&lt;/h4&gt;&lt;div class="sc-path-track"&gt;
&lt;div class="sc-node flow-node" data-node&gt;Build the biometric approval gate&lt;/div&gt;&lt;div aria-hidden="true" class="sc-flow-connector"&gt;&lt;/div&gt;
&lt;div class="sc-node flow-node" data-node&gt;Describe agent self-approval as removed&lt;/div&gt;&lt;div aria-hidden="true" class="sc-flow-connector sc-grow"&gt;&lt;/div&gt;
&lt;div class="sc-node flow-node" data-node&gt;Ship&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;
&lt;section aria-labelledby="with-label" class="sc-path sc-path-with"&gt;&lt;h4 class="sc-path-label" id="with-label"&gt;After review&lt;/h4&gt;&lt;div class="sc-path-track"&gt;
&lt;div class="sc-node flow-node" data-node&gt;Build the biometric approval gate&lt;/div&gt;&lt;div aria-hidden="true" class="sc-flow-connector"&gt;&lt;/div&gt;
&lt;div class="sc-node flow-node" data-node&gt;Define which workflow the gate controls&lt;/div&gt;&lt;div aria-hidden="true" class="sc-flow-connector"&gt;&lt;/div&gt;
&lt;div class="sc-node flow-node" data-node&gt;Require human approval within that workflow&lt;/div&gt;&lt;div aria-hidden="true" class="sc-flow-connector"&gt;&lt;/div&gt;
&lt;div class="sc-node flow-node" data-node&gt;Test denial, timeout, and automated confirmation&lt;/div&gt;&lt;div aria-hidden="true" class="sc-flow-connector"&gt;&lt;/div&gt;
&lt;div class="sc-node flow-node" data-node&gt;Accept the gate with its limits documented&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;
&lt;/div&gt;&lt;figcaption class="sc-caption"&gt;A working prompt is only part of the evidence. Acceptance depends on what the guarded operation does when approval is absent.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="layered-reasoning-title"&gt;Layered reasoning&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Make the argument inspectable&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Once the dialogue settles, Socrates does something that matters more than producing polished prose: it turns the result into a &lt;a href="https://github.com/lanej/dotfiles/blob/e48e4f0f3cc72f8f6ab7a0c025bd5304be24fb2d/claude/commands/socrates.md#phase-2--validation-and-layered-reasoning"&gt;reasoning chain&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The layers are problem, requirements, constraints, risks, success, validation, and execution readiness. I do not care whether all seven headings are present because seven is a nice number. I care that each layer has to follow from the one below it.&lt;/p&gt;
&lt;p&gt;For the cost gate, the &lt;strong&gt;problem&lt;/strong&gt; was spending beyond an intended budget without a deliberate decision from me. That established a &lt;strong&gt;requirement&lt;/strong&gt;: when the guarded workflow asks for approval, only a human can supply it. The &lt;strong&gt;constraint&lt;/strong&gt; was that the agent kept its other access to the tools. Recording that constraint exposed a &lt;strong&gt;risk&lt;/strong&gt;: I might trust the gate to enforce a spending limit beyond the workflow it actually controlled.&lt;/p&gt;
&lt;p&gt;From there, &lt;strong&gt;success&lt;/strong&gt; becomes concrete: a denied or unanswered request must leave the costly operation unexecuted. &lt;strong&gt;Validation&lt;/strong&gt; has to force those cases and inspect what happens afterward. A screenshot of the fingerprint prompt establishes that a prompt appeared. It says nothing about whether the operation still ran after the prompt failed.&lt;/p&gt;
&lt;p&gt;The specification also records what the executor can decide. Prompt wording and internal code structure leave room for judgment. Continuing after a timeout changes the agreement. So does accepting an automated confirmation as approval. Those choices have to come back to me, even if they make the implementation easier.&lt;/p&gt;
&lt;p&gt;The next agent may have none of the conversation that established these limits. The document has to explain why an apparently helpful fallback would violate the requirement.&lt;/p&gt;
&lt;figure aria-labelledby="layers-title" class="sc-figure sc-layers-figure" data-essay-diagram="socrates-layers" id="layers-figure"&gt;
&lt;h3 class="sc-figure-title" id="layers-title"&gt;The seven layers, applied to the cost gate&lt;/h3&gt;
&lt;ol class="sc-layers"&gt;
&lt;li class="sc-layer-row" style="--level:0"&gt;&lt;div class="sc-layer-name flow-node" data-node&gt;&lt;span class="sc-layer-number"&gt;1&lt;/span&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/div&gt;&lt;span class="sc-layer-description"&gt;spending beyond the intended budget without a deliberate human decision&lt;/span&gt;&lt;/li&gt;
&lt;li class="sc-layer-row" style="--level:1"&gt;&lt;div class="sc-layer-name flow-node" data-node&gt;&lt;span class="sc-layer-number"&gt;2&lt;/span&gt;&lt;strong&gt;Requirements&lt;/strong&gt;&lt;/div&gt;&lt;span class="sc-layer-description"&gt;require human approval when the guarded workflow reaches its limit&lt;/span&gt;&lt;/li&gt;
&lt;li class="sc-layer-row" style="--level:2"&gt;&lt;div class="sc-layer-name flow-node" data-node&gt;&lt;span class="sc-layer-number"&gt;3&lt;/span&gt;&lt;strong&gt;Constraints&lt;/strong&gt;&lt;/div&gt;&lt;span class="sc-layer-description"&gt;the agent keeps its existing shell access&lt;/span&gt;&lt;/li&gt;
&lt;li class="sc-layer-row" style="--level:3"&gt;&lt;div class="sc-layer-name flow-node" data-node&gt;&lt;span class="sc-layer-number"&gt;4&lt;/span&gt;&lt;strong&gt;Risks&lt;/strong&gt;&lt;/div&gt;&lt;span class="sc-layer-description"&gt;trust in the gate extends beyond the workflow it controls&lt;/span&gt;&lt;/li&gt;
&lt;li class="sc-layer-row" style="--level:4"&gt;&lt;div class="sc-layer-name flow-node" data-node&gt;&lt;span class="sc-layer-number"&gt;5&lt;/span&gt;&lt;strong&gt;Success&lt;/strong&gt;&lt;/div&gt;&lt;span class="sc-layer-description"&gt;the guarded operation stops when approval is denied or absent&lt;/span&gt;&lt;/li&gt;
&lt;li class="sc-layer-row" style="--level:5"&gt;&lt;div class="sc-layer-name flow-node" data-node&gt;&lt;span class="sc-layer-number"&gt;6&lt;/span&gt;&lt;strong&gt;Validation&lt;/strong&gt;&lt;/div&gt;&lt;span class="sc-layer-description"&gt;exercise refusal and timeout; verify that no costly operation runs&lt;/span&gt;&lt;/li&gt;
&lt;li class="sc-layer-row" style="--level:6"&gt;&lt;div class="sc-layer-name flow-node" data-node&gt;&lt;span class="sc-layer-number"&gt;7&lt;/span&gt;&lt;strong&gt;Execution readiness&lt;/strong&gt;&lt;/div&gt;&lt;span class="sc-layer-description"&gt;approval rules, dependencies, and checks are settled&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;figcaption class="sc-caption"&gt;Each layer changes what the next one must prove. A weakness higher in the stack should send us back down, not get papered over in the plan.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="preserve-intent-title"&gt;Document, sequence, and preserve intent&lt;/h2&gt;
&lt;p&gt;The output of Socrates is not the conversation. It is a set of artifacts another process can use: an authoritative &lt;code&gt;spec.md&lt;/code&gt;, an optional independent critique, a &lt;code&gt;plan.md&lt;/code&gt;, and verification evidence when the work is done.&lt;/p&gt;
&lt;p&gt;The accompanying decision record illustrates what I want the handoff to preserve: the decision, why it exists, what is delegated, and what evidence would demonstrate it. It is a condensed example for the cost gate, not a copy from a saved Socrates session.&lt;/p&gt;
&lt;figure class="sc-figure" data-essay-diagram="socrates-record" id="record-figure" aria-labelledby="record-title"&gt;
&lt;h3 class="sc-figure-title" id="record-title"&gt;What the handoff preserves&lt;/h3&gt;
&lt;div class="sc-cycle-node" data-node&gt;&lt;strong&gt;Decision to preserve&lt;/strong&gt;&lt;span class="sc-node-detail"&gt;Require human approval within the guarded workflow. Other access remains outside its control.&lt;/span&gt;&lt;/div&gt;
&lt;div class="sc-flow-connector" aria-hidden="true"&gt;&lt;/div&gt;
&lt;div class="sc-record-branches"&gt;
&lt;div class="sc-cycle-node" data-node&gt;&lt;strong&gt;Executor may choose&lt;/strong&gt;&lt;span class="sc-node-detail"&gt;Prompt wording and internal code structure.&lt;/span&gt;&lt;/div&gt;
&lt;div class="sc-cycle-node" data-node&gt;&lt;strong&gt;Executor must preserve&lt;/strong&gt;&lt;span class="sc-node-detail"&gt;Denial or timeout stops the operation. Automated confirmation is not approval.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="sc-flow-connector" aria-hidden="true"&gt;&lt;/div&gt;
&lt;div class="sc-cycle-node" data-node&gt;&lt;strong&gt;Evidence for acceptance&lt;/strong&gt;&lt;span class="sc-node-detail"&gt;Exercise missing approval and automated confirmation; inspect whether the costly operation ran.&lt;/span&gt;&lt;/div&gt;
&lt;figcaption class="sc-caption"&gt;The decision record carries the why, the limits, and the proof obligation into the next session.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Once that agreement is stable enough, Socrates freezes and versions the specification before planning. “Frozen” is procedural, not magical file protection. If critique exposes a bad assumption or execution discovers something genuinely new, the specification can reopen. What should not happen is an executor quietly weakening the requirement until its preferred implementation qualifies.&lt;/p&gt;
&lt;p&gt;Then sequencing becomes a different problem. Every task in the plan has to trace back through a requirement to the original problem, and the plan gets its own dependency graph. The question is no longer “what do we mean?” but “what has to happen before what?”&lt;/p&gt;
&lt;p&gt;In the cost-gate example, independent plan critique exposed the overstated promise. That finding belonged back in the specification, where it could change both the implementation plan and the standard used to judge the result. Leaving the correction in a review comment would make it too easy for a later executor to miss.&lt;/p&gt;
&lt;p&gt;That is why I separate specification review from plan review. A specification can be right while the proposed steps fail to preserve it. A plan can be internally coherent while testing the wrong thing.&lt;/p&gt;
&lt;p&gt;For the gate, useful verification evidence would show the outcome of denial and timeout, including whether any costly work ran. It would also show that an automated confirmation could not substitute for the required approval. That evidence could establish the agreed behavior within the guarded workflow. The verifier could not turn it into a broader claim about every route the agent could take.&lt;/p&gt;
&lt;p&gt;This is an AI workflow, but the underlying discipline is older and broader: examine the claim, make the reasoning explicit, preserve the decisions, sequence the dependencies, and test the thing you actually meant.&lt;/p&gt;
&lt;p&gt;I use Socrates because AI makes execution cheap enough that &lt;strong&gt;starting the wrong work is increasingly the expensive mistake&lt;/strong&gt;. Sometimes the outcome is a better plan. Sometimes the outcome is deciding not to build the thing I originally asked for.&lt;/p&gt;
&lt;p&gt;Before I say “go build it,” that is exactly the kind of friction I want.&lt;/p&gt;
&lt;figure aria-labelledby="workflow-title" class="sc-figure sc-workflow-figure" data-essay-diagram="socrates-workflow" id="workflow-figure"&gt;
&lt;h3 class="sc-figure-title" id="workflow-title"&gt;The decision handoff&lt;/h3&gt;
&lt;div class="sc-workflow"&gt;
&lt;div class="sc-workflow-stage"&gt;&lt;div class="sc-step flow-node" data-node&gt;&lt;span class="sc-step-number"&gt;1&lt;/span&gt;&lt;strong&gt;Interrogate&lt;/strong&gt;&lt;/div&gt;&lt;p class="sc-step-detail"&gt;Research + dialogue&lt;/p&gt;&lt;/div&gt;
&lt;div aria-hidden="true" class="sc-workflow-connector"&gt;&lt;/div&gt;
&lt;div class="sc-workflow-stage"&gt;&lt;div class="sc-step flow-node" data-node&gt;&lt;span class="sc-step-number"&gt;2&lt;/span&gt;&lt;strong&gt;Freeze spec&lt;/strong&gt;&lt;/div&gt;&lt;p class="sc-step-detail"&gt;spec.md + authority boundaries&lt;/p&gt;&lt;/div&gt;
&lt;div aria-hidden="true" class="sc-workflow-connector"&gt;&lt;/div&gt;
&lt;div class="sc-workflow-stage"&gt;&lt;div class="sc-step flow-node" data-node&gt;&lt;span class="sc-step-number"&gt;3&lt;/span&gt;&lt;strong&gt;Critique plan&lt;/strong&gt;&lt;/div&gt;&lt;p class="sc-step-detail"&gt;plan.md + independent review&lt;/p&gt;&lt;/div&gt;
&lt;div aria-hidden="true" class="sc-workflow-connector"&gt;&lt;/div&gt;
&lt;div class="sc-workflow-stage"&gt;&lt;div class="sc-step flow-node" data-node&gt;&lt;span class="sc-step-number"&gt;4&lt;/span&gt;&lt;strong&gt;Execute&lt;/strong&gt;&lt;/div&gt;&lt;p class="sc-step-detail"&gt;implement the agreed change&lt;/p&gt;&lt;/div&gt;
&lt;div aria-hidden="true" class="sc-workflow-connector"&gt;&lt;/div&gt;
&lt;div class="sc-workflow-stage"&gt;&lt;div class="sc-step flow-node" data-node&gt;&lt;span class="sc-step-number"&gt;5&lt;/span&gt;&lt;strong&gt;Verify&lt;/strong&gt;&lt;/div&gt;&lt;p class="sc-step-detail"&gt;dogfood the failure paths&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div aria-hidden="true" class="sc-return-path"&gt;&lt;span class="sc-return-label"&gt;New evidence reopens the specification&lt;/span&gt;&lt;/div&gt;
&lt;figcaption class="sc-caption"&gt;Reasoning and execution are different sequences. The documents preserve the decisions while the plan orders the work.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;aside class="sc-resources" aria-label="Further reading"&gt;&lt;p&gt;Continue with &lt;a href="https://lanej.io/writing/close-the-loop/"&gt;Close the Loop&lt;/a&gt;, on verifying the work against reality. &lt;a href="https://github.com/lanej/dotfiles/blob/e48e4f0f3cc72f8f6ab7a0c025bd5304be24fb2d/claude/commands/socrates.md"&gt;Read the Socrates source&lt;/a&gt;.&lt;/p&gt;
&lt;/aside&gt;</content:encoded></item><item><title>Lead With Problems</title><link>https://lanej.io/writing/lead-with-problems/</link><guid isPermaLink="true">https://lanej.io/writing/lead-with-problems/</guid><pubDate>Sun, 06 Sep 2026 23:29:00 +0000</pubDate><description>A problem statement is not enough. Ownership, authority, and accountability have to follow it.</description><content:encoded>&lt;p&gt;If I ask a team to build a dashboard, I have already made several decisions.&lt;/p&gt;
&lt;p&gt;I have decided that the problem is missing information. That a dashboard is the right way to provide it. That someone will use the information to make a better decision. And that building software is worth more than the other things the team could do.&lt;/p&gt;
&lt;p&gt;Perhaps all of that is true. But if I only communicate the solution, those assumptions arrive as instructions. The team can execute perfectly without testing any of them.&lt;/p&gt;
&lt;p&gt;I want the organization to distinguish what we know needs to change from what we currently think might change it.&lt;/p&gt;
&lt;p&gt;Marty Cagan makes this distinction in his writing about empowered product teams: their responsibility is to find a solution that produces a useful outcome, not merely implement a feature someone else selected.&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;That requires more than a better problem statement. The funding, decision rights, and definition of success cannot still belong to a predetermined solution.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The problem has to become the unit of ownership, not just the opening paragraph of a project brief.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="a-missing-solution-is-not-a-problem-statement"&gt;A missing solution is not a problem statement&lt;/h2&gt;
&lt;p&gt;“We don&amp;rsquo;t have a dashboard” describes an absence. It does not establish that the absence matters.&lt;/p&gt;
&lt;p&gt;Consider a hypothetical business where new customers stall between signing a contract and completing their first successful transaction. Someone asks for an onboarding dashboard.&lt;/p&gt;
&lt;p&gt;The delay could come from unclear requirements, slow access approvals, an unreliable integration, or a handoff nobody owns. A dashboard could make the delay more visible without making it shorter.&lt;/p&gt;
&lt;p&gt;Start with who is getting stuck, where they wait, and what we have observed. The dashboard is a hypothesis. So are changing a policy, improving documentation, and eliminating a handoff.&lt;/p&gt;
&lt;p&gt;There is a line commonly attributed to Charles Kettering:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A problem well stated is a problem half solved.&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Defining the problem is productive work. Finding that a customer is waiting for an approval, rather than struggling to use the software, can change both the solution and who needs to be involved.&lt;/p&gt;
&lt;p&gt;But the clearer definition only matters if the team can act on it. If a team cannot reject the proposed solution while remaining accountable for the problem, it has been assigned a solution.&lt;/p&gt;
&lt;p&gt;Putting “improve onboarding” above “build dashboard” does not change that.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="leadership-still-has-to-choose"&gt;Leadership still has to choose&lt;/h2&gt;
&lt;p&gt;There are more real problems than a company can afford to solve. Reframing a feature roadmap as outcomes does not establish that it contains the most important problems.&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;My responsibility is to identify the smallest set whose solution would materially improve the company&amp;rsquo;s position, then concentrate resources on them. Why this problem? Why now? What are we choosing not to do?&lt;/p&gt;
&lt;p&gt;“Grow revenue” and “improve efficiency” name desirable results without explaining the obstacle or a credible way through it. Richard Rumelt&amp;rsquo;s distinction is useful here: strategy connects a diagnosis to a guiding policy and coordinated actions. A target alone does not do that work.&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Teams should surface problems leadership has missed and challenge a diagnosis when the evidence contradicts it. Leadership still has to make the choices and resolve competing claims on resources.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="put-the-problem-where-it-can-be-solved"&gt;Put the problem where it can be solved&lt;/h2&gt;
&lt;p&gt;A proposed solution can quietly determine which department receives the work.&lt;/p&gt;
&lt;p&gt;“Build a dashboard” goes to a software team. “Hire more implementation engineers” becomes a staffing request. “Train the customer better” goes to customer success. Each narrows the diagnosis before anyone has established where the problem lives.&lt;/p&gt;
&lt;p&gt;In the onboarding example, the relevant system runs from what Sales promises to what the customer can successfully do. The owner needs to follow that whole path, not just the part inside one department.&lt;/p&gt;
&lt;p&gt;The operating model I want separates two responsibilities: functions develop capabilities and maintain standards; a named problem owner stays accountable for the complete outcome.&lt;/p&gt;
&lt;p&gt;That owner needs capacity commitments from contributing functions, authority within agreed constraints, and a named leader to resolve conflicts beyond that authority.&lt;/p&gt;
&lt;p&gt;“Own onboarding” is an empty assignment if the owner can change a page but cannot get a decision about the approval process causing the delay. Leadership has to commit the necessary capacity, provide that decision path, or place ownership where the conflict can be resolved.&lt;/p&gt;
&lt;p&gt;Individual teams can own bounded contributions. Someone must still own the complete outcome. Every department finishing its task does not help a customer who remains stuck.&lt;/p&gt;
&lt;p&gt;The people manager and problem owner can be different people. Their commitments must not create two competing priority queues. Capacity, decision rights, and escalation need to be agreed rather than renegotiated by individual contributors every morning.&lt;/p&gt;
&lt;figure class="essay-diagram" data-essay-diagram="problem-ownership" aria-labelledby="problem-ownership-caption"&gt;
&lt;div class="formalization-panel"&gt;
&lt;p class="diagram-label"&gt;Two responsibilities, one outcome&lt;/p&gt;
&lt;p class="diagram-description"&gt;The problem can cross functions. Accountability must follow the complete path.&lt;/p&gt;
&lt;div class="ownership-roles"&gt;
&lt;div class="flow-node"&gt;&lt;strong&gt;Functions&lt;/strong&gt;&lt;p&gt;Develop capabilities and maintain standards. Commit the capacity the problem needs.&lt;/p&gt;&lt;/div&gt;
&lt;div class="flow-node flow-node-accent"&gt;&lt;strong&gt;Problem owner&lt;/strong&gt;&lt;p&gt;Coordinate the work across functions. Stay accountable for the complete outcome.&lt;/p&gt;&lt;/div&gt;
&lt;div class="flow-node"&gt;&lt;strong&gt;Named leader&lt;/strong&gt;&lt;p&gt;Resolve policy or priority conflicts beyond the owner's agreed authority.&lt;/p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;figcaption id="problem-ownership-caption"&gt;Capacity, decision rights, and escalation make ownership actionable.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="discover-the-solution-together"&gt;Discover the solution together&lt;/h2&gt;
&lt;p&gt;Problem ownership is not unilateral solution ownership.&lt;/p&gt;
&lt;p&gt;In a product team, Product is responsible for value and business viability, Design for usability, and Engineering for feasibility. Those responsibilities support joint discovery; they are not a sequence in which Product decides, Design decorates, and Engineering implements.&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Engineers should help determine what is worth building. Designers should question whether the workflow makes sense. Product needs to understand what can be sold, supported, funded, and operated, not just what a customer requested. Functions outside the team contribute constraints and access to customers and data, not merely a list of features.&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;A named owner makes accountability clear. It does not make one person&amp;rsquo;s judgment sufficient.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="make-the-assignment-useful"&gt;Make the assignment useful&lt;/h2&gt;
&lt;p&gt;A problem brief should make the next decision easier. For the hypothetical onboarding problem, it might look like this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem.&lt;/strong&gt; New customers stall between signing a contract and their first successful transaction. We need to establish where they wait and why.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why now.&lt;/strong&gt; Customers cannot use what they bought. Establish the frequency and cost of the delay before committing to the requested dashboard.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Evidence and uncertainty.&lt;/strong&gt; We have stalled onboarding cases to investigate. We do not yet know whether missing information, approvals, or integration failures explain the delay.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Outcome and guardrails.&lt;/strong&gt; Reduce time to a successful first transaction without increasing errors or shifting manual work onto customers. Establish a baseline before setting a target.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ownership and authority.&lt;/strong&gt; Name an onboarding owner and agree on capacity from the teams needed to investigate. Let the owner choose the approach within those commitments; name the leader who resolves policy or priority conflicts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next decision.&lt;/strong&gt; Trace recent onboarding attempts and review the findings in one week. Decide what to test, who must act, or whether the problem warrants further investment.&lt;/p&gt;
&lt;p&gt;Suppose that investigation shows most of the delay sits in an approval queue with no clear owner. The onboarding owner brings the evidence to the policy owner and agrees on a named approver and an escalation deadline for a limited trial. If the functions cannot agree on capacity, the designated leader resolves the tradeoff.&lt;/p&gt;
&lt;p&gt;Engineering does not build the dashboard merely because it was the original request. The owner now has a different answer to test against the same outcome.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="change-the-review-not-just-the-brief"&gt;Change the review, not just the brief&lt;/h2&gt;
&lt;p&gt;If every review asks only whether the feature shipped, the practical definition of success is still delivery.&lt;/p&gt;
&lt;p&gt;Deployment does not end the responsibility. The team still needs to establish whether the intended benefit occurred and respond when it did not.&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt; That is the same discipline I described in &lt;a href="https://lanej.io/writing/close-the-loop/"&gt;Close the Loop&lt;/a&gt;: test the result against reality, not just the completion of the work.&lt;/p&gt;
&lt;p&gt;For the onboarding trial, assigning an approver is an action; shorter customer waits are the intended result. Compare those waits with the baseline, check errors and support effort, and investigate cases still getting stuck. Then continue, change, or stop the approach.&lt;/p&gt;
&lt;p&gt;Outcome measures can move for unrelated reasons. The owner is responsible for distinguishing evidence of improvement from coincidence, escalating blockers, and changing an approach that is not working. Sound process supports that responsibility; it does not replace the result.&lt;/p&gt;
&lt;p&gt;Stopping is also a decision. The problem may be smaller than expected, the economics may not work, or another problem may deserve the resources. The owner should be able to make that case without defending the continued existence of a project.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="keep-the-answer-open"&gt;Keep the answer open&lt;/h2&gt;
&lt;p&gt;Leaders can propose solutions. Constraints can be fixed. Routine maintenance does not require elaborate discovery.&lt;sup id="fnref1:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt; The requirement is to distinguish what is genuinely constrained from what is merely someone&amp;rsquo;s preferred answer.&lt;/p&gt;
&lt;p&gt;“I think a dashboard would help because teams cannot see where customers are waiting” is useful because the explanation makes the idea testable. If the dashboard is mandatory, say so. Do not ask a team to discover a solution while privately expecting it to rediscover yours.&lt;/p&gt;
&lt;p&gt;The discipline matters most when substantial effort is at stake: choose the problem deliberately, put it where it can be solved, and give the owner enough authority to let evidence change the answer.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Marty Cagan, &lt;a href="https://www.svpg.com/product-vs-feature-teams/"&gt;Product vs Feature Teams&lt;/a&gt;, August 29, 2019. The distinction concerns outcome accountability and authority to discover solutions, not merely team composition.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;Robert W. Lucky, &lt;a href="https://spectrum.ieee.org/when-the-problem-is-the-problem"&gt;When the Problem Is the Problem&lt;/a&gt;, IEEE Spectrum. Attributes the quotation to Charles Franklin Kettering; this is a secondary attribution, not a verified original Kettering source.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;Jon Moore and Marty Cagan, &lt;a href="https://www.svpg.com/changing-how-you-decide-which-problems-to-solve/"&gt;Changing How You Decide Which Problems To Solve&lt;/a&gt;, September 23, 2022.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;Richard Rumelt, &lt;a href="https://www.mckinsey.com/capabilities/strategy-and-corporate-finance/our-insights/the-perils-of-bad-strategy"&gt;The perils of bad strategy&lt;/a&gt;, June 1, 2011.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;Marty Cagan, &lt;a href="https://www.svpg.com/four-big-risks/"&gt;The Four Big Risks&lt;/a&gt;, December 4, 2017; and &lt;a href="https://www.svpg.com/value-and-viability/"&gt;Value and Viability&lt;/a&gt;, February 7, 2022.&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;Chris Jones and Marty Cagan, &lt;a href="https://www.svpg.com/stakeholders-and-the-product-model/"&gt;Stakeholders and the Product Model&lt;/a&gt;, December 1, 2025. Covers problem framing, sharing potential solutions, business constraints, access to customers and data, and proportionate treatment of operational work.&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7"&gt;
&lt;p&gt;Marty Cagan, &lt;a href="https://www.svpg.com/product-model-concepts/"&gt;Product Model Concepts&lt;/a&gt;, January 17, 2024, especially Product Delivery.&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title>Harmony</title><link>https://lanej.io/writing/harmony/</link><guid isPermaLink="true">https://lanej.io/writing/harmony/</guid><pubDate>Sun, 06 Sep 2026 18:22:16 +0000</pubDate><description>How Socrates keeps a specification coherent as its assumptions change.</description><content:encoded>&lt;p&gt;A specification can become incoherent one reasonable answer at a time.&lt;/p&gt;
&lt;p&gt;I built &lt;strong&gt;Socrates&lt;/strong&gt;, a Claude skill, to turn ambiguous intent into an execution-ready specification through dialogue. It investigates the problem, challenges assumptions, tests interpretations, and makes success criteria and decision boundaries explicit. The goal is a shared understanding that lets an agent do the intended work rather than execute the wrong task correctly.&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Harmony is one of the properties Socrates evaluates: whether the problem, requirements, assumptions, constraints, success criteria, and verification strategy still describe the same task as the conversation changes.&lt;sup id="fnref1:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;A requirement can be clear while its acceptance test rewards the wrong behavior. A risk can look acceptable while depending on a fallback another decision removed. Each answer can make sense in isolation. Together, they may no longer describe a viable task.&lt;/p&gt;
&lt;p&gt;In &lt;a href="https://lanej.io/writing/close-the-loop/"&gt;Close the Loop&lt;/a&gt;, I argued for feedback that tests a result against reality. Harmony applies a complementary check inside the specification.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do our requirements and checks still describe compatible ideas of success?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="what-unix-already-got-right"&gt;What Unix already got right&lt;/h2&gt;
&lt;p&gt;Unix already gives us narrow purpose and composition together. The 1978 foreword by McIlroy, Pinson, and Tague tells programmers to make each program do one thing well and to expect its output to become input to another program.&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The useful amendment for my own practice is temporal: composition has to remain coherent as its parts change.&lt;/p&gt;
&lt;p&gt;A useful interface lets me ignore how another component works. It cannot let me ignore the promises I depend on.&lt;/p&gt;
&lt;p&gt;That distinction matters in specifications too. The sections are separate because they serve different purposes, but the promises crossing those sections still have to agree.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="the-contract-between-the-contracts"&gt;The contract between the contracts&lt;/h2&gt;
&lt;p&gt;Consider a simple job-processing system.&lt;/p&gt;
&lt;p&gt;The client may retry a request for up to 24 hours. It uses the same request identifier each time. The service remembers completed identifiers for at least that long, so it can recognize a retry instead of performing the work again.&lt;/p&gt;
&lt;p&gt;Now shorten the retention window to 15 minutes to reduce storage.&lt;/p&gt;
&lt;p&gt;The service faithfully expires its records after 15 minutes. Its tests pass. The client faithfully retries within its 24-hour window. Its tests pass too.&lt;/p&gt;
&lt;p&gt;But a retry arriving after the record expires can be treated as new work.&lt;/p&gt;
&lt;p&gt;Both local rules are implemented correctly. The shared promise is broken.&lt;/p&gt;
&lt;figure class="essay-diagram" data-essay-diagram="harmony-contracts" aria-labelledby="harmony-contracts-caption"&gt;
&lt;div class="loop-comparison"&gt;
&lt;section class="diagram-panel" aria-label="Before: compatible time windows"&gt;
&lt;p class="diagram-label"&gt;Before&lt;/p&gt;
&lt;p class="diagram-description"&gt;The retention policy covers the retry promise.&lt;/p&gt;
&lt;div class="flow-node"&gt;Client retry window: 24 hours&lt;/div&gt;
&lt;div class="flow-arrow" aria-hidden="true"&gt;↓&lt;/div&gt;
&lt;div class="flow-node flow-node-accent"&gt;Service memory: at least 24 hours&lt;/div&gt;
&lt;p class="loop-note"&gt;This timing condition holds. Other correctness checks still apply.&lt;/p&gt;
&lt;/section&gt;
&lt;section class="diagram-panel" aria-label="After: incompatible time windows"&gt;
&lt;p class="diagram-label"&gt;After a local optimization&lt;/p&gt;
&lt;p class="diagram-description"&gt;Storage falls. The client's promise stays unchanged.&lt;/p&gt;
&lt;div class="flow-node"&gt;Client retry window: 24 hours&lt;/div&gt;
&lt;div class="flow-arrow" aria-hidden="true"&gt;↓&lt;/div&gt;
&lt;div class="flow-node flow-node-accent"&gt;Service memory: 15 minutes&lt;/div&gt;
&lt;p class="loop-note"&gt;&lt;strong&gt;Contract mismatch:&lt;/strong&gt; an allowed retry can repeat completed work.&lt;/p&gt;
&lt;/section&gt;
&lt;/div&gt;
&lt;figcaption id="harmony-contracts-caption"&gt;&lt;span&gt;Figure 1.&lt;/span&gt; Illustrative example: both local rules can be implemented correctly while the shared retry guarantee fails.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The relationship that mattered was not the request shape. It was the relationship between the retry window and the lifetime of the service&amp;rsquo;s memory.&lt;/p&gt;
&lt;p&gt;Interface theory gives this distinction a formal counterpart. In &lt;em&gt;Interface Automata&lt;/em&gt;, Luca de Alfaro and Thomas Henzinger model both a component&amp;rsquo;s assumptions and guarantees, then reason about whether components are compatible.&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt; I am borrowing the distinction, not claiming Socrates implements that formalism.&lt;/p&gt;
&lt;p&gt;In the retry example, the deduplication window has to cover the retry window. Losing records, changing identifiers, and concurrent requests introduce other requirements, but the timing relationship alone is enough to show why two locally valid decisions can conflict.&lt;/p&gt;
&lt;p&gt;The same conflict can exist before any code does. A requirement permits retries for 24 hours. A constraint permits retaining the necessary records for only 15 minutes. Someone has to change the design, change the promise, or reject the optimization.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="untouched-does-not-mean-unaffected"&gt;Untouched does not mean unaffected&lt;/h2&gt;
&lt;p&gt;The dangerous part of the retry example is the client. Nobody changed it.&lt;/p&gt;
&lt;p&gt;A review focused on storage might examine memory usage, expiration behavior, and cleanup performance. All relevant. None tells us whether the client can still rely on the service.&lt;/p&gt;
&lt;p&gt;The client&amp;rsquo;s previous validation depended on an assumption about how long the service remembered requests. When that assumption changed, the justification changed too.&lt;/p&gt;
&lt;p&gt;An unchanged component can lose its justification.&lt;/p&gt;
&lt;p&gt;I think about conclusions in a design discussion the same way. We decide a requirement is feasible because a constraint holds. We accept a risk because a fallback exists. Later, the constraint changes or the fallback disappears, while the earlier conclusion remains marked as settled.&lt;/p&gt;
&lt;p&gt;That conclusion is no longer settled for the same reasons.&lt;/p&gt;
&lt;p&gt;Jon Doyle&amp;rsquo;s &lt;em&gt;A Truth Maintenance System&lt;/em&gt; records the reasons behind beliefs so they can be revised when assumptions change.&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt; Socrates does not implement Doyle&amp;rsquo;s algorithm, but the practical obligation is similar: conclusions should not outlive the premises that justified them.&lt;/p&gt;
&lt;p&gt;That is the part of Harmony I care about most. It is not terminology consistency. It is preserving the dependency between a decision and the reasons it was safe to make.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="the-property-and-the-check"&gt;The property and the check&lt;/h2&gt;
&lt;p&gt;Harmony names the property. The recurring review is how Socrates tries to preserve it.&lt;/p&gt;
&lt;p&gt;Requirements engineering has treated inconsistency as useful information rather than merely a defect to erase. Nuseibeh, Easterbrook, and Russo describe evolving specifications, code, tests, and other descriptions that can disagree in ways that expose missing knowledge.&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;That fits the behavior I want from Socrates. A contradiction should reopen the discussion, not be smoothed over so the plan reads cleanly.&lt;/p&gt;
&lt;p&gt;Most checks in the workflow are revisited when the conversation touches them. Harmony runs on every interrogation pass. Its useful question is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What would this change break somewhere else in the spec that nobody is discussing?&lt;/strong&gt;&lt;sup id="fnref2:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the retry example, shortening retention should reopen the retry promise, its acceptance tests, and migration assumptions—not just the storage paragraph. Socrates should ask whether the promise changes or another mechanism must preserve it.&lt;/p&gt;
&lt;p&gt;The process records a Harmony assessment on each pass, including rationale and uncertainty. Contradictions are resolved, bounded, or explicitly left open; a frozen specification can be reopened when later evidence undermines its premises.&lt;sup id="fnref3:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;figure class="essay-diagram" data-essay-diagram="harmony-review" aria-labelledby="harmony-review-caption"&gt;
&lt;div class="formalization-panel"&gt;
&lt;p class="diagram-label"&gt;Harmony in Socrates&lt;/p&gt;
&lt;p class="diagram-description"&gt;Each interrogation pass checks the whole specification, including conclusions nobody edited.&lt;/p&gt;
&lt;ol class="formalization-steps"&gt;
&lt;li&gt;&lt;div class="flow-node"&gt;&lt;strong&gt;Change&lt;/strong&gt;&lt;span&gt;A requirement, constraint, or assumption changes.&lt;/span&gt;&lt;/div&gt;&lt;p&gt;Identify what is different.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;div class="flow-node"&gt;&lt;strong&gt;Trace&lt;/strong&gt;&lt;span&gt;Which earlier conclusions depended on it?&lt;/span&gt;&lt;/div&gt;&lt;p&gt;Untouched does not mean unaffected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;div class="flow-node"&gt;&lt;strong&gt;Reconcile&lt;/strong&gt;&lt;span&gt;Preserve the promise—or explicitly revise it.&lt;/span&gt;&lt;/div&gt;&lt;p&gt;Reopen decisions when needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;div class="flow-node flow-node-accent"&gt;&lt;strong&gt;Verify and record&lt;/strong&gt;&lt;span&gt;Check the relationship. Name the uncertainty.&lt;/span&gt;&lt;/div&gt;&lt;p&gt;A recorded review is not a proof.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;figcaption id="harmony-review-caption"&gt;&lt;span&gt;Figure 2.&lt;/span&gt; Harmony checks whether the specification still holds together. This is a review procedure, not a formal proof.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;That does not turn the process into a proof system. The verification procedure can check that Harmony was assessed and that required escalations have a recorded resolution.&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt; It cannot prove that the assessment found every contradiction.&lt;/p&gt;
&lt;p&gt;The benefit is narrower: the whole specification remains an explicit object of attention, and uncertainty is left visible instead of being converted into false consistency.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="the-tools-have-to-agree-too"&gt;The tools have to agree too&lt;/h2&gt;
&lt;p&gt;The change that introduced Harmony also corrected an inconsistency in the tooling itself.&lt;/p&gt;
&lt;p&gt;The specification workflow represented an approved specification with a status of &lt;code&gt;Validated&lt;/code&gt; and a separate &lt;code&gt;Frozen: true&lt;/code&gt; flag. The orchestration instructions used a different vocabulary: they treated &lt;code&gt;Frozen&lt;/code&gt; as the status to wait for.&lt;/p&gt;
&lt;p&gt;The producer and consumer disagreed about the same state transition.&lt;/p&gt;
&lt;p&gt;The same change aligned that vocabulary and repaired an active-session pointer expected downstream but not written upstream.&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Those defects were small. They made the abstraction concrete: separate tools can each do their own job correctly while disagreeing about the protocol between them.&lt;/p&gt;
&lt;p&gt;The fix did not copy the entire Harmony process into every command. Specification work kept the reasoning; critique and verification received checks appropriate to their roles; orchestration stayed narrow.&lt;sup id="fnref1:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Preserving the whole does not mean making every part do everything. It means making responsibility for the relationships explicit.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="make-the-review-cheaper"&gt;Make the review cheaper&lt;/h2&gt;
&lt;p&gt;If every small change required re-proving the entire system, independent development would disappear.&lt;/p&gt;
&lt;p&gt;The practical answer is to make important relationships explicit enough that most checks can stay narrow.&lt;/p&gt;
&lt;p&gt;Start with the promise. In the retry example, that is not &amp;ldquo;the expiration worker ran.&amp;rdquo; It is &amp;ldquo;a permitted retry must not repeat completed work.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Name the assumptions that support it, then give the relationship a check. A test can complete a request, advance a controlled clock beyond the proposed retention window, retry within the client&amp;rsquo;s allowed window, and verify that the work is not repeated. A configuration check can reject incompatible windows earlier.&lt;/p&gt;
&lt;p&gt;Once the relationship is explicit, we do not have to rediscover it in every review.&lt;/p&gt;
&lt;p&gt;The harder work is finding relationships we have not represented yet. That is where I still want people and AI reasoning across the changed boundary: which promises depend on this decision, which earlier conclusions may no longer hold, and who can authorize a revision?&lt;/p&gt;
&lt;p&gt;Every-pass assessment does not mean exhaustive re-proving. The depth of investigation should follow the consequences of the change, not just the size of its diff.&lt;/p&gt;
&lt;p&gt;If every small change genuinely affects everything, Harmony is not the root-cause fix. The boundaries probably need to change.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="the-organizational-version"&gt;The organizational version&lt;/h2&gt;
&lt;p&gt;The same failure appears in organizations.&lt;/p&gt;
&lt;p&gt;Suppose a company wants teams to own outcomes but retains central approval for every consequential decision. Each manager can follow the process correctly. The accountability promise and authority model still do not fit together.&lt;/p&gt;
&lt;p&gt;Or suppose a company promises faster delivery while adding review stages whose waiting time is excluded from the delivery target.&lt;/p&gt;
&lt;p&gt;The question is the same as in the retry example: what has to remain true elsewhere for this local rule to work?&lt;/p&gt;
&lt;p&gt;Local autonomy is more useful when teams know which promises they are free to change and which ones other teams rely on. Decomposition should reduce unnecessary coordination. It should not make necessary coordination ownerless.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="preserve-the-whole"&gt;Preserve the whole&lt;/h2&gt;
&lt;p&gt;Harmony starts as a property of a Socrates specification. The broader rule I would add to my working version of the Unix philosophy is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do one thing well. Compose through clear interfaces. Preserve the coherence of the whole as the parts change.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A new answer can reopen an old conclusion. A locally correct change can invalidate a neighboring promise. A component can remain untouched while the reasoning that justified it disappears.&lt;/p&gt;
&lt;p&gt;The useful discipline is to make those relationships visible enough that stable ones become checks and unstable ones remain subjects for judgment.&lt;/p&gt;
&lt;p&gt;Close the loop to detect whether the system worked. Use Harmony to keep its parts from pursuing incompatible definitions of success.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;My &lt;a href="https://github.com/lanej/dotfiles/blob/74f56988ad1fa6debf3702c8b848e352e063761f/claude/commands/socrates.md"&gt;Socrates instructions&lt;/a&gt;, particularly the purpose, Harmony commandment, Commandment Scoring, and freeze/reopen semantics. These specify intended behavior; they do not themselves enforce every requirement.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref2:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref3:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;M. D. McIlroy, E. N. Pinson, and B. A. Tague, &lt;em&gt;UNIX Time-Sharing System: Foreword&lt;/em&gt;, Bell System Technical Journal 57(6), 1978, especially the Style section. &lt;a href="https://www.tuhs.org/Archive/Documentation/Papers/BSTJ/bstj57-6-1899.pdf"&gt;Original paper&lt;/a&gt;; &lt;a href="https://danluu.com/mcilroy-unix/"&gt;HTML transcription&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;Luca de Alfaro and Thomas A. Henzinger, &lt;em&gt;Interface Automata&lt;/em&gt;, ESEC/FSE 2001, pp. 109–120. &lt;a href="https://doi.org/10.1145/503209.503226"&gt;Publication&lt;/a&gt;; &lt;a href="https://research-explorer.ista.ac.at/record/4622"&gt;author-institution record and abstract&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;Jon Doyle, &lt;em&gt;A Truth Maintenance System&lt;/em&gt;, Artificial Intelligence 12(3), 1979, pp. 231–272. &lt;a href="https://doi.org/10.1016/0004-3702(79)90008-0"&gt;Publication and abstract&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;Bashar Nuseibeh, Steve Easterbrook, and Alessandra Russo, &lt;em&gt;Leveraging Inconsistency in Software Development&lt;/em&gt;, IEEE Computer 33(4), 2000, pp. 24–29. &lt;a href="https://doi.org/10.1109/2.839317"&gt;Publication&lt;/a&gt;; &lt;a href="https://www.cs.toronto.edu/~sme/papers/2000/IEEEComputer2000.pdf"&gt;author-hosted paper&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;My &lt;a href="https://github.com/lanej/dotfiles/blob/74f56988ad1fa6debf3702c8b848e352e063761f/claude/commands/verify.md"&gt;verification instructions&lt;/a&gt;, Step 5: Harmony Cadence and Deferral.&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7"&gt;
&lt;p&gt;&lt;a href="https://github.com/lanej/dotfiles/commit/6d8710ec4151ddfc67b2995c87273fc2513ff260"&gt;Add Harmony and per-commandment confidence scoring&lt;/a&gt;, September 3, 2026.&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item><item><title>Close the Loop</title><link>https://lanej.io/writing/close-the-loop/</link><guid isPermaLink="true">https://lanej.io/writing/close-the-loop/</guid><pubDate>Sun, 06 Sep 2026 00:00:00 -0700</pubDate><description>What control theory and Unix taught me about building with AI</description><content:encoded>&lt;p&gt;Most failures I see in AI-assisted engineering are not failures of intelligence. They are failures of feedback.&lt;/p&gt;
&lt;p&gt;A model can reason well about code, write a plausible implementation, run some checks, and confidently say the task is finished.&lt;/p&gt;
&lt;p&gt;None of that means the thing actually works.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What signal tells the model that reality moved toward the state I actually wanted?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is the difference between an open-loop system and a closed-loop one. Once I started thinking about AI this way, a lot of my tooling changed.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="open-loop-ai"&gt;Open-loop AI&lt;/h2&gt;
&lt;p&gt;The naive pattern is simple: give the model a task, let it reason, and let it produce an artifact. Then the model looks at what it produced and effectively asks itself whether it seems right.&lt;/p&gt;
&lt;p&gt;A more capable model improves the odds. A better prompt may improve them again. Neither creates a return path from reality.&lt;/p&gt;
&lt;p&gt;A closed loop does. The model acts. The environment changes. Something measures the result. That evidence comes back, and the next action can respond to it.&lt;/p&gt;
&lt;figure class="essay-diagram" data-essay-diagram="feedback-loop" aria-labelledby="feedback-loop-caption"&gt;
&lt;div class="loop-comparison"&gt;
&lt;section class="diagram-panel" aria-label="Open loop"&gt;
&lt;p class="diagram-label"&gt;Open loop&lt;/p&gt;&lt;p class="diagram-description"&gt;Plausible, but unverified.&lt;/p&gt;
&lt;div class="flow-row"&gt;&lt;span class="flow-node"&gt;Intent&lt;/span&gt;&lt;span class="flow-arrow" aria-hidden="true"&gt;→&lt;/span&gt;&lt;span class="flow-node"&gt;AI&lt;/span&gt;&lt;span class="flow-arrow" aria-hidden="true"&gt;→&lt;/span&gt;&lt;span class="flow-node"&gt;Output&lt;/span&gt;&lt;/div&gt;
&lt;p class="open-loop-note"&gt;No return path from reality.&lt;/p&gt;
&lt;/section&gt;
&lt;section class="diagram-panel closed-loop" aria-label="Closed loop"&gt;
&lt;p class="diagram-label"&gt;Closed loop&lt;/p&gt;&lt;p class="diagram-description"&gt;Action informed by evidence.&lt;/p&gt;
&lt;p class="loop-intent"&gt;Intent &lt;span aria-hidden="true"&gt;↓&lt;/span&gt;&lt;/p&gt;
&lt;div class="flow-row"&gt;&lt;span class="flow-node flow-node-accent"&gt;AI&lt;/span&gt;&lt;span class="flow-arrow" aria-hidden="true"&gt;→&lt;/span&gt;&lt;span class="flow-node"&gt;Action&lt;/span&gt;&lt;span class="flow-arrow" aria-hidden="true"&gt;→&lt;/span&gt;&lt;span class="flow-node"&gt;Environment&lt;/span&gt;&lt;/div&gt;
&lt;div class="feedback-return"&gt;&lt;span class="return-arrow" aria-hidden="true"&gt;↑&lt;/span&gt;&lt;span class="feedback-label"&gt;Evidence &lt;span aria-hidden="true"&gt;←&lt;/span&gt; Verification&lt;/span&gt;&lt;span class="return-arrow" aria-hidden="true"&gt;↓&lt;/span&gt;&lt;/div&gt;
&lt;p class="loop-note"&gt;Observe the result. Adjust the next action.&lt;/p&gt;
&lt;/section&gt;
&lt;/div&gt;
&lt;figcaption id="feedback-loop-caption"&gt;&lt;span&gt;Figure 1.&lt;/span&gt; The difference is not a better prompt. It is a return path from reality.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Claude Code itself works roughly this way: gather context, act, verify, repeat. Anthropic&amp;rsquo;s broader agent guidance makes the same point about obtaining ground truth from the environment during execution.&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The engineering question is what counts as ground truth for the requirement at hand.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="verify-where-the-requirement-lives"&gt;Verify where the requirement lives&lt;/h2&gt;
&lt;p&gt;I recently rediscovered this while rebuilding this website.&lt;/p&gt;
&lt;p&gt;The agent changed the source and committed it. The static-site build passed. The deployment completed.&lt;/p&gt;
&lt;p&gt;The image on the actual mobile site was broken.&lt;/p&gt;
&lt;p&gt;The uploaded image was corrupted, but none of the intermediate checks looked at the user-visible result. They established that source could build and deploy, then those successes were treated as evidence for a different claim: that the page worked.&lt;/p&gt;
&lt;p&gt;The requirement did not live in Hugo. It was that a person opening the site on a phone should see the right page.&lt;/p&gt;
&lt;p&gt;So verification had to happen on the deployed domain, in a browser, at the relevant viewport.&lt;/p&gt;
&lt;p&gt;That leads to a rule I use aggressively now: &lt;strong&gt;verify at the layer where the requirement exists.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If the requirement is visual, inspect the rendering. If it is an API contract, exercise the API. If it is a deployed service, observe the deployed service. If it is a data pipeline, check the resulting data.&lt;/p&gt;
&lt;p&gt;Intermediate checks are useful. They establish narrower claims.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="design-the-feedback-loop-before-the-implementation"&gt;Design the feedback loop before the implementation&lt;/h2&gt;
&lt;p&gt;This changed how I think about specification.&lt;/p&gt;
&lt;p&gt;Before writing code, I increasingly want to know what done means, what could create a false green, what signal we can observe while work is underway, how expensive that signal is, and what fallback exists when there is no cheap automated check.&lt;/p&gt;
&lt;p&gt;A final acceptance test tells you whether you arrived. A feedback loop tells you whether you are still driving in the right direction.&lt;/p&gt;
&lt;p&gt;I eventually made this explicit in my Socrates tooling. Earlier versions concentrated on end-state validation. Later versions required a &lt;strong&gt;Feedback Loop Design&lt;/strong&gt;: a signal, its cost and cadence, and a fallback when no fast automated check exists.&lt;sup id="fnref:2"&gt;&lt;a href="#fn:2" class="footnote-ref" role="doc-noteref"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;That change came from watching execution discover too late that it had no useful way to tell whether it was making progress.&lt;/p&gt;
&lt;p&gt;The verification path is part of the design.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="a-green-signal-you-have-not-tried-to-break-is-weak-evidence"&gt;A green signal you have not tried to break is weak evidence&lt;/h2&gt;
&lt;p&gt;Tests are the obvious feedback mechanism for code. But a test harness can itself be wrong.&lt;/p&gt;
&lt;p&gt;A selector can match the wrong element. A mock can hide a disconnected integration. A regression test can be green because it was never wired into the suite.&lt;/p&gt;
&lt;p&gt;For a new or uncertain harness, I want to deliberately break the relevant behavior, confirm the signal turns red, restore the implementation, and confirm green.&lt;sup id="fnref:3"&gt;&lt;a href="#fn:3" class="footnote-ref" role="doc-noteref"&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The point is not ritualistic TDD. It is to demonstrate that the verifier can detect the failure it claims to detect.&lt;/p&gt;
&lt;p&gt;The same principle applies outside tests. If a browser check is supposed to catch horizontal overflow, create overflow and make sure it catches it. If a policy gate claims to prevent a class of writes, try the prohibited write in an isolated environment.&lt;/p&gt;
&lt;p&gt;A signal is useful only if it discriminates between success and failure.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="use-ai-to-discover-the-process"&gt;Use AI to discover the process&lt;/h2&gt;
&lt;p&gt;There is a recurring pattern in my workflow.&lt;/p&gt;
&lt;p&gt;At first, the process exists only as conversation. I tell Claude to inspect the rendered output rather than trust the build.&lt;/p&gt;
&lt;p&gt;The next time, I say it again. Eventually I encode the procedure in a skill. If the procedure becomes stable and mechanical enough, I stop asking AI to perform that part at all.&lt;/p&gt;
&lt;figure class="essay-diagram" data-essay-diagram="progressive-formalization" aria-labelledby="formalization-caption"&gt;
&lt;div class="formalization-panel"&gt;
&lt;p class="diagram-label"&gt;Progressive formalization&lt;/p&gt;&lt;p class="diagram-description"&gt;As uncertainty falls, move behavior from language into software.&lt;/p&gt;
&lt;ol class="formalization-steps"&gt;
&lt;li&gt;&lt;span class="flow-node"&gt;&lt;strong&gt;Prompt&lt;/strong&gt;&lt;span&gt;Discover behavior&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Flexible. Good for exploration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="flow-node"&gt;&lt;strong&gt;Repeated correction&lt;/strong&gt;&lt;span&gt;Identify patterns&lt;/span&gt;&lt;/span&gt;&lt;p&gt;The same feedback, again and again.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="flow-node"&gt;&lt;strong&gt;Skill&lt;/strong&gt;&lt;span&gt;Encode procedure&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Reusable, with judgment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class="flow-node flow-node-accent"&gt;&lt;strong&gt;Program / hook&lt;/strong&gt;&lt;span&gt;Enforce the check&lt;/span&gt;&lt;/span&gt;&lt;p&gt;Fast, consistent, mechanical.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;figcaption id="formalization-caption"&gt;&lt;span&gt;Figure 2.&lt;/span&gt; Every repeated correction is a candidate for compilation—not an instruction to automate every judgment.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I think of this as &lt;strong&gt;progressive formalization&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Natural language is useful while we are still learning the problem. Software becomes preferable once the behavior is understood well enough to encode.&lt;/p&gt;
&lt;p&gt;Every repeated correction is therefore a candidate for compilation. Not every correction should become code; some expose a misunderstood goal. But if I keep reminding the model to perform the same mechanically checkable action, I should ask whether I am fixing the wrong layer.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="unix-has-something-to-say-about-this"&gt;Unix has something to say about this&lt;/h2&gt;
&lt;p&gt;There is a temptation with AI to construct increasingly capable monoliths: more tools, more context, more rules, more responsibility concentrated in the agent.&lt;/p&gt;
&lt;p&gt;That is not how I generally like to build software.&lt;/p&gt;
&lt;p&gt;The Unix instinct is to decompose: narrow jobs, explicit interfaces, specialized tools, inspectable behavior. My own Constitution for Claude tooling carries that forward.&lt;sup id="fnref:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;So I increasingly put formatters, validators, tests, browser checks, and policy enforcement outside the model&amp;rsquo;s reasoning. The model calls those tools, reads their results, and handles the parts they cannot settle.&lt;/p&gt;
&lt;p&gt;The interesting direction is not necessarily a smarter monolith. It is carving deterministic pieces out of the agent until the model is concentrating on work that genuinely requires judgment.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="skills-are-for-procedures-programs-are-for-invariants"&gt;Skills are for procedures. Programs are for invariants.&lt;/h2&gt;
&lt;p&gt;A skill is a good place for a procedure that still requires reasoning: investigate the codebase, challenge assumptions, inspect several sources, decide which validation strategy applies, and adapt based on what you find.&lt;sup id="fnref:5"&gt;&lt;a href="#fn:5" class="footnote-ref" role="doc-noteref"&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;But there is a boundary.&lt;/p&gt;
&lt;p&gt;If a skill says “always run the formatter,” why should that remain a reasoning task? If it says “never write to these paths,” why should that depend on remembering prose?&lt;/p&gt;
&lt;p&gt;The table maps each concern to the mechanism I use.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concern&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Durable context&lt;/td&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reusable reasoning&lt;/td&gt;
&lt;td&gt;Skill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contextual judgment&lt;/td&gt;
&lt;td&gt;AI or a person&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hard policy&lt;/td&gt;
&lt;td&gt;Enforced permissions, hooks, or CI gates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mechanical correctness&lt;/td&gt;
&lt;td&gt;Test or program&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Claude&amp;rsquo;s documentation makes a useful distinction here too: instructions such as &lt;code&gt;CLAUDE.md&lt;/code&gt; are context, while hooks run at defined lifecycle events instead of depending on the model to remember to invoke them.&lt;sup id="fnref:6"&gt;&lt;a href="#fn:6" class="footnote-ref" role="doc-noteref"&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;A hook is not automatically a security boundary, and code is not automatically correct. The useful distinction is whether compliance still depends on remembering an instruction at the right moment.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="when-wording-stops-being-the-bottleneck"&gt;When wording stops being the bottleneck&lt;/h2&gt;
&lt;p&gt;I learned this one empirically.&lt;/p&gt;
&lt;p&gt;I had a rule that forked agents should not write files under certain circumstances. The rule was clear. An agent violated it.&lt;/p&gt;
&lt;p&gt;I strengthened the instruction. It happened again. I documented the failure. It happened again, including immediately after an agent had read the history explaining that exact failure.&lt;sup id="fnref:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;At that point the wording was no longer the useful place to invest. The boundary belonged in the harness.&lt;/p&gt;
&lt;p&gt;This is a systems-design lesson that predates AI. Policy and mechanism are different things. If correctness requires a model to remember an instruction at the right time, what you have is a preference, not an invariant.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="the-workers-self-report-is-not-verification"&gt;The worker&amp;rsquo;s self-report is not verification&lt;/h2&gt;
&lt;p&gt;One of my newer tools makes the distinction explicit.&lt;/p&gt;
&lt;p&gt;I have a small bug-and-feature dispatcher for a scoped set of repositories. An AI worker receives the task, investigates it, writes the change, and adds a test.&lt;/p&gt;
&lt;p&gt;But its claim that it succeeded is not evidence for the merge decision.&lt;/p&gt;
&lt;p&gt;A separate script inspects the worktree. It reruns the test suite, checks whether the diff includes a test file, and flags changes to sensitive paths. Independent code review remains a judgment step. The dispatcher combines that review with the mechanical results instead of trusting the worker&amp;rsquo;s completion message.&lt;sup id="fnref:8"&gt;&lt;a href="#fn:8" class="footnote-ref" role="doc-noteref"&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The current checks are useful but not omniscient. Touching a test file does not prove meaningful coverage, and a passing suite does not prove the tests measure the right requirement.&lt;sup id="fnref:9"&gt;&lt;a href="#fn:9" class="footnote-ref" role="doc-noteref"&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;That boundary is the point: conventional software obtains observations that conventional software can obtain consistently; the model handles interpretation and judgment around them.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="but-dont-mechanize-judgment"&gt;But don&amp;rsquo;t mechanize judgment&lt;/h2&gt;
&lt;p&gt;There is an opposite failure mode.&lt;/p&gt;
&lt;p&gt;At one point I added a hard gate requiring an independent high-capability model to critique every plan before Claude could exit plan mode.&lt;/p&gt;
&lt;p&gt;It also fired for small, obvious, low-risk plans where the second review added little. I removed the universal gate and made additional critique contextual instead.&lt;sup id="fnref1:7"&gt;&lt;a href="#fn:7" class="footnote-ref" role="doc-noteref"&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The lesson is not “turn everything into hooks.” Mechanize invariants. Preserve judgment for decisions that depend on context, risk, ambiguity, or competing goals.&lt;/p&gt;
&lt;!--essay-chapter--&gt;&lt;h2 id="two-loops"&gt;Two loops&lt;/h2&gt;
&lt;p&gt;There are really two timescales here.&lt;/p&gt;
&lt;p&gt;The execution loop is &lt;strong&gt;act → observe → correct → verify&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The learning loop is &lt;strong&gt;failure → reflection → lesson → skill, rule, or mechanism → future behavior&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;My tooling has gradually accumulated both. Incidents become lessons. Repeated lessons become operating rules. Repeated procedures become skills. Mechanically checkable boundaries become candidates for enforcement.&lt;sup id="fnref1:4"&gt;&lt;a href="#fn:4" class="footnote-ref" role="doc-noteref"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;That is the part of AI-assisted engineering I find most interesting. A model can help discover which parts of our own reasoning should eventually stop being model work.&lt;/p&gt;
&lt;p&gt;When I build an AI-assisted workflow now, I want to know the desired state, the observation that tells us whether we are getting closer, what could create a false green, and which parts of the procedure still require judgment.&lt;/p&gt;
&lt;p&gt;Then I want the repeated mechanical parts to migrate outward into ordinary software.&lt;/p&gt;
&lt;p&gt;The goal is not an AI that never makes mistakes. It is a system where mistakes become observations, observations improve the process, and repeated process eventually becomes mechanism.&lt;/p&gt;
&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Anthropic, &lt;a href="https://code.claude.com/docs/en/how-claude-code-works#the-agentic-loop"&gt;How Claude Code works&lt;/a&gt; and &lt;a href="https://www.anthropic.com/engineering/building-effective-agents"&gt;Building effective agents&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:2"&gt;
&lt;p&gt;&lt;a href="https://github.com/lanej/dotfiles/commit/ec94ec4159c9e7ea6fa04fba37d94f342515128c"&gt;Add in-progress feedback-loop design to the Socrates lifecycle&lt;/a&gt;, September 1, 2026.&amp;#160;&lt;a href="#fnref:2" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:3"&gt;
&lt;p&gt;My &lt;a href="https://github.com/lanej/dotfiles/blob/74f56988ad1fa6debf3702c8b848e352e063761f/claude/skills/methodology/SKILL.md"&gt;methodology skill&lt;/a&gt;, particularly Feedback Loop Design and harness verification.&amp;#160;&lt;a href="#fnref:3" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:4"&gt;
&lt;p&gt;My &lt;a href="https://github.com/lanej/dotfiles/blob/74f56988ad1fa6debf3702c8b848e352e063761f/claude/CONSTITUTION.md"&gt;tooling Constitution&lt;/a&gt;, particularly Root Cause and Technical Integrity, Unix Philosophy, and the distinction between durable principles and mechanisms.&amp;#160;&lt;a href="#fnref:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:4" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:5"&gt;
&lt;p&gt;Anthropic, &lt;a href="https://code.claude.com/docs/en/skills"&gt;Extend Claude with skills&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:5" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:6"&gt;
&lt;p&gt;Anthropic, &lt;a href="https://code.claude.com/docs/en/memory"&gt;How Claude remembers your project&lt;/a&gt; and &lt;a href="https://code.claude.com/docs/en/hooks-guide"&gt;Automate actions with hooks&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:6" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:7"&gt;
&lt;p&gt;My &lt;a href="https://github.com/lanej/dotfiles/blob/74f56988ad1fa6debf3702c8b848e352e063761f/claude/CLAUDE.md"&gt;operating rules&lt;/a&gt;, including the recorded no-write failures and removal of the universal plan-critique gate.&amp;#160;&lt;a href="#fnref:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&amp;#160;&lt;a href="#fnref1:7" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:8"&gt;
&lt;p&gt;The &lt;a href="https://github.com/lanej/dotfiles/blob/74f56988ad1fa6debf3702c8b848e352e063761f/claude/skills/bugfix-dispatcher/SKILL.md"&gt;bug-and-feature dispatcher protocol&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:8" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:9"&gt;
&lt;p&gt;The corresponding &lt;a href="https://github.com/lanej/dotfiles/blob/74f56988ad1fa6debf3702c8b848e352e063761f/bin/bugfix-worker"&gt;mechanical worker script&lt;/a&gt;.&amp;#160;&lt;a href="#fnref:9" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded></item></channel></rss>