<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>Posts Tagged "article" on Alex Leighton's Blog</title>
  <id>https://alexleighton.com/posts/tags/article-tag-feed.xml</id>
  <link href="https://alexleighton.com/posts/tags/article-tag-feed.xml" rel="self" />
  <link href="https://alexleighton.com/posts/tags/article.html" />
  <updated>2026-04-20T00:41:38.993470907Z</updated>
  <author>
    <name>Alex Leighton</name>
    <uri>https://alexleighton.com/</uri>
  </author>
  <icon>https://alexleighton.com/static/icon-dino.png</icon>
  <logo>https://alexleighton.com/static/icon-dino.png</logo>
  
  <entry>
    <title>KBS: Fast Forward</title>
    <id>https://alexleighton.com/posts/2026-02-28-kbs-fast-forward.html</id>
    <link href="https://alexleighton.com/posts/2026-02-28-kbs-fast-forward.html" />
    <published>2026-03-01T03:45:00Z</published>
    <updated>2026-03-01T03:45:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Code generation on cruise control.</p><p>Published on <span title="2026-03-01T03:45:00Z">2026-03-01</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Code generation on cruise control.</h3><p>Published on <span title="2026-03-01T03:45:00Z">2026-03-01</span><br>Tags: article, llm, ocaml, python, software-eng, software-eng-auto</p><p>On today's episode: a lot of code. The previous work prepared the project codebase to guide agents in generating good quality code, which is what we did.</p>
<h2>Update, Resolve, Archive Commands</h2>
<p>After the <code>Kb_service</code> module was broken apart, the coding agent easily generated full verticals for update, resolve, and archive commands. The process I'm following:</p>
<ul>
<li>Work with the agent to peel off a chunk of functionality from <a href="https://github.com/alexleighton/knowledge-bases/blob/0eb55844acc47bb847f6d8063a9bc1b4c7689e4b/docs/product-requirements.md"><code>docs/product-requirements.md</code></a>.</li>
<li>Then write a <a href="https://github.com/alexleighton/knowledge-bases/blob/0eb55844acc47bb847f6d8063a9bc1b4c7689e4b/prompts/activities/implementation-plan.md"><code>prompts/activities/implementation-plan.md</code></a> for building the functionality.</li>
<li>After the code is generated, I review the code, as well as the agent (<a href="https://github.com/alexleighton/knowledge-bases/blob/0eb55844acc47bb847f6d8063a9bc1b4c7689e4b/prompts/activities/code-review.md"><code>prompts/activities/code-review.md</code></a>), and apply changes for all issues.</li>
</ul>
<p>Related commit: <a href="https://github.com/alexleighton/knowledge-bases/commit/0eb55844acc47bb847f6d8063a9bc1b4c7689e4b"><code>0eb5584</code></a> — feat: add update, resolve, and archive commands</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-28-kbs-fast-forward.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: List and Show</title>
    <id>https://alexleighton.com/posts/2026-02-25-kbs-list-and-show.html</id>
    <link href="https://alexleighton.com/posts/2026-02-25-kbs-list-and-show.html" />
    <published>2026-02-26T05:00:00Z</published>
    <updated>2026-02-26T05:00:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Code generation picks up speed.</p><p>Published on <span title="2026-02-26T05:00:00Z">2026-02-26</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Code generation picks up speed.</h3><p>Published on <span title="2026-02-26T05:00:00Z">2026-02-26</span><br>Tags: article, llm, ocaml, software-eng, software-eng-auto</p><p>Today's log consists mostly of code generation. We've laid enough foundation that new functionality is easily produced.</p>
<h2>List Functionality</h2>
<p>The functionality for <code>bs list</code> is well defined after the work for the <a href="../../../posts/2026-02-24-kbs-nesting-and-ideation.html">previous dev log</a>. I think the experiment of directing the agents from the requirements document rather than my own intuition of what to tackle was successful, though perhaps only at the scale of a project like Knowledge Bases. The coding agent was able to select a reasonable chunk of functionality to peel off and turn into an implementation plan, with a different agent generating the implementation.</p>
<h2>"Flaky" Tests</h2><p>...<br><a href="https://alexleighton.com/posts/2026-02-25-kbs-list-and-show.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: Nesting and Ideation</title>
    <id>https://alexleighton.com/posts/2026-02-24-kbs-nesting-and-ideation.html</id>
    <link href="https://alexleighton.com/posts/2026-02-24-kbs-nesting-and-ideation.html" />
    <published>2026-02-24T14:30:00Z</published>
    <updated>2026-02-24T14:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>More scaffolding before future work.</p><p>Published on <span title="2026-02-24T14:30:00Z">2026-02-24</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>More scaffolding before future work.</h3><p>Published on <span title="2026-02-24T14:30:00Z">2026-02-24</span><br>Tags: article, llm, ocaml, software-eng, software-eng-auto</p><p>Today's changes follow on from the previous post's "next steps": nesting and ideation.</p>
<h2>Nesting</h2>
<p>I worked with the agent to find code with deep nesting, decide how to flatten it, and generalize the approach into suggestions for a <a href="https://github.com/alexleighton/knowledge-bases/blob/faf049e4a4fecaf8a04552e505a178ed29c2299f/docs/lib/principles.md#3-low-nesting-depth">nesting principle</a>. We then applied that principle across the codebase, and I think we were successful as the diff in <a href="https://github.com/alexleighton/knowledge-bases/commit/a05f2ea7eaa69805e88e395082dbfe57d29198d2">the refactor commit</a> is noticeably flatter.</p>
<blockquote>
<p><strong>4. Nesting Depth</strong></p>
<p>Keep expressions nested at most two or three levels deep. Deeply nested code
is hard to follow because the reader must hold every enclosing context in their
head at once. When nesting grows, treat it as a signal that the code should be
restructured.</p>
<p>Approaches for reducing nesting:</p>
<ul>
<li>Use monadic result operators (<code>let*</code>, <code>let+</code>). ...</li>
<li>Extract resource-management wrappers. ...</li>
<li>Consolidate error mapping into named functions. ...</li>
<li>Factor repeated control-flow shapes into helpers. ...</li>
</ul>
</blockquote><p>...<br><a href="https://alexleighton.com/posts/2026-02-24-kbs-nesting-and-ideation.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: Adding Todos</title>
    <id>https://alexleighton.com/posts/2026-02-19-kbs-adding-todos.html</id>
    <link href="https://alexleighton.com/posts/2026-02-19-kbs-adding-todos.html" />
    <published>2026-02-20T03:45:00Z</published>
    <updated>2026-02-20T03:45:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>More guidance, and thoughts on automatic review.</p><p>Published on <span title="2026-02-20T03:45:00Z">2026-02-20</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>More guidance, and thoughts on automatic review.</h3><p>Published on <span title="2026-02-20T03:45:00Z">2026-02-20</span><br>Tags: article, code-review, llm, ocaml, software-eng, software-eng-auto</p><p>Today's changes build on the previous commit's unpacking of <code>Todo</code>, making a repository for <code>Todo</code>s, and hooking it up to the command line to provide <code>bs add todo ...</code>.</p>
<h2>More Guidance</h2>
<p>The implementation plan forgot to add a task for integration tests, which resulted in a <a href="https://github.com/alexleighton/knowledge-bases/blob/412117ae6940be69a6122a8a1d048f73ba0fa8de/docs/bin/principles.md?plain=1#L17-L40"><code>bin</code> principle</a> saying changes to <code>bin</code>, where we're only keeping command-line parsing and top-level orchestration, should always be accompanied by an integration test. I also had the agent put together an <a href="https://github.com/alexleighton/knowledge-bases/blob/412117ae6940be69a6122a8a1d048f73ba0fa8de/docs/test-integration/architecture.md">architecture document</a> guiding the structure of integration tests and their purpose.</p>
<p>In the hopes of keeping file sizes down, I added a line length principle to <a href="https://github.com/alexleighton/knowledge-bases/blob/412117ae6940be69a6122a8a1d048f73ba0fa8de/docs/bin/principles.md?plain=1#L52-L57"><code>bin</code></a> and <a href="https://github.com/alexleighton/knowledge-bases/blob/412117ae6940be69a6122a8a1d048f73ba0fa8de/docs/lib/principles.md?plain=1#L41-L46"><code>lib</code></a>. I'm not sure about these principles, because I think this can be automated as a lint. I will keep these in mind and improve the linting situation when I get another structural/syntactic principle that can be automated.</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-19-kbs-adding-todos.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: Unpacking Todo</title>
    <id>https://alexleighton.com/posts/2026-02-18-kbs-unpacking-todo.html</id>
    <link href="https://alexleighton.com/posts/2026-02-18-kbs-unpacking-todo.html" />
    <published>2026-02-19T04:15:00Z</published>
    <updated>2026-02-19T04:15:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Guidance, prompts, and TDD.</p><p>Published on <span title="2026-02-19T04:15:00Z">2026-02-19</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Guidance, prompts, and TDD.</h3><p>Published on <span title="2026-02-19T04:15:00Z">2026-02-19</span><br>Tags: article, code-review, llm, ocaml, software-eng, software-eng-auto</p><p>Today's change to Knowledge Bases is addressing my unhappiness at the beginning of the month: <a href="../../../posts/2026-02-01-storage-for-knowledge-bases.html">"Data modeling"</a>. I've returned to the work of <a href="https://github.com/alexleighton/knowledge-bases/blob/d5fcf06481d710a6ecf35a0b874474e96d016dc5/lib/data/todo.ml#L19-L25">unpacking <code>Note</code> into <code>Todo</code></a>, to make it easier to control the TypeID prefix, and prepare for making a <code>Todo</code> repository.</p>
<h2>Revisiting Guidance Docs</h2>
<p>A handy thing about coding agents: they can make such a wide-ranging change with minimal effort (see the number of changed files in the commit). Additionally, the coding principles guidance doc paid for itself — agent code review noted the duplicated validation logic for title and content now in both <code>Note</code> and <code>Todo</code> and recommended deduplication. I redirected it to encapsulate the validation into new types, a favorite software engineering technique of mine (see <a href="../../../posts/2025-10-24-note-identifiers-and-tests.html">"Aside: Correct Construction"</a>), as well as <a href="https://github.com/alexleighton/knowledge-bases/blob/d5fcf06481d710a6ecf35a0b874474e96d016dc5/docs/lib/principles.md?plain=1#L15-L26">adjusted the guidance</a>.</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-18-kbs-unpacking-todo.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>KBS: Going Automatic</title>
    <id>https://alexleighton.com/posts/2026-02-17-kbs-going-automatic.html</id>
    <link href="https://alexleighton.com/posts/2026-02-17-kbs-going-automatic.html" />
    <published>2026-02-18T05:30:00Z</published>
    <updated>2026-02-18T05:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Exploring a hands-off agent-driven workflow.</p><p>Published on <span title="2026-02-18T05:30:00Z">2026-02-18</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Exploring a hands-off agent-driven workflow.</h3><p>Published on <span title="2026-02-18T05:30:00Z">2026-02-18</span><br>Tags: article, git, llm, ocaml, software-eng, software-eng-auto</p><p>I've decided to use this project as a testbed for automatic development, to explore the kinds of techniques described in recent results [<a href="../../../posts/2026-02-12-new-software-engineering-modes.html">1</a>] [<a href="../../../posts/2026-02-14-more-software-engineering-research.html">2</a>], and to speed up development. I'll be making the vast majority of changes to the codebase via coding agents, exploring what controls are needed to stay hands-off yet maintain code quality.</p>
<h2>Short AGENTS.md</h2>
<p>I've played around with longer <code>AGENTS.md</code> and not seen much value. Agents would ignore pieces, and after a while it felt like simply a waste of context space. I'm keeping <a href="https://github.com/alexleighton/knowledge-bases/blob/223c4ece2550fb1196cec770d97762a66823fcda/AGENTS.md?plain=1"><code>AGENTS.md</code> short</a> this time around, "linking" to where more information can be retrieved, with the hope that brevity keeps the content important.</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-17-kbs-going-automatic.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Storage for Knowledge Bases</title>
    <id>https://alexleighton.com/posts/2026-02-01-storage-for-knowledge-bases.html</id>
    <link href="https://alexleighton.com/posts/2026-02-01-storage-for-knowledge-bases.html" />
    <published>2026-02-03T05:30:00Z</published>
    <updated>2026-02-03T05:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Progress, regrets, and motivation working with SQLite.</p><p>Published on <span title="2026-02-03T05:30:00Z">2026-02-03</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Progress, regrets, and motivation working with SQLite.</h3><p>Published on <span title="2026-02-03T05:30:00Z">2026-02-03</span><br>Tags: article, database, git, ocaml, software-eng</p><p>Today's update is brought to you by my lack of motivation 😆. I decided to work on building out a storage layer for Knowledge Bases objects, and then got burned by lack of interest.</p>
<p>Restating our storage requirements: we need notes, todos, etc to be persisted to disk in a way where git's diff will capably show edits, additions, and deletions, and which allows for easily querying these objects by identifier or by their relation to each other (we want to support parent-child, related-to, etc). To meet those requirements I intend to persist data in two ways. First, in an appropriately-sorted JSON or YAML file, to solve for the git-diff requirement. Second, in a <a href="https://en.wikipedia.org/wiki/SQLite">SQLite</a> database to make it easy to add/edit/delete/query. The program will mirror the SQLite database onto the JSON file unless it's determined to be out of date (i.e. when the git branch is changed), in which case we'll rebuild the database from the JSON file. For now I'm starting with the SQLite db, as that can be useful for purely local todo storage, and we'll bolt-on the ability to synchronize them over git later.</p><p>...<br><a href="https://alexleighton.com/posts/2026-02-01-storage-for-knowledge-bases.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Year in Review: 2025</title>
    <id>https://alexleighton.com/posts/2025-12-31-year-in-review-2025.html</id>
    <link href="https://alexleighton.com/posts/2025-12-31-year-in-review-2025.html" />
    <published>2026-01-01T06:15:00Z</published>
    <updated>2026-01-01T06:15:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Building and blogging on this site the past year.</p><p>Published on <span title="2026-01-01T06:15:00Z">2026-01-01</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Building and blogging on this site the past year.</h3><p>Published on <span title="2026-01-01T06:15:00Z">2026-01-01</span><br>Tags: article, git, meta, ocaml, static-site</p><p>For 2024's New Year's resolution I decided I'd finally build and publish a personal website. That I'd write up my thoughts on the articles I was reading and post them instead of dumping them on friends 😆. In review, I'm happy to say I succeeded.</p>
<p>I wrote and published 164 blog posts over the past year, not counting this post. September was my most prolific month. I initialized the OCaml project that became the static site generator in late January, writing a <a href="../../../posts/2025-02-02-listening-to-the-resonance-between.html">test post</a> at the beginning of February to work out frontmatter parsing, markdown generation, and my custom templating language. The first "real" post came at the end of June, a few days after I bought the domain name.</p><p>...<br><a href="https://alexleighton.com/posts/2025-12-31-year-in-review-2025.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>TypeIDs for Knowledge Bases</title>
    <id>https://alexleighton.com/posts/2025-11-29-typeids-for-knowledge-bases.html</id>
    <link href="https://alexleighton.com/posts/2025-11-29-typeids-for-knowledge-bases.html" />
    <published>2025-11-30T04:00:00Z</published>
    <updated>2025-11-30T04:00:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Data consistency and the primary identifier for content.</p><p>Published on <span title="2025-11-30T04:00:00Z">2025-11-30</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Data consistency and the primary identifier for content.</h3><p>Published on <span title="2025-11-30T04:00:00Z">2025-11-30</span><br>Tags: article, git, ocaml, software-eng</p><h2>TypeID</h2>
<p><a href="https://github.com/jetify-com/typeid">TypeID</a> is a micro-standard combining a number of well-thought-out decisions.</p>
<blockquote>
<p>TypeIDs are a modern, type-safe extension of UUIDv7. Inspired by a similar use of prefixes in Stripe's APIs.</p>
<p>TypeIDs are canonically encoded as lowercase strings consisting of three parts:</p>
<ol>
<li>A type prefix (at most 63 characters in all lowercase snake_case ASCII <code>[a-z_]</code>).</li>
<li>An underscore '_' separator</li>
<li>A 128-bit UUIDv7 encoded as a 26-character string using a modified base32 encoding.</li>
</ol>
</blockquote>
<pre><code class="language-plain">user_2x4y6z8a0b1c2d3e4f5g6h7j8k
└──┘ └────────────────────────┘
type    uuid suffix (base32)
</code></pre>
<p>Most identifiers, barring a specialized context, should include a "type" for the identifier. Interconnected computer systems are always passing around identifiers — for someone holding an identifier in their database it is really valuable to know who that identifier belongs to as well as what the identifier is for. For example in a financial institution handling investments, <code>md_quote_2x4y6z8a0b1c2d3e4f5g6h7j8k</code> can tell the receiver that they're holding a reference to a stock price quote, owned by the market data (<code>md</code>) system. Identifier types give engineers metadata, which can be especially useful when there's a bug in the system — no need to stress whether the integer identifier you're currently holding came from the <code>user</code> table or <code>news</code> table.</p><p>...<br><a href="https://alexleighton.com/posts/2025-11-29-typeids-for-knowledge-bases.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Notes and Todos</title>
    <id>https://alexleighton.com/posts/2025-10-31-notes-and-todos.html</id>
    <link href="https://alexleighton.com/posts/2025-10-31-notes-and-todos.html" />
    <published>2025-11-01T00:00:00Z</published>
    <updated>2025-11-01T00:00:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Small Knowledge Bases update.</p><p>Published on <span title="2025-11-01T00:00:00Z">2025-11-01</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Small Knowledge Bases update.</h3><p>Published on <span title="2025-11-01T00:00:00Z">2025-11-01</span><br>Tags: article, ocaml</p><p>Short update today — the definitions of <code>note</code> and <code>todo</code> types and their basic operations.</p>
<p>My intention is to represent arbitrary content as a <code>note</code>, and represent things to be done with <code>todo</code>. Notes are just an identifier, a title, and some content, while Todos also have a status and eventually relationships. I've left relationships between notes and todos for later. I'm not sure if I want them represented separately or as part of the structures.</p>
<h2>Note</h2>
<pre><code class="language-ocaml">(** Note type and operations.

    A note bundles an [Identifier.t] with a title and content.
*)

(** Abstract type of notes. *)
type t

(** [pp fmt t] prints the note [t] using the formatter [fmt]. *)
val pp : Format.formatter -&gt; t -&gt; unit

(** [show t] returns the same string that {!pp} would print. *)
val show : t -&gt; string

(** [make identifier title content] constructs a note after validating inputs.

    - [title] must be non-empty and at most 100 characters.
    - [content] must be non-empty and at most 10000 characters.

    @raise Invalid_argument if validation fails. *)
val make : Identifier.t -&gt; string -&gt; string -&gt; t

(** [id t] returns the note identifier. *)
val id : t -&gt; Identifier.t

(** [title t] returns the title of the note. *)
val title : t -&gt; string

(** [content t] returns the content of the note. *)
val content : t -&gt; string
</code></pre><p>...<br><a href="https://alexleighton.com/posts/2025-10-31-notes-and-todos.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Note Identifiers and Tests</title>
    <id>https://alexleighton.com/posts/2025-10-24-note-identifiers-and-tests.html</id>
    <link href="https://alexleighton.com/posts/2025-10-24-note-identifiers-and-tests.html" />
    <published>2025-10-25T00:45:00Z</published>
    <updated>2025-10-25T00:45:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Extended discussion on data representation.</p><p>Published on <span title="2025-10-25T00:45:00Z">2025-10-25</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Extended discussion on data representation.</h3><p>Published on <span title="2025-10-25T00:45:00Z">2025-10-25</span><br>Tags: article, llm, ocaml</p><p>My inclination, after getting the hello world project set up in place, is to start defining the major data representations of the domain we're working in. Since I'm documenting the process, and I want to discuss decisions, I'm going to start out pretty slowly — today's update is basically just a type for representing identifiers for "notes" (whatever it is we decide to call the basic content building block).</p>
<h2>Basic Definition and Data Access</h2>
<p>The plan here is to expose an opaque type <code>t</code> for our identifier values (<code>Identifier.t</code>), and be explicit and deliberate about what data is exposed to the rest of the program. I liked how Beads stuck with an identifier format that's human readable, and likely prevalent in LLM training data, so we'll use the same format for our identifier: <code>[a-z]{1,5}-[0-9]+</code> (e.g. <code>kbase-12345</code>). Decomposing that identifier gets us a <code>namespace</code> and <code>raw_id</code>.</p><p>...<br><a href="https://alexleighton.com/posts/2025-10-24-note-identifiers-and-tests.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Starting Knowledge Bases</title>
    <id>https://alexleighton.com/posts/2025-10-22-starting-knowledge-bases.html</id>
    <link href="https://alexleighton.com/posts/2025-10-22-starting-knowledge-bases.html" />
    <published>2025-10-22T13:30:00Z</published>
    <updated>2025-10-22T13:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Writing a coding agent tool in OCaml.</p><p>Published on <span title="2025-10-22T13:30:00Z">2025-10-22</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Writing a coding agent tool in OCaml.</h3><p>Published on <span title="2025-10-22T13:30:00Z">2025-10-22</span><br>Tags: article, git, llm, ocaml</p><p>A couple days ago, <a href="https://en.wikipedia.org/wiki/Steve_Yegge">Steve Yegge</a> <a href="https://steve-yegge.medium.com/beads-for-blobfish-80c7a2977ffa">wrote about a coding agent tool</a> he's been developing called <a href="https://github.com/steveyegge/beads">Beads</a>.</p>
<blockquote>
<p>Beads is a lightweight memory system for coding agents, using a graph-based issue tracker. Four kinds of dependencies work to chain your issues together like beads, making them easy for agents to follow for long distances, and reliably perform complex task streams in the right order.</p>
</blockquote>
<p>I haven't had an opportunity to see if it works well or not, but the feature set seems straightforward to implement and I've been looking for a project to work on which will involve OCaml and publishing to opam. I'll be documenting the development process here 😁.</p><p>...<br><a href="https://alexleighton.com/posts/2025-10-22-starting-knowledge-bases.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Randomart</title>
    <id>https://alexleighton.com/posts/2025-09-05-randomart.html</id>
    <link href="https://alexleighton.com/posts/2025-09-05-randomart.html" />
    <published>2025-09-06T05:15:00Z</published>
    <updated>2025-09-06T05:15:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>SSH key visualization.</p><p>Published on <span title="2025-09-06T05:15:00Z">2025-09-06</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>SSH key visualization.</h3><p>Published on <span title="2025-09-06T05:15:00Z">2025-09-06</span><br>Tags: article, ocaml, security, software-eng</p><p>When using <a href="https://en.wikipedia.org/wiki/OpenSSH">OpenSSH</a>, you may see ASCII art from time to time, like:</p>
<pre><code>+--[ED25519 256]--+
|                 |
|     .           |
|      o          |
|     o o o  .    |
|     .B S oo     |
|     =+^ =...    |
|    oo#o@.o.     |
|    E+.&amp;.=o      |
|    ooo.X=.      |
+----[SHA256]-----+
</code></pre>
<p>This is output<sup><a href="#fn-1" id="ref-1-fn-1" role="doc-noteref" class="fn-label">[1]</a></sup> of the randomart SSH Key visualization algorithm, intended to leverage the user's visual pattern matching to quickly recognize (or not) a remote host key. It's known as the <a href="https://www.jfurness.uk/the-drunken-bishop-algorithm/">Drunken Bishop's algorithm</a>, contributed to the OpenSSH codebase by <a href="https://undeadly.org/cgi?action=article&amp;sid=20080615022750">Alexander von Gernler in 2008</a>.</p>
<blockquote>
<p><a href="https://marc.info/?l=openbsd-cvs&amp;m=121321826818823&amp;w=2"><strong>Alexander von Gernler</strong> on 2008-06-11</a>:</p><p>Introduc[ing] SSH Fingerprint ASCII Visualization, a technique inspired by the graphical hash visualization schemes known as "random art", and by Dan Kaminsky's musings on the subject during a BlackOp talk at the 23C3 in Berlin.</p>
<p>Scientific publication (original paper): "Hash Visualization: a New Technique to improve Real-World Security", Perrig A. and Song D., 1999, International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99)</p></blockquote><p>...<br><a href="https://alexleighton.com/posts/2025-09-05-randomart.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Building Search for this Site</title>
    <id>https://alexleighton.com/posts/2025-08-09-building-search-for-this-site.html</id>
    <link href="https://alexleighton.com/posts/2025-08-09-building-search-for-this-site.html" />
    <published>2025-08-10T05:10:37Z</published>
    <updated>2025-08-10T05:10:37Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Search on a static site.</p><p>Published on <span title="2025-08-10T05:10:37Z">2025-08-10</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Search on a static site.</h3><p>Published on <span title="2025-08-10T05:10:37Z">2025-08-10</span><br>Tags: article, java, javascript, ocaml, static-site</p><p>I like the idea of having search for my blog, to help readers find anything related to a specific topic, or something they'd read in the past. How do I make something as dynamic as search, but statically generated?</p>
<h2>Requirements</h2>
<ul>
<li><strong>The solution has to be small</strong> — part of my purpose in statically generating the site is to make it fast to download, fast to view. Whatever is chosen needs to maintain that vision.</li>
<li><strong>The solution can't introduce too many dependencies</strong> — I really like OCaml as a language, and I used building my personal site as an excuse to work in it. Introducing non-OCaml dependencies has to be done with care, as I don't want to maintain a Rube Goldberg machine for my website.</li>
</ul><p>...<br><a href="https://alexleighton.com/posts/2025-08-09-building-search-for-this-site.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Syntax Highlighting</title>
    <id>https://alexleighton.com/posts/2025-08-06-syntax-highlighting.html</id>
    <link href="https://alexleighton.com/posts/2025-08-06-syntax-highlighting.html" />
    <published>2025-08-06T13:30:00Z</published>
    <updated>2025-08-06T13:30:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>We're not there yet.</p><p>Published on <span title="2025-08-06T13:30:00Z">2025-08-06</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>We're not there yet.</h3><p>Published on <span title="2025-08-06T13:30:00Z">2025-08-06</span><br>Tags: article, css, html, javascript, static-site</p><p>Unfortunately I spoke too soon when I wrote the <a href="../../../posts/2025-07-18-building-this-site.html">Building this Site</a> post. I had a plan in place to use <a href="https://opam.ocaml.org/packages/hilite/"><code>hilite</code></a>, along with TextMate grammars and themes pulled from <a href="https://shiki.style/">Shiki</a> (which in turn gets its grammars and themes from TextMate/VSCode), but it fell through.</p>
<h2>The Plan</h2>
<p>The plan was to grab lightmode and darkmode themes from Shiki's <a href="https://github.com/shikijs/textmate-grammars-themes/tree/main/packages/tm-themes">trove of themes</a>, stripping out any extraneous styles (a lot of text-editor-specific colors are given) to arrive at two sets of colors for pre-determined class names. Shiki works similarly to <code>hilite</code>: during processing it tags portions of the source code with CSS tags derived from the grammars. All of the <a href="https://github.com/shikijs/textmate-grammars-themes/tree/main/packages/tm-grammars">TextMate grammars</a> employed by Shiki use a consistent naming scheme, ensuring themes always line up with the grammars, resulting in colored text. With a little adjustment of the theme CSS tags to account for any differences between Hilite's and Shiki's tagging, I'd have ahead-of-time syntax highlighting, with as many supported languages as VSCode.</p><p>...<br><a href="https://alexleighton.com/posts/2025-08-06-syntax-highlighting.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Multiple Scripts</title>
    <id>https://alexleighton.com/posts/2025-07-25-multiple-scripts.html</id>
    <link href="https://alexleighton.com/posts/2025-07-25-multiple-scripts.html" />
    <published>2025-07-25T23:06:48Z</published>
    <updated>2025-07-25T23:06:48Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>HTML-Browser quirk.</p><p>Published on <span title="2025-07-25T23:06:48Z">2025-07-25</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>HTML-Browser quirk.</h3><p>Published on <span title="2025-07-25T23:06:48Z">2025-07-25</span><br>Tags: article, html, static-site</p><p>I learned recently that web browsers will execute an HTTP request for each <code>&lt;script&gt;</code> tag they find in the document. I hadn't really thought much about it, assuming a kind of declarative interpretation of HTML, where when multiple <code>&lt;script src="foo.js"&gt;&lt;/script&gt;</code> show up in the document, only one would be requested and executed. Turns out my assumption is wrong and the browser will happily request the same script multiple times. It's not much of an issue in practice, on subsequent page loads the browser will hit its local cache for every script load.</p>
<p>I have a number of "builtins", invokable functions, in the site's templating language. For example, <code>date</code> which parses and calculates date formats:</p><p>...<br><a href="https://alexleighton.com/posts/2025-07-25-multiple-scripts.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Building this Site</title>
    <id>https://alexleighton.com/posts/2025-07-18-building-this-site.html</id>
    <link href="https://alexleighton.com/posts/2025-07-18-building-this-site.html" />
    <published>2025-07-18T16:31:00Z</published>
    <updated>2025-07-18T16:31:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Start of a series on building this website.</p><p>Published on <span title="2025-07-18T16:31:00Z">2025-07-18</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Start of a series on building this website.</h3><p>Published on <span title="2025-07-18T16:31:00Z">2025-07-18</span><br>Tags: article, software-eng, static-site</p><p>This website is created with a hand-rolled <a href="https://en.wikipedia.org/wiki/Static_site_generator">static site generator</a>. In this series I'll talk about some of the infrastructure I've built towards making the website.</p>
<h2>Infrastructure</h2>
<p>My static site generator <code>asite</code>, is primarily programmed in <a href="https://ocaml.org/">OCaml</a>, using <a href="https://dune.build/">Dune</a> and <a href="https://opam.ocaml.org/">OPAM</a> for the build system. The templating language used is custom, as is the majority of steps in the site building process. I do use a number of external packages:</p>
<ul>
<li><a href="https://ocaml.org/p/cmarkit/latest">cmarkit</a> — blog posts are written in markdown, <code>asite</code> uses <code>cmarkit</code> to render the markdown into HTML.</li>
<li><a href="https://ocaml.org/p/hilite/latest">hilite</a> — for code syntax highlighting, though this isn't a complete solution, more on this in future posts.</li>
<li><a href="https://opam.ocaml.org/packages/js_of_ocaml/">js_of_ocaml</a>, <a href="https://opam.ocaml.org/packages/search/">search</a> — used in building the <a href="../../../search.html">search page</a>, more on this in the future.</li>
<li><a href="https://ocaml.org/p/markup/latest">markup</a> — when generating rss, <code>markup</code> is used to parse and process a blog post's HTML into just a teaser, to keep the size of the rss file small.</li>
<li><a href="https://ocaml.org/p/subprocess/latest">subprocess</a> — used to invoke <code>esbuild</code> as a step in the build process, more on this in future posts.</li>
<li><a href="https://ocaml.org/p/yaml/latest">yaml</a> — blog posts and other pages have a <a href="https://jekyllrb.com/docs/front-matter/">YAML frontmatter</a> containing "columns" in the "post database".</li>
<li><a href="https://ocaml.org/p/alcotest/latest">alcotest</a>, <a href="https://ocaml.org/p/cmdliner/latest">cmdliner</a>, <a href="https://ocaml.org/p/logs/latest">logs</a>, <a href="https://ocaml.org/p/re/latest">re</a>, <a href="https://ocaml.org/p/timedesc/latest">timedesc</a>, and <a href="https://ocaml.org/p/yojson/latest">yojson</a> — miscellaneous low level utilities used all over the place.</li>
</ul><p>...<br><a href="https://alexleighton.com/posts/2025-07-18-building-this-site.html">Read the full post →</a></p>]]></content>
  </entry>
  
  <entry>
    <title>Conventional Communication</title>
    <id>https://alexleighton.com/posts/2025-06-30-conventional-communication.html</id>
    <link href="https://alexleighton.com/posts/2025-06-30-conventional-communication.html" />
    <published>2025-07-01T00:32:00Z</published>
    <updated>2025-07-01T00:32:00Z</updated>
    <author><name>Alex Leighton</name></author>
    <summary type="html"><![CDATA[<p>Communicating with conventions is still just communication.</p><p>Published on <span title="2025-07-01T00:32:00Z">2025-07-01</span></p>]]></summary>
    <content type="html"><![CDATA[<h3>Communicating with conventions is still just communication.</h3><p>Published on <span title="2025-07-01T00:32:00Z">2025-07-01</span><br>Tags: article, code-review, communication, software-eng</p><p>At my day job I review a lot of other people's work, in the form of code
reviews or design (and other) documents. A few years back a coworker whose
code I was reviewing requested, rather insistently, that I start using
<a href="https://conventionalcomments.org/">conventional comments</a> when doing code
reviews. They also messaged it out to the team, though more as a practice
suggestion and not a proposed change to the team's process.</p>
<p>I internally shrugged the request off, as they were a junior engineer still
working through their personal relationship to feedback — as we all do. I don't
think many people are raised with the education necessary for internally
de-personalizing feedback, analyzing your own behavior, synthesizing the given
feedback with your own understanding of "the world", and thanking the other
person for their gift, regardless of your orientation towards that "gift". It's
complicated stuff and most of us, myself included, take years to adjust our
reactions accordingly.</p><p>...<br><a href="https://alexleighton.com/posts/2025-06-30-conventional-communication.html">Read the full post →</a></p>]]></content>
  </entry>
  
</feed>
