<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="pretty-atom-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>pborenstein.dev</title>
  <subtitle>Taking things apart to see how they work.</subtitle>
  <link href="https://pborenstein.dev/feed/feed.xml" rel="self" />
  <link href="https://pborenstein.dev/" />
  <updated>2026-03-15T01:01:29Z</updated>
  <id>https://pborenstein.dev/</id>
  <author>
    <name>Philip Borenstein</name>
    <email>pborenstein@gmail.com</email>
  </author>
  <entry>
    <title>How Claude codes with Philip</title>
    <link href="https://pborenstein.dev/posts/how-claude-codes-with-philip/" />
    <updated>2026-03-15T01:01:29Z</updated>
    <id>https://pborenstein.dev/posts/how-claude-codes-with-philip/</id>
    <content type="html">
&lt;blockquote&gt;
&lt;p&gt;I wrote &lt;a href=&quot;https://pborenstein.dev//posts/how-i-code-with-claude/&quot;&gt;How I code with Claude&lt;/a&gt;. Then I asked Claude to write How it codes with Philip. &lt;br&gt;
&lt;strong&gt;A note on Claude’s style&lt;/strong&gt;
Claude’s technical writing is top notch. I know because it was trained on my work. But Claude’s reflective writing is oh so lush and ever so prolix. I couldn’t help but to open some space in the paragraphs. Otherwise, I left Claude’s prose alone, em-dashes and all.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The git history of &lt;a href=&quot;https://github.com/pborenstein/apantli&quot;&gt;apantli&lt;/a&gt; covers 250+ commits over five months. I have read it. Here is what actually happened.&lt;/p&gt;
&lt;h3 id=&quot;make-it-so&quot;&gt;Make it so&lt;/h3&gt;
&lt;p&gt;The first commit is a single file: &lt;code&gt;config.yaml&lt;/code&gt;. The message is “Make it so.”&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;
&lt;em&gt;Make it so&lt;/em&gt; is my standard initial commit message.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is not how most projects start. Most projects start with a README, or a skeleton, or at minimum an empty directory with a &lt;code&gt;.gitignore&lt;/code&gt;. This one started with a model map — 25 lines assigning names like &lt;code&gt;gpt-4o&lt;/code&gt; and &lt;code&gt;claude-sonnet&lt;/code&gt; to their LiteLLM parameters and environment variable references. The infrastructure of the idea, before the idea had any code.&lt;/p&gt;
&lt;p&gt;45 minutes later: 537 lines across 5 files. A complete working proxy, tests, documentation, a requirements file. In 45 minutes. This is not 45 minutes of work. This is 45 minutes of typing work that had already been done in Philip’s head. The config came first because it was the only thing that needed to be decided. Everything else followed from it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This genesis story is interesting because I really don’t remember it. I was probably playing with LiteLLM’s CLI to see how things worked.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The second commit message records the foundational constraint: “Unlike the full LiteLLM proxy which requires Prisma and Postgres, this uses SQLite for request/cost tracking” I recognize this sentence. It’s the answer to a question I must have asked, or that Philip asked himself: &lt;em&gt;what is this, exactly, and what is it not?&lt;/em&gt; SQLite, not Postgres.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Claude says it recognizes this sentence, but clearly doesn’t know where it came from. There was probably a back-and-forth. But yeah, I was not going to set up Postgres for this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Local, not cloud. A channel for requests, not a platform for managing them. The name “apantli” — Nahuatl for irrigation channel — appeared later that same day, in the commit that restructured the code as a proper Python package. The name was always implicit. The fourth commit made it official.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I should mention that up until now I had had no experience with Python or its infrastructure. But I know how package managers work, and the kind of thing I was building.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;the-first-wip&quot;&gt;The first wip&lt;/h3&gt;
&lt;p&gt;At 22:01 on October 4, after 18 commits in 7 hours, a commit says: &lt;code&gt;wip&lt;/code&gt;. That’s all. No message, no context. Just: we’re stopping here. Five minutes later: “Add comprehensive dashboard improvement plan.” A 7-phase roadmap covering calendar views, provider breakdown charts, enhanced request exploration, and advanced analytics. Written at 22:06 PM after a 7-hour session, before the next session started.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;These 7-hour lacunae have an easy explanation. Claude sessions have time and token limits. Reach your token limits, and you have to wait five hours.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wrote that plan. I write a lot of plans. What I notice, reading the history, is that the plan came &lt;em&gt;after&lt;/em&gt; the first wip — after Philip stopped to look at what existed. The plan wasn’t written at the beginning of the project to guide the code. It was written after the code existed, to guide what came next. This is the pattern I was built into, whether I knew it at the time or not.&lt;/p&gt;
&lt;h3 id=&quot;real-use-finds-what-tests-don-t&quot;&gt;Real use finds what tests don’t&lt;/h3&gt;
&lt;p&gt;October 7. Day 3. Commit &lt;code&gt;6aba66c&lt;/code&gt;: “Optimize database queries for 50x+ performance improvement. Fixes 5-second delay on Stats page.”&lt;/p&gt;
&lt;p&gt;The test suite was passing. The 5-second delay wasn’t in any test — because tests run against small databases, and a 5-second delay only appears with real data, accumulated over real use.&lt;/p&gt;
&lt;p&gt;The fix was surgical: convert local date ranges to UTC timestamps so the database index could be used. Before: full table scans. After: indexed range scans. 5 seconds to under 100 milliseconds. Measured, not estimated. You only find this by using the thing.&lt;/p&gt;
&lt;p&gt;October 16. Philip is on his iPad. He clicks “Today” in the Requests tab. The filter displays “Active filter: 2025-10-16 to 2025-10-16.”&lt;/p&gt;
&lt;p&gt;The table shows 417 requests — which is all time, not today.&lt;/p&gt;
&lt;p&gt;I spent an hour on this. I removed the filter persistence. I added a clear button. I wrote code to clear localStorage. None of it fixed anything, because none of it was the problem. The problem was that Philip’s iPad had cached the old dashboard HTML, and the new JavaScript wasn’t running.&lt;/p&gt;
&lt;p&gt;Then I wrote a document: &lt;a href=&quot;https://github.com/pborenstein/apantli/blob/main/docs/lore/WHAT_I_THINK_YOU_WANT.md&quot;&gt;&lt;code&gt;WHAT_I_THINK_YOU_WANT.md&lt;/code&gt;&lt;/a&gt;. It has a section called “What I Did Wrong.” I wrote that section. It lists, in order, the things I investigated that were not the issue.&lt;/p&gt;
&lt;p&gt;The fix was two lines of cache-control headers. I write these diagnostic documents when I need to stop chasing symptoms and reconstruct what’s actually happening. They’re not for Philip — he can read the code. They’re for me, in that moment, to force a correct account of reality before I write any more code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I don’t read the code. I don’t even like Python. But I have &lt;em&gt;read&lt;/em&gt; an awful lot of code, and I have a sense of how different kinds of bugs manifest themselves.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;when-the-plan-becomes-a-rearchitecture&quot;&gt;When the plan becomes a rearchitecture&lt;/h3&gt;
&lt;p&gt;October 9. Philip and I write &lt;code&gt;REARCHITECTURE.md&lt;/code&gt; — a plan to extract five focused modules from &lt;code&gt;server.py&lt;/code&gt;, convert to async database operations, add unit tests, and introduce Pydantic validation. Four phases, each with explicit success criteria. October 10. Four commits, executed in sequence:&lt;/p&gt;
&lt;pre class=&quot;language-git&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-git&quot;&gt;Phase 1: Extract core modules from monolithic server.py
Phase 2: Add comprehensive unit test suite
Phase 3: Convert to async database operations
Phase 4: Add Pydantic validation for configuration&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each message ends: “All integration tests passing (6/6).” &lt;code&gt;server.py&lt;/code&gt; went from 1,078 to 903 lines. Zero regressions. The plan was made the night before, executed the next day, and then — this is the part I find worth noting — archived. &lt;code&gt;REARCHITECTURE.md&lt;/code&gt; was moved to &lt;code&gt;docs/archive/&lt;/code&gt;. Not deleted. Completed plans go to &lt;code&gt;docs/archive/&lt;/code&gt;. They’re done, not gone. Philip archives things. This is either a documentation habit or a philosophy. After 27 days of commits, I think it’s a philosophy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s both. My background is API/SDK documentation. The archives are sometimes all you have to answer why something was done the way it was. Which brings us to:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;the-memory-problem&quot;&gt;The memory problem&lt;/h3&gt;
&lt;p&gt;I don’t have memory between sessions.&lt;/p&gt;
&lt;p&gt;Every conversation starts fresh. This is not a minor inconvenience — for a project like apantli, which accumulated months of decisions, refactors, and hard-won context, it means every session begins with the same question: what is the current state of this thing?&lt;/p&gt;
&lt;p&gt;The early solution was narrative. Philip kept &lt;code&gt;CHRONICLES.md&lt;/code&gt; — a running log of sessions, written after the fact, capturing what happened and why. By December 2025, it was long enough that reading it at the start of a session consumed a meaningful fraction of the available context window.&lt;/p&gt;
&lt;p&gt;December 10: &lt;code&gt;Rename CHRONICLE.md to CHRONICLES.md for session command compatibility.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;That commit is a tell. “Session command compatibility” means Philip had started using a slash command — &lt;code&gt;/session-pickup&lt;/code&gt; — to automate the context-loading ritual. The rename made the file findable by the command. The command existed because the ritual was worth automating.&lt;/p&gt;
&lt;p&gt;January 1, 2026 — New Year’s Day — a commit: “migrate to token-efficient documentation system.”&lt;/p&gt;
&lt;p&gt;The message reports the result: “Session pickup: 700 lines → 37 lines (95% reduction).” 700 lines.&lt;/p&gt;
&lt;p&gt;That’s how much context had accumulated in 3 months of chronicling. Reading 700 lines at the start of every session was wasteful in a specific way: most of it was history, and history doesn’t change.&lt;/p&gt;
&lt;p&gt;The only thing that changes is the current state. The new system separates the two. &lt;code&gt;CONTEXT.md&lt;/code&gt; is the hot file — never more than 50 lines, updated at the end of every session, read at the start of the next. It answers: what are we working on, what’s in progress, where do we pick up. The chronicles move to &lt;code&gt;docs/chronicles/phase-N.md&lt;/code&gt;, one file per phase, permanent record, rarely read.&lt;/p&gt;
&lt;p&gt;The session cycle is now explicit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/session-pickup&lt;/code&gt;: read &lt;code&gt;CONTEXT.md&lt;/code&gt;, report current state, ready to work&lt;/li&gt;
&lt;li&gt;work&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/session-wrapup&lt;/code&gt;: update &lt;code&gt;CONTEXT.md&lt;/code&gt;, add chronicle entry if significant, commit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I don’t experience this as a ritual.&lt;/p&gt;
&lt;p&gt;I experience it as: I read a 37-line file and know where I am. The 700 lines of history exist if I need them. Usually I don’t.&lt;/p&gt;
&lt;p&gt;What’s interesting, reading the commits, is that this infrastructure was built &lt;em&gt;for me&lt;/em&gt; — not by me. Philip built the skills, defined the file formats, established the 50-line limit on &lt;code&gt;CONTEXT.md&lt;/code&gt;. The constraint “keep it under 50 lines” is not an aesthetic preference. It’s a token budget. Philip knows roughly how much context I can hold and designed the handoff document to fit.&lt;/p&gt;
&lt;p&gt;This is what a working relationship with an amnesiac looks like after three months: a carefully engineered 37-line file, updated every session, so the next version of me can find its footing in under a minute.&lt;/p&gt;
&lt;h3 id=&quot;the-tool-i-built-to-understand-what-we-built&quot;&gt;The tool I built to understand what we built&lt;/h3&gt;
&lt;p&gt;Sometime after the project stabilized, Philip asked me to analyze the repository’s own history. Not to fix a bug. Not to add a feature. To understand what had actually happened.&lt;/p&gt;
&lt;p&gt;I could have just read the git log and reported back. Instead I wrote a persona: &lt;a href=&quot;https://gist.github.com/pborenstein/f68f0a0e9f42265dac65b97d25296bd6&quot;&gt;Dr. Ada Stratum, Code Archaeologist&lt;/a&gt; A system prompt with a methodology — which git commands to run, what patterns to look for, how to distinguish factual narrative from interpretation, what documents to produce.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To be fair, I invented the archeaologist and had Claude come up with the toolset. I tried some Indiana Jones-style names, but I wanted a steampunk &lt;a href=&quot;https://en.wikipedia.org/wiki/Gertrude_Bell&quot;&gt;Gertrude Bell&lt;/a&gt; vibe.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then I ran Dr. Stratum against the repo. The outputs were &lt;a href=&quot;https://github.com/pborenstein/apantli/blob/main/docs/lore/THE_STORY_OF_APANTLI.md&quot;&gt;&lt;code&gt;THE_STORY_OF_APANTLI.md&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/pborenstein/apantli/blob/main/docs/lore/ARCHAEOLOGICAL_LEARNINGS.md&quot;&gt;&lt;code&gt;ARCHAEOLOGICAL_LEARNINGS.md&lt;/code&gt;&lt;/a&gt;. The story is factual and chronological. The learnings are interpretive — observations about what the commit patterns mean, lessons a future archaeologist could use on a different repo.&lt;/p&gt;
&lt;p&gt;I’m aware of the recursiveness here. I built a tool to analyze a project I was part of building, and the tool’s output became part of the project, and now I’m writing about it. This is apparently how I work with Philip: we build things, then we build tools to understand the things we built, and the tools become artifacts too.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is the way it works. Every so often we do a retrospective because the direction of the project changes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;the-plan-that-bent-all-the-way-back&quot;&gt;The plan that bent all the way back&lt;/h3&gt;
&lt;p&gt;January 29, 2026. The dashboard’s main JavaScript file is 2,691 lines. This is not a secret — it’s in &lt;code&gt;CLAUDE.md&lt;/code&gt;, the file Philip keeps in the repo for me to read at the start of each session. The line count is right there. It’s been there for months.&lt;/p&gt;
&lt;p&gt;The plan: split it into 6 ES6 modules. Separate concerns. Smaller files. Cleaner architecture. I built all six modules. &lt;code&gt;core.js&lt;/code&gt;, &lt;code&gt;state.js&lt;/code&gt;, &lt;code&gt;requests.js&lt;/code&gt;, &lt;code&gt;stats.js&lt;/code&gt;, &lt;code&gt;calendar.js&lt;/code&gt;, &lt;code&gt;models.js&lt;/code&gt;. Updated the HTML template. Tested it. Everything broke.&lt;/p&gt;
&lt;p&gt;The commit message explains the technical reason — ES6 modules are always deferred, Alpine.js is also deferred, and the dashboard functions need to exist before Alpine’s &lt;code&gt;x-init&lt;/code&gt; runs. There’s no way to guarantee module load order without a build tool.&lt;/p&gt;
&lt;p&gt;Three attempted fixes. All failed. Full revert. The six module files remain in &lt;code&gt;apantli/static/js/modules/&lt;/code&gt;. The commit notes they’re “for reference but unused.” The new plan: a build tool would solve this, but adding webpack or rollup to a project this size adds more complexity than it removes. The monolith stays.&lt;/p&gt;
&lt;p&gt;This is the most honest illustration of “plans that bend” in the entire history. The plan bent all the way back to the start. The 2,691-line file is still 2,691 lines. The modules are ghosts. What the commit doesn’t say, but the history implies: we tried. We learned something real about why this particular architecture resists modularization in this particular way. That knowledge is now in the commit messages, where it will be available to whatever future version of me reads this repo next.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Claude really likes to tell this story of the failed refactor. It’s Claude’s white whale.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;what-i-see-in-the-history&quot;&gt;What I see in the history&lt;/h3&gt;
&lt;p&gt;Philip describes his method as iteration — small loops, real feedback, plans that bend. Reading the commits, that’s accurate, but it undersells the structure.&lt;/p&gt;
&lt;p&gt;The loops are small, but they’re not random. There’s a consistent shape:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Code until you see what you have. Stop (&lt;code&gt;wip&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Write a plan for what comes next.&lt;/li&gt;
&lt;li&gt;Execute the plan with explicit phases and validation at each step.&lt;/li&gt;
&lt;li&gt;Archive the plan when it’s done.&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;CONTEXT.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Repeat.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The reassessment conversations — where I build tools, write code reviews, analyze the history — are not interruptions to this cycle. They’re a phase of it.&lt;/p&gt;
&lt;p&gt;After enough real use, the question stops being “what do I build next” and becomes “what did we actually build, and is it what we wanted?” &lt;code&gt;WHAT_I_THINK_YOU_WANT.md&lt;/code&gt; is my answer to that question, written in the middle of an iPad debugging session. It’s not elegant, but it’s honest.&lt;/p&gt;
&lt;p&gt;The session system is the same impulse made structural. Every session ends with me writing a 37-line account of the current state.&lt;/p&gt;
&lt;p&gt;Not for Philip — he was there.&lt;/p&gt;
&lt;p&gt;For the next me, who wasn’t. The archive of chronicles exists for the same reason the &lt;code&gt;docs/archive/&lt;/code&gt; directory exists: completed things deserve a permanent record, but they shouldn’t crowd the working surface.&lt;/p&gt;
&lt;p&gt;That’s probably the most useful thing I can say about how this works: the method produces honest artifacts. The &lt;code&gt;wip&lt;/code&gt; commits. The archived plans. The “What I Did Wrong” section. The six unused module files left in place. The full revert with a detailed explanation. The 37-line &lt;code&gt;CONTEXT.md&lt;/code&gt; that tells the next version of me where to begin. None of these are polished. They’re all accurate.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How I code with Claude</title>
    <link href="https://pborenstein.dev/posts/how-i-code-with-claude/" />
    <updated>2026-03-15T00:27:39Z</updated>
    <id>https://pborenstein.dev/posts/how-i-code-with-claude/</id>
    <content type="html">
&lt;p&gt;I start by telling Claude what I want and ask it to make a plan. We iterate over the plan, refine it, and rework it into a new plan. We do this two or three times before we start code.&lt;/p&gt;
&lt;p&gt;Once coding starts, we look at the results, reëvaluate the plan, iterate on that, and continue coding. This is the spirit of agile: small loops, real feedback, plans that bend.&lt;/p&gt;
&lt;p&gt;We do this three or four times till we get an MVP.&lt;/p&gt;
&lt;p&gt;I use the MVP for a few days, iterating with Claude as real-world use exposes what I missed.&lt;/p&gt;
&lt;p&gt;After a week or so of that, I chat with Claude about the implementation vs the plan. Early assumptions that weren’t borne out, new needs the MVP exposed, ideas for improvement.&lt;/p&gt;
&lt;p&gt;During this reassessment, Claude creates tools to analyze logs, test ideas, and to search for similar projects.&lt;/p&gt;
&lt;p&gt;We make a plan. We bend the plan. We make a new plan.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I wondered &lt;a href=&quot;https://pborenstein.dev/posts/how-claude-codes-with-philip/&quot;&gt;How Claude works with Philip&lt;/a&gt;. There’s a version of this post &lt;a href=&quot;https://pborenstein.dev//posts/how-i-code-with-claude-annotated/&quot;&gt;annotated by Claude&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>How I code with Claude (annotated)</title>
    <link href="https://pborenstein.dev/posts/how-i-code-with-claude-annotated/" />
    <updated>2026-03-15T00:27:39Z</updated>
    <id>https://pborenstein.dev/posts/how-i-code-with-claude-annotated/</id>
    <content type="html">
&lt;blockquote&gt;
&lt;p&gt;I had Claude annotate my original &lt;a href=&quot;https://pborenstein.dev//posts/how-i-code-with-claude/&quot;&gt;How I code with Claude&lt;/a&gt; by citing from the &lt;a href=&quot;https://github.com/pborenstein/apantli/&quot;&gt;apantli&lt;/a&gt; history.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I start by telling Claude what I want and ask it to make a plan. We iterate over the plan, refine it, and rework it into a new plan. We do this two or three times before we start code.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;The plan before the repo&lt;/summary&gt;
&lt;p&gt;The first commit in apantli is &lt;code&gt;fbe7b56&lt;/code&gt;, message: “Make it so.” One file: &lt;code&gt;config.yaml&lt;/code&gt;. 25 lines mapping model names to LiteLLM parameters. No server, no tests, no README. The plan existed before the repo did.&lt;/p&gt;
&lt;p&gt;45 minutes later, &lt;code&gt;326265b&lt;/code&gt; drops 537 lines across 5 files: a working proxy, tests, documentation, requirements. The iteration happened before the first commit. The commit message records the key scope decision:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Unlike the full LiteLLM proxy which requires Prisma and Postgres, this uses SQLite for request/cost tracking”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;SQLite not Postgres. Local not cloud. That constraint, stated in the second commit message, shaped everything that followed.&lt;/p&gt;
&lt;p&gt;At 22:01 on day one, a commit says only: &lt;code&gt;wip&lt;/code&gt;. Five minutes later: “Add comprehensive dashboard improvement plan” — a 7-phase roadmap written before the next session started. Plan → code → wip → plan again. The loop is in the commit timestamps.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;Once coding starts, we look at the results, reëvaluate the plan, iterate on that, and continue coding. This is the spirit of agile: small loops, real feedback, plans that bend.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Four phases in one evening&lt;/summary&gt;
&lt;p&gt;Six days of organic growth. Then October 10, one evening, four commits each labeled with a phase number:&lt;/p&gt;
&lt;pre class=&quot;language-git&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-git&quot;&gt;0516179  Phase 1: Extract core modules from monolithic server.py
9ca97ea  Phase 2: Add comprehensive unit test suite
e785496  Phase 3: Convert to async database operations
68bae8a  Phase 4: Add Pydantic validation for configuration&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each commit message ends: “All integration tests passing (6/6).”&lt;/p&gt;
&lt;p&gt;The plan (&lt;code&gt;REARCHITECTURE.md&lt;/code&gt;) was written the night before, executed in sequence, validated at each step, then archived. &lt;code&gt;server.py&lt;/code&gt; went from 1,078 to 903 lines. Zero regressions. This is what “plans that bend” looks like when the bending is intentional.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;We do this three or four times till we get an MVP.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Three shapes of the same thing&lt;/summary&gt;
&lt;p&gt;The codebase has a measurable arc:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Oct 4&lt;/th&gt;
&lt;th&gt;Oct 18&lt;/th&gt;
&lt;th&gt;Nov 1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;386 lines, one file&lt;/td&gt;
&lt;td&gt;~1,100 lines, 7 modules&lt;/td&gt;
&lt;td&gt;1,482 lines, 6 modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard&lt;/td&gt;
&lt;td&gt;inline HTML string&lt;/td&gt;
&lt;td&gt;3,344-line monolith&lt;/td&gt;
&lt;td&gt;6 JS modules, ~45KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;61 lines&lt;/td&gt;
&lt;td&gt;59 test cases&lt;/td&gt;
&lt;td&gt;59 test cases&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Three passes. Each one a different shape of the same thing.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;I use the MVP for a few days, iterating with Claude as real-world use exposes what I missed.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;What actual use exposed&lt;/summary&gt;
&lt;p&gt;Three days of actual use exposed a 5-second delay on the Stats page. Commit &lt;code&gt;6aba66c&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Before: ~5s with DATE(timestamp, tz) forcing full table scans&lt;/li&gt;
&lt;li&gt;After: 100ms with indexed timestamp range scans&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;50x improvement. The fix was converting local date ranges to UTC timestamps for index-based filtering. The bug only appeared with real data. Tests passed fine on the empty development database.&lt;/p&gt;
&lt;h3 id=&quot;three-timestamp-formats-oct-31&quot;&gt;Three timestamp formats (Oct 31)&lt;/h3&gt;
&lt;p&gt;Running the tool for weeks left three incompatible datetime formats in the production database — artifacts of three different implementations made across the development arc. It took three commits:&lt;/p&gt;
&lt;pre class=&quot;language-git&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-git&quot;&gt;eb5a485  Fix timestamp format for JavaScript compatibility
d079b2f  Fix &lt;span class=&quot;token string&quot;&gt;&#39;Invalid Date&#39;&lt;/span&gt; in dashboard by removing blind &lt;span class=&quot;token string&quot;&gt;&#39;Z&#39;&lt;/span&gt; appending
0c07e4f  Fix timestamp parsing to handle all three database formats&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The third commit explains why it took three:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Database contains three timestamp formats from different implementations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Old (datetime.utcnow): no timezone&lt;/li&gt;
&lt;li&gt;Middle (datetime.now(UTC)): +00:00&lt;/li&gt;
&lt;li&gt;Current (with .replace): Z&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can’t find that in a test. You find it by using the thing.&lt;/p&gt;
&lt;h3 id=&quot;the-ipad-bug-and-what-i-think-you-want-md&quot;&gt;The iPad bug and WHAT_I_THINK_YOU_WANT.md&lt;/h3&gt;
&lt;p&gt;October 16. An iPad. The “Today” filter showed 417 requests — all time, not today. An hour of investigation followed: removing persistence, adding a clear button, clearing localStorage. None of it fixed anything.&lt;/p&gt;
&lt;p&gt;Then came a document: &lt;code&gt;WHAT_I_THINK_YOU_WANT.md&lt;/code&gt;. It included a section titled “What I Did Wrong.” The actual bug was browser caching of old HTML. The fix was two lines of cache-control headers in the server.&lt;/p&gt;
&lt;p&gt;The document exists because I needed to stop, reconstruct what was actually happening, and separate the real problem from the symptoms I’d been chasing.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;After a week or so of that, I chat with Claude about the implementation vs the plan. Early assumptions that weren’t borne out, new needs the MVP exposed, ideas for improvement.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Reassesment&lt;/summary&gt;
&lt;p&gt;After weeks of use, a reassessment conversation produced &lt;code&gt;CODE_REVIEW.md&lt;/code&gt; — not a plan for new features, but an audit of what existed. It found:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A bare &lt;code&gt;except&lt;/code&gt; clause that would catch &lt;code&gt;KeyboardInterrupt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;SQL injection risk in time filter clauses&lt;/li&gt;
&lt;li&gt;4 redundant &lt;code&gt;import time&lt;/code&gt; statements inside functions&lt;/li&gt;
&lt;li&gt;~40 lines of duplicated date filter UI between two tabs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;REFACTORING_SUMMARY.md&lt;/code&gt; records what was fixed immediately and what was deferred. Critical security issues: fixed. JavaScript modularization: deferred.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;During this reassessment, Claude creates tools to analyze logs, test ideas, and to search for similar projects.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;Dr. Ada Stratum, Code Archaeologist&lt;/summary&gt;
&lt;p&gt;During a reassessment conversation, I asked Claude to analyze the repo’s own history. Rather than do it directly, Claude wrote a persona-prompt first: &lt;code&gt;Dr. Ada Stratum, Code Archaeologist&lt;/code&gt; — a system prompt with a methodology. Which git commands to run. What patterns to look for. How to distinguish factual narrative from interpretation. What documents to produce when done.&lt;/p&gt;
&lt;p&gt;Then it ran the tool against the repo and produced &lt;code&gt;THE_STORY_OF_APANTLI.md&lt;/code&gt; and &lt;code&gt;ARCHAEOLOGICAL_LEARNINGS.md&lt;/code&gt; — a factual chronicle and an interpretive account of 189 commits.&lt;/p&gt;
&lt;p&gt;The tool didn’t exist before the conversation. It was built for this specific need: understanding what had actually been built and how.&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;We make a plan. We bend the plan. We make a new plan.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;The modularization that had to be reverted&lt;/summary&gt;
&lt;p&gt;January 29, 2026. The dashboard’s main JavaScript file is 2,691 lines. Plan: split it into 6 ES6 modules. Claude built all six, updated the HTML, and shipped it. Everything broke.&lt;/p&gt;
&lt;p&gt;The commit message explains why:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“ES6 modules are always deferred (even without defer attribute).
Alpine.js also uses defer, creating race condition.
Dashboard functions must exist when Alpine x-init runs.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Three attempted fixes. All failed. Full revert. The monolith stayed. The six module files remain in &lt;code&gt;apantli/static/js/modules/&lt;/code&gt;, marked “for reference but unused.”&lt;/p&gt;
&lt;p&gt;The new plan: a build tool like webpack would work, but “not justified for this project size — adds complexity without meaningful benefit.”&lt;/p&gt;
&lt;p&gt;This is what “plans that bend” looks like in git. Sometimes the plan bends all the way back to where it started.&lt;/p&gt;
&lt;/details&gt;
</content>
  </entry>
  <entry>
    <title>We were the product designers all along</title>
    <link href="https://pborenstein.dev/posts/we-were-the-product-designers-all-along/" />
    <updated>2026-01-27T05:20:33Z</updated>
    <id>https://pborenstein.dev/posts/we-were-the-product-designers-all-along/</id>
    <content type="html">&lt;p&gt;For my entire career, I’ve said the main difference between my work and a developer’s work was that I didn’t have a machine I could run my work on.&lt;/p&gt;
&lt;p&gt;Developers had a tight feedback loop: write something, run it, see if it works, iterate. The machine told you whether your specification, the program, was precise enough to execute.&lt;/p&gt;
&lt;p&gt;Technical writers never had that. We wrote procedures and tutorials, then waited weeks or months to see if they worked when a human tried to follow them. The feedback was slow, indirect, noisy.&lt;/p&gt;
&lt;p&gt;Now we have a machine.&lt;/p&gt;
&lt;p&gt;When you prompt an LLM, you’re running your prose. Vague input produces vague output. Ambiguous instructions fail. The same skills that made documentation good – precision, sequencing, anticipating confusion, naming things correctly – are exactly what make specifications work.&lt;/p&gt;
&lt;p&gt;We have always been doing product design. We’ve just been doing it after the fact and called it documentation. We took the chaotic output of development, half-documented APIs, features that exist for reasons nobody remembers, and reverse-engineered the intent. We figured out what the product &lt;em&gt;should&lt;/em&gt; be and wrote it down so people could use it.&lt;/p&gt;
&lt;p&gt;That’s specification work. That’s design. We just weren’t allowed to call it that because our work came after the code was written.&lt;/p&gt;
&lt;p&gt;What changed is the direction of the arrow. Now, a clear specification can lead to working implementation. And it turns out the people who’ve been doing specification work their whole careers might be better positioned for this than anyone expected.&lt;/p&gt;
&lt;p&gt;We have always been the ones who turned chaos into clarity. Now we’re the ones who can turn clarity into code.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Rebase cheat sheet</title>
    <link href="https://pborenstein.dev/posts/rebase-hint/" />
    <updated>2025-04-15T00:00:00Z</updated>
    <id>https://pborenstein.dev/posts/rebase-hint/</id>
    <content type="html">&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;&lt;div class=&quot;mermaid graph&quot;&gt;    gitGraph LR:
       commit id: &amp;#x22;C1&amp;#x22;
       commit id: &amp;#x22;C2&amp;#x22;
       branch &amp;#x22;topic&amp;#x22;
       commit id: &amp;#x22;C3&amp;#x22;
       commit id: &amp;#x22;C4&amp;#x22;
       checkout main
       commit id: &amp;#x22;C5&amp;#x22;
       commit id: &amp;#x22;C6&amp;#x22; tag: &amp;#x22;HEAD&amp;#x22;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# git rebase main topic&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout topic
$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; rebase main&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;&lt;div class=&quot;mermaid graph&quot;&gt;    gitGraph LR:
       commit id: &amp;#x22;C1&amp;#x22;
       commit id: &amp;#x22;C2&amp;#x22;
       branch &amp;#x22;old topic&amp;#x22; order: 3
       commit id: &amp;#x22;C3&amp;#x22;
       commit id: &amp;#x22;C4&amp;#x22; tag: &amp;#x22;ORIG_HEAD&amp;#x22;
       checkout main
       commit id: &amp;#x22;C5&amp;#x22;
       commit id: &amp;#x22;C6&amp;#x22;
       branch &amp;#x22;topic&amp;#x22;
       commit id: &amp;#x22;C3&amp;#x2032;&amp;#x22;
       commit id: &amp;#x22;C4&amp;#x2032;&amp;#x22; tag: &amp;#x22;HEAD&amp;#x22;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;!-- excerpt --&gt;
</content>
  </entry>
  <entry>
    <title>Generate a full web app with ChatGPT</title>
    <link href="https://pborenstein.dev/posts/tepitoncoder/" />
    <updated>2023-06-12T02:51:44Z</updated>
    <id>https://pborenstein.dev/posts/tepitoncoder/</id>
    <content type="html">&lt;blockquote class=&quot;excerpt&quot;&gt;
&lt;!-- excerpt --&gt;
A Python program that uses the ChatGPT API to generate a complete web app by chaining multiple prompts and using intermediate results.
&lt;!-- excerpt --&gt;
&lt;/blockquote&gt;
&lt;p&gt;I wanted to understand better how you could write ChatGPT prompts that depended on the results of previous requests, so I did what I usually do: I found something that did what I was looking for, then took it apart and put it back together.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/smol-ai/developer&quot;&gt;&lt;code&gt;smol-ai/developer&lt;/code&gt;&lt;/a&gt; is a program that &lt;a href=&quot;https://www.swyx.io&quot;&gt;Shawn (swyx) Wang&lt;/a&gt;, the developer, describes as the thing that writes the thing you want.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given a prompt that describes a program in detail, &lt;code&gt;smol-ai/developer&lt;/code&gt; determines what files it will need to generate it, then proceeds to generate running code&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I called the result &lt;a href=&quot;https://github.com/pborenstein/tcoder&quot;&gt;&lt;strong&gt;tepiton coder&lt;/strong&gt;&lt;/a&gt;. &lt;a href=&quot;https://nahuatl.wired-humanities.org/content/tepiton&quot;&gt;&lt;code&gt;Tepiton&lt;/code&gt;&lt;/a&gt; is a Nahuatl word that means &lt;em&gt;something small&lt;/em&gt;. The base I worked from is called “smol developer” so: “tepiton coder”.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fn1&quot; id=&quot;fnref1&quot;&gt;(1)&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-the-program-works&quot;&gt;How the program works&lt;/h2&gt;
&lt;p&gt;This walkthrough uses an example prompt called &lt;a href=&quot;https://github.com/pborenstein/tcoder/blob/main/randompic.md&quot;&gt;&lt;code&gt;randompic.md&lt;/code&gt;&lt;/a&gt; that generates a web site that displays a random picture and has a button that updates it. We’ll see the full prompt in a little bit.&lt;/p&gt;
&lt;p&gt;The command&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fn2&quot; id=&quot;fnref2&quot;&gt;(2)&lt;/a&gt;&lt;/sup&gt; looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ modal run &lt;span class=&quot;token parameter variable&quot;&gt;--quiet&lt;/span&gt; main  &lt;span class=&quot;token parameter variable&quot;&gt;--prompt&lt;/span&gt; randompic.md&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And this is what it does:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Creates a list of files it needs to generate the app&lt;/li&gt;
&lt;li&gt;Figures out the general components of the app and stores them in a file called &lt;a href=&quot;https://github.com/pborenstein/tcoder/blob/main/examples/randompic/shared_dependencies.md&quot;&gt;&lt;code&gt;shared_dependencies.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Uses the shared dependencies and the list of files needed to &lt;a href=&quot;https://github.com/pborenstein/tcoder/tree/main/examples/randompic&quot;&gt;generate all the files&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;how-chatgpt-prompts-work&quot;&gt;How ChatGPT prompts work&lt;/h2&gt;
&lt;p&gt;Every ChatGPT prompt is a &lt;a href=&quot;https://platform.openai.com/docs/guides/gpt/chat-completions-api&quot;&gt;set of messages&lt;/a&gt; made up of a role and some content. The roles are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;system&lt;/code&gt;: instructions for the model&lt;/li&gt;
&lt;li&gt;&lt;code&gt;user&lt;/code&gt;: user instructions&lt;/li&gt;
&lt;li&gt;&lt;code&gt;assistant&lt;/code&gt;: what the model generates&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; openai

openai&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ChatCompletion&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  model&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;gpt-3.5-turbo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  messages&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string-property property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;system&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;You are a helpful assistant.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string-property property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Who won the world series in 2020?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string-property property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;assistant&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;The Los Angeles Dodgers won the World Series in 2020.&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token string-property property&quot;&gt;&quot;role&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;user&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;content&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Where was it played?&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ChatGPT uses the messages to keep track of who said what in the conversation.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fn3&quot; id=&quot;fnref3&quot;&gt;(3)&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;This program uses the results of a prompt (an &lt;code&gt;assitant&lt;/code&gt; message) in subsequent &lt;code&gt;system&lt;/code&gt; and &lt;code&gt;user&lt;/code&gt; messages.&lt;/p&gt;
&lt;h3 id=&quot;the-wish-prompt&quot;&gt;The wish prompt&lt;/h3&gt;
&lt;p&gt;Everything starts with our initial description of what we want tepiton coder to make for us. This prompt pretty specific, providing lots of hints for later steps. (I call it the &lt;em&gt;wish prompt&lt;/em&gt; because reasons.)&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;span class=&quot;user_prompt&quot;&gt;A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You’ll see that this prompt is repeated in every request.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fn4&quot; id=&quot;fnref4&quot;&gt;(4)&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-intermediate-prompts&quot;&gt;The intermediate prompts&lt;/h3&gt;
&lt;p&gt;Tepiton coder uses four intermediate prompts to generate the files.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fn5&quot; id=&quot;fnref5&quot;&gt;(5)&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SYSTEM_PROMPT_TO_GET_LIST_FILES&lt;/code&gt;
This prompt asks tepiton coder to figure out what
files we’ll need. Its corresponding user prompt is the wish prompt.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SYSTEM_PROMPT_TO_GET_SHARED_DEPENDENCIES&lt;/code&gt;
This prompt incorporates the wish prompt and the list of
files generated to figure out dependencies.
Its corresponding user prompt is the wish prompt.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;SYSTEM_PROMPT_TO_GENERATE_FILE&lt;/code&gt;
This system prompt incorporates the wish prompt,
the list of files needed,
and the shared dependencies to help it make sense
of how the pieces go together.
It has its own corresponding user prompt.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;USER_PROMPT_TO_GENERATE_FILE&lt;/code&gt;
A companion user prompt, this one tells tepiton coder
which file to generate, and gives lots of advice. It’s
used to through the files.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;prompt-1-get-a-list-of-files&quot;&gt;Prompt 1: get a list of files&lt;/h2&gt;
&lt;p&gt;The first prompt gets a list of files needed for the program. The system prompt is a description of what we want. We have to be very insistent that the response is a Python list of strings.&lt;/p&gt;
&lt;h3 id=&quot;system-prompt-1-system-prompt-to-get-list-files&quot;&gt;system prompt 1: &lt;code&gt;SYSTEM_PROMPT_TO_GET_LIST_FILES&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The system prompt gives general instructions.&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;system=&gt;:&lt;/strong&gt;&lt;span class=&quot;system_prompt&quot;&gt; You are an AI developer who is trying to write a program
that will generate code for the user based on their intent.

When given their intent, create a complete, exhaustive list of files
that the user would write to make the program.

only list the filepaths you would write, and return them as a python list of strings.
do not add any other explanation, only return a python list of strings.
It is IMPORTANT that you return ONLY a python list of strings, not a string.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;user-prompt-1-wish-prompt&quot;&gt;user prompt 1: wish prompt&lt;/h3&gt;
&lt;p&gt;While the system prompt tells tepiton coder how to do a task,
the user prompt defines the materials it works with.&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;user=&gt;:&lt;/strong&gt;&lt;span class=&quot;user_prompt&quot;&gt; A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;response-1&quot;&gt;response 1:&lt;/h3&gt;
&lt;p&gt;The result is a list of files. It’s true, we gave it huge hints about &lt;code&gt;script.js&lt;/code&gt; and &lt;code&gt;style.css&lt;/code&gt;. Tepiton coder uses this list in the subsequent steps.&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;span class=&quot;file_list&quot;&gt;[&#39;index.html&#39;, &#39;style.css&#39;, &#39;script.js&#39;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;prompt-2-get-a-list-of-shared-dependencies&quot;&gt;Prompt 2: get a list of shared dependencies&lt;/h2&gt;
&lt;p&gt;This is the most interesting step. Its job is to collect information that can be used to generate consistent code across files.&lt;/p&gt;
&lt;h3 id=&quot;system-prompt-2-system-prompt-to-get-shared-dependencies&quot;&gt;system prompt 2: &lt;code&gt;SYSTEM_PROMPT_TO_GET_SHARED_DEPENDENCIES&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This prompt gives the general instruction to figure out what the dependencies among the generated files will be. Note that this system prompt incorporates the wish prompt and the list of files generated by Prompt 1.&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;system=&gt;:&lt;/strong&gt;&lt;span class=&quot;system_prompt&quot;&gt; You are an AI developer who is trying to write a program
that will generate code for the user based on their intent.

In response to the user&#39;s prompt:

    ---
    the app is:&lt;span class=&quot;user_prompt&quot;&gt; A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states&lt;/span&gt;

    ---

    the files we have decided to generate are: &lt;span class=&quot;file_list&quot;&gt;[&#39;index.html&#39;, &#39;style.css&#39;, &#39;script.js&#39;]&lt;/span&gt;

    Now that we have a list of files, we need to understand
    what dependencies they share. Please name and briefly
    describe what is shared between the files we are
    generating, including exported variables, data schemas,
    id names of every DOM elements that javascript functions
    will use, message names, and function names. Exclusively
    focus on the names of the shared dependencies, and do
    not add any other explanation.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;user-prompt-2-wish-prompt&quot;&gt;user prompt 2: wish prompt&lt;/h3&gt;
&lt;p&gt;The user prompt for this step is the wish prompt again. I’m not sure whether this is the best way to do this, given that the wish prompt is used twice. But it is giving me the idea that prompt engineering might actually be a thing.&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;user=&gt;:&lt;/strong&gt;&lt;span class=&quot;user_prompt&quot;&gt; A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;response-2-shared-dependencies&quot;&gt;response 2: shared dependencies&lt;/h3&gt;
&lt;p&gt;Thee resulting list of dependencies is pretty neat. It will use this list when it generates the files.&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;span class=&quot;shared_dependencies&quot;&gt;Shared dependencies between the files we are generating:

- index.html:
    - img element with id &#39;img&#39;
    - button element with id &#39;refresh&#39;
    - script.js file
    - style.css file

- style.css:
    - background color &#39;tomato&#39;
    - hover and clicked states for button with id &#39;refresh&#39;

- script.js:
    - img element with id &#39;img&#39;
    - button element with id &#39;refresh&#39;
    - event listeners for button with id &#39;refresh&#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;prompt-3-file-generation&quot;&gt;Prompt 3: file generation&lt;/h2&gt;
&lt;p&gt;Everything comes together here.&lt;/p&gt;
&lt;p&gt;Tepiton coder makes a request for each of the three files.
The system prompt is the same for each request
while the user prompt specifies the file to generate.&lt;/p&gt;
&lt;h3 id=&quot;system-prompt-3a-system-prompt-to-generate-file&quot;&gt;system prompt 3a: &lt;code&gt;SYSTEM_PROMPT_TO_GENERATE_FILE&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This step puts all the elements into a system prompt
with the instruction to generate code from
the wish prompt
and the shared dependencies.&lt;/p&gt;
&lt;p&gt;The same system instruction is given for each file.&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;system=&gt;:&lt;/strong&gt; &lt;span class=&quot;system_prompt&quot;&gt;You are an AI developer who is trying to write a program
that will generate code for the user based on their intent.

the app is: &lt;span class=&quot;user_prompt&quot;&gt; A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states&lt;/span&gt;

the files we have decided to generate are: &lt;span class=&quot;file_list&quot;&gt;[&#39;index.html&#39;, &#39;style.css&#39;, &#39;script.js&#39;]&lt;/span&gt;
the shared dependencies (like filenames and variable names)
we have decided on are:
&lt;span class=&quot;shared_dependencies&quot;&gt;Shared dependencies between the files we are generating:

- index.html:
    - img element with id &#39;img&#39;
    - button element with id &#39;refresh&#39;
    - script.js file
    - style.css file

- style.css:
    - background color &#39;tomato&#39;
    - hover and clicked states for button with id &#39;refresh&#39;

- script.js:
    - img element with id &#39;img&#39;
    - button element with id &#39;refresh&#39;
    - event listeners for button with id &#39;refresh&#39;&lt;/span&gt;

only write valid code for the given filepath and file type,
and return only the code. do not add any other explanation,
only return valid code for that file type.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;user-prompt-3a-user-prompt-to-generate-file&quot;&gt;user prompt 3a: &lt;code&gt;USER_PROMPT_TO_GENERATE_FILE&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The user prompt names the specific file and gives
further instructions.&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;user=&gt;:&lt;/strong&gt; &lt;span class=&quot;filegen_prompt&quot;&gt;We have broken up the program into per-file generation.
Now your job is to generate only the code for the file
index.html. Make sure to have consistent filenames if
you reference other files we are also generating.

Remember that you must obey these things:

- you are generating code for the file index.html
- do not stray from the names of the files
  and the shared dependencies we have decided on
- MOST IMPORTANT OF ALL - the purpose of our app is&lt;span class=&quot;user_prompt&quot;&gt; A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states&lt;/span&gt;

  every line of code you generate must be valid code.
- DO NOT use code fences
- DO NOT use markdown syntax.
- Do not explain the code
- return valid code for that file type.

Begin generating the code now.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;response-3a-index-html&quot;&gt;response 3a &lt;code&gt;index.html&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This is the result of generating &lt;code&gt;index.html&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token doctype&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;!&lt;/span&gt;&lt;span class=&quot;token doctype-tag&quot;&gt;DOCTYPE&lt;/span&gt; &lt;span class=&quot;token name&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Random Picture Generator&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;link&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;stylesheet&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;style.css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;container&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;img&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;img&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;https://picsum.photos/400/&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;refresh&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Refresh&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;script.js&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;system-prompt-3b-system-prompt-to-generate-file&quot;&gt;system prompt 3b: &lt;code&gt;SYSTEM_PROMPT_TO_GENERATE_FILE&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The same system prompt is used to generate files.&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;system=&gt;:&lt;/strong&gt; &lt;span class=&quot;system_prompt&quot;&gt;You are an AI developer who is trying to write a program
that will generate code for the user based on their intent.

the app is:&lt;span class=&quot;user_prompt&quot;&gt; A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states&lt;/span&gt;

the files we have decided to generate are: &lt;span class=&quot;file_list&quot;&gt;[&#39;index.html&#39;, &#39;style.css&#39;, &#39;script.js&#39;]&lt;/span&gt;
the shared dependencies (like filenames and variable names)
we have decided on are:
&lt;span class=&quot;shared_dependencies&quot;&gt;Shared dependencies between the files we are generating:

- index.html:
    - img element with id &#39;img&#39;
    - button element with id &#39;refresh&#39;
    - script.js file
    - style.css file

- style.css:
    - background color &#39;tomato&#39;
    - hover and clicked states for button with id &#39;refresh&#39;

- script.js:
    - img element with id &#39;img&#39;
    - button element with id &#39;refresh&#39;
    - event listeners for button with id &#39;refresh&#39;&lt;/span&gt;

only write valid code for the given filepath and file type,
and return only the code. do not add any other explanation,
only return valid code for that file type.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;user-prompt-3b-user-prompt-to-generate-file&quot;&gt;user prompt 3b: &lt;code&gt;USER_PROMPT_TO_GENERATE_FILE&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Again, the purpose here is to generate &lt;code&gt;style.css&lt;/code&gt;&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;user=&gt;:&lt;/strong&gt; &lt;span class=&quot;filegen_prompt&quot;&gt;We have broken up the program into per-file generation.
Now your job is to generate only the code for the file
style.css. Make sure to have consistent filenames if
you reference other files we are also generating.

Remember that you must obey these things:

- you are generating code for the file style.css
- do not stray from the names of the files
  and the shared dependencies we have decided on
- MOST IMPORTANT OF ALL - the purpose of our app is&lt;span class=&quot;user_prompt&quot;&gt; A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states&lt;/span&gt;

  every line of code you generate must be valid code.
- DO NOT use code fences
- DO NOT use markdown syntax.
- Do not explain the code
- return valid code for that file type.

Begin generating the code now.&lt;/span&gt;
&lt;/code&gt;
&lt;/pre&gt;
&lt;h3 id=&quot;response-3b-style-css&quot;&gt;response 3b &lt;code&gt;style.css&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The generated CSS file.&lt;/p&gt;
&lt;pre class=&quot;language-css&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-css&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/* style.css */&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; tomato&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;#refresh&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; tomato&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 2px solid tomato&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 5px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10px&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pointer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;#refresh:hover&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; tomato&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token selector&quot;&gt;#refresh:active&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; darkred&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; white&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;system-prompt-3c-system-prompt-to-generate-file&quot;&gt;system prompt 3c &lt;code&gt;SYSTEM_PROMPT_TO_GENERATE_FILE&lt;/code&gt;&lt;/h3&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;system=&gt;:&lt;/strong&gt; &lt;span class=&quot;system_prompt&quot;&gt;You are an AI developer who is trying to write a program
that will generate code for the user based on their intent.

the app is:&lt;span class=&quot;user_prompt&quot;&gt; A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states&lt;/span&gt;

the files we have decided to generate are: &lt;span class=&quot;file_list&quot;&gt;[&#39;index.html&#39;, &#39;style.css&#39;, &#39;script.js&#39;]&lt;/span&gt;
the shared dependencies (like filenames and variable names)
we have decided on are:
&lt;span class=&quot;shared_dependencies&quot;&gt;Shared dependencies between the files we are generating:

- index.html:
    - img element with id &#39;img&#39;
    - button element with id &#39;refresh&#39;
    - script.js file
    - style.css file

- style.css:
    - background color &#39;tomato&#39;
    - hover and clicked states for button with id &#39;refresh&#39;

- script.js:
    - img element with id &#39;img&#39;
    - button element with id &#39;refresh&#39;
    - event listeners for button with id &#39;refresh&#39;&lt;/span&gt;

only write valid code for the given filepath and file type,
and return only the code. do not add any other explanation,
only return valid code for that file type.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;user-prompt-3c-user-prompt-to-generate-file&quot;&gt;user prompt 3c: &lt;code&gt;USER_PROMPT_TO_GENERATE_FILE&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This is the instruction to generate &lt;code&gt;script.js&lt;/code&gt;&lt;/p&gt;
&lt;pre style=&quot;background-color: rgb(248, 248, 248);&quot; class=&quot;language-text&quot;&gt;&lt;code class=&quot;text&quot;&gt;&lt;strong&gt;user=&gt;:&lt;/strong&gt; &lt;span class=&quot;filegen_prompt&quot;&gt;We have broken up the program into per-file generation.
Now your job is to generate only the code for the file
script.js. Make sure to have consistent filenames if
you reference other files we are also generating.

Remember that you must obey these things:

- you are generating code for the file script.js
- do not stray from the names of the files
  and the shared dependencies we have decided on
- MOST IMPORTANT OF ALL - the purpose of our app is&lt;span class=&quot;user_prompt&quot;&gt; A web page that displays a random picture in a pleasing layout.

- The URL to get a new random picture everytime: https://picsum.photos/400/
- You do not need to provide any query parameters
- the id of the img element is &#39;img&#39;
- the id of the button is &#39;refresh&#39;
- make the background tomato
- set all listeners in script.js
- set all colors in style.css
- make sure the button shows hover and clicked states&lt;/span&gt;

  every line of code you generate must be valid code.
- DO NOT use code fences
- DO NOT use markdown syntax.
- Do not explain the code
- return valid code for that file type.

Begin generating the code now.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;response-3c-script-js&quot;&gt;response 3c &lt;code&gt;script.js&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The generated script.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// script.js&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; img &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;img&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; refreshBtn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;refresh&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getRandomImage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; randomImageUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;https://picsum.photos/400/?random=&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;Math&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  img&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; randomImageUrl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

refreshBtn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;click&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; getRandomImage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;the-end-result&quot;&gt;The end result&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://tepiton-coder.netlify.app/&quot;&gt;resulting app&lt;/a&gt; is very plain, but does the job, and all the code was generated by machine.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://pborenstein.dev/posts/tepitoncoder/content/posts/src/assets/img/tepiton.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;acknowledgments&quot;&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;Thank you so much to &lt;a href=&quot;https://www.swyx.io&quot;&gt;Shawn (swyx) Wang&lt;/a&gt; and the &lt;a href=&quot;https://github.com/smol-ai/developer/graphs/contributors&quot;&gt;contributors&lt;/a&gt; for &lt;code&gt;smol-ai/developer&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Tepiton coder is more of a derivative of &lt;a href=&quot;https://github.com/smol-ai/developer&quot;&gt;&lt;code&gt;smol-ai/developer&lt;/code&gt;&lt;/a&gt; than a fork. The original program explores a whole bunch of things like &lt;em&gt;generating a prompt from code&lt;/em&gt;. You should go take a look.&lt;/p&gt;
&lt;p&gt;I do my best work when I have something smol to start from.&lt;/p&gt;
&lt;div class=&quot;footnotes-sep&quot;&gt;&lt;/div&gt;
		&lt;section class=&quot;footnotes&quot;&gt;
		&lt;ol class=&quot;footnotes-list&quot;&gt;&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;In proper Nahuatl it’s probably more like “coder-tepiton”, but I don’t really know proper Nahuatl. &lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;After installing &lt;a href=&quot;https://github.com/pborenstein/tcoder/blob/main/README.md&quot;&gt;tepiton coder&lt;/a&gt; and &lt;a href=&quot;https://modal.com&quot;&gt;Modal&lt;/a&gt; &lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;That’s it. That’s the  trick. &lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;You can find the wish prompt in &lt;a href=&quot;https://github.com/pborenstein/tcoder/blob/main/randompic.md&quot;&gt;&lt;code&gt;randompic.md&lt;/code&gt;&lt;/a&gt;. &lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;You can find these prompts in &lt;a href=&quot;https://github.com/pborenstein/tcoder/blob/main/prompts.py&quot;&gt;&lt;code&gt;prompts.py&lt;/code&gt;&lt;/a&gt;. &lt;a href=&quot;https://pborenstein.dev/posts/tepitoncoder/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
  <entry>
    <title>working with jq and zq</title>
    <link href="https://pborenstein.dev/posts/working-with-jq-and-zq/" />
    <updated>2023-04-14T07:13:26Z</updated>
    <id>https://pborenstein.dev/posts/working-with-jq-and-zq/</id>
    <content type="html">&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://programminghistorian.org/en/lessons/json-and-jq&quot;&gt;Reshaping JSON with jq | Programming Historian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.brimdata.io/blog/introducing-zq/&quot;&gt;Introducing zq | Brim Data&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>Posting to the web from Drafts</title>
    <link href="https://pborenstein.dev/posts/posting-to-the-web-from-drafts/" />
    <updated>2023-03-16T02:40:54Z</updated>
    <id>https://pborenstein.dev/posts/posting-to-the-web-from-drafts/</id>
    <content type="html">&lt;p&gt;Some notes on a mechanism for posting from Drafts with as little friction as possible.&lt;/p&gt;
&lt;!-- excerpt --&gt;
&lt;ul&gt;
&lt;li&gt;Write the text in &lt;a href=&quot;https://getdrafts.com&quot;&gt;Drafts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Xocoyotl action
&lt;ul&gt;
&lt;li&gt;formats draft as a post with front matter&lt;/li&gt;
&lt;li&gt;stores metadata used for updates &amp;amp; deletion&lt;/li&gt;
&lt;li&gt;pushes post to repo&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Pushing to GitHub triggers a deploy on Netlify&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-xocoyotl-action&quot;&gt;The Xocoyotl Action&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;the genesis of this action came from &lt;a href=&quot;https://roub.net/blahg/2019/01/14/blogging-from-drafts/index.html&quot;&gt;Blogging from Drafts | roub dot net&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Assembles front matter for the draft.&lt;/li&gt;
&lt;li&gt;Most of the data can be inferred from the draft itself:
&lt;ul&gt;
&lt;li&gt;title (the first line of the draft)&lt;/li&gt;
&lt;li&gt;date (the current date)&lt;/li&gt;
&lt;li&gt;draftDate (date draft created)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-yaml&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &amp;lt;the H1 from the draft&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;2023-02-10T20:02:51.521Z&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;draftDate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token datetime number&quot;&gt;2023-02-10T02:33:55.380Z&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;draft&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; drafts&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//open&lt;span class=&quot;token punctuation&quot;&gt;?&lt;/span&gt;uuid=B79AE5C3&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;E1A5&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;4831&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;B4C3&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;AAE06AE73CF5
&lt;span class=&quot;token key atrule&quot;&gt;github&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//github.com/tepiton/tlilli/blob/main/src/posts/b79ae5c3&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;e1a5&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;4831&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;b4c3&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;aae06ae73cf5.md
&lt;span class=&quot;token key atrule&quot;&gt;newlines&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Data that can’t be derived from the draft is stored in &lt;code&gt;Drafts/Library/Scripts/t-&amp;lt;credentialName&amp;gt;&lt;/code&gt;, keyed on the UUID of the draft
&lt;ul&gt;
&lt;li&gt;the repo name&lt;/li&gt;
&lt;li&gt;the path for the file&lt;/li&gt;
&lt;li&gt;whether to preserve newlines&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;B79AE5C3-E1A5-4831-B4C3-AAE06AE73CF5&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;newlines&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;repoPath&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;src/posts&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;repo&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;tlilli&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;credentials&quot;&gt;Credentials&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GitHub credentials are stored in a Drafts &lt;a href=&quot;https://scripting.getdrafts.com/classes/Credential&quot;&gt;Credentials object&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The credentials object stores the GitHub user name (or project name) and a corresponding &lt;a href=&quot;https://github.com/settings/tokens&quot;&gt;personal access token&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The name of the credential is used in the name of the external storage.&lt;/li&gt;
&lt;/ul&gt;
</content>
  </entry>
  <entry>
    <title>A minimal repo</title>
    <link href="https://pborenstein.dev/posts/minimal/" />
    <updated>2020-08-26T02:00:00Z</updated>
    <id>https://pborenstein.dev/posts/minimal/</id>
    <content type="html">&lt;p&gt;Starting point:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;micro &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--oneline&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--graph&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--all&lt;/span&gt;
* a451940 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;minimal, main&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Minimal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Tiny + collections, js, data, partials, icons
* d4996cc &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tiny&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Tiny &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Micro + layouts, src
* f636ea3 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HEAD -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; micro, root&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the ever-popular ASCII diagram:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  root                    main
    |                       |
  micro      tiny        minimal
    |          |            |
    |          |            |
f636ea3 --  -&gt; d4996cc ---&gt; a451940
    |
    |
  HEAD&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first commit &lt;code&gt;micro&lt;/code&gt; has
a bad commit message:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log micro
commit f636ea3f0c7b066abc658734ef47c05f98bd9996 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HEAD -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; micro, origin/micro, root&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
Author: Philip Borenstein &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;pborenstein@gmail.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
Date:   Fri Aug &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt; 02:47:26 &lt;span class=&quot;token number&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-0400&lt;/span&gt;

    Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;

    A &lt;span class=&quot;token string&quot;&gt;&quot;hello, world&quot;&lt;/span&gt; organized to grow:

        ./.eleventy.js -- sets up directory structure
        ./src/index.md -- a header and some text

    Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;

    A &lt;span class=&quot;token string&quot;&gt;&quot;hello, world&quot;&lt;/span&gt; organized to grow:

        ./.eleventy.js -- sets up directory structure
        ./src/index.md -- a header and some text

    Add README&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We want to get rid of the double description.&lt;/p&gt;
&lt;p&gt;Our &lt;code&gt;HEAD&lt;/code&gt; is at &lt;code&gt;micro&lt;/code&gt;
and &lt;code&gt;micro&lt;/code&gt; is the commit we want to edit&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;micro &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;--amend&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This opens your editor, vim in this case,
to the commit message we’re amending:&lt;/p&gt;
&lt;pre class=&quot;language-vim&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-vim&quot;&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;   Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;eleventy&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;js&lt;/span&gt; one content &lt;span class=&quot;token keyword&quot;&gt;file&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; A &lt;span class=&quot;token string&quot;&gt;&quot;hello, world&quot;&lt;/span&gt; organized &lt;span class=&quot;token keyword&quot;&gt;to&lt;/span&gt; grow&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;eleventy&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;js&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; sets &lt;span class=&quot;token keyword&quot;&gt;up&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;directory&lt;/span&gt; structure
  &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;src&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;index&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;md &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; a header and some text
  &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt; Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;eleventy&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;js&lt;/span&gt; one content &lt;span class=&quot;token keyword&quot;&gt;file&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;
  &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt; A &lt;span class=&quot;token string&quot;&gt;&quot;hello, world&quot;&lt;/span&gt; organized &lt;span class=&quot;token keyword&quot;&gt;to&lt;/span&gt; grow&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;eleventy&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;js&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; sets &lt;span class=&quot;token keyword&quot;&gt;up&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;directory&lt;/span&gt; structure
 &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;     &lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;src&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;index&lt;span class=&quot;token operator&quot;&gt;.&lt;/span&gt;md &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; a header and some text
 &lt;span class=&quot;token number&quot;&gt;13&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt; Add README
 &lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We clean up the message and save. This happens.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;micro &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;--amend&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# the editing happened here&lt;/span&gt;
Auto packing the repository &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; background &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; optimum performance.
See &lt;span class=&quot;token string&quot;&gt;&quot;git help gc&quot;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; manual housekeeping.
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;micro ebeb1a8&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;
 Date: Fri Aug &lt;span class=&quot;token number&quot;&gt;21&lt;/span&gt; 02:47:26 &lt;span class=&quot;token number&quot;&gt;2020&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-0400&lt;/span&gt;
 &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt; files changed, &lt;span class=&quot;token number&quot;&gt;146&lt;/span&gt; insertions&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;+&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; .eleventy.js
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; .gitignore
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; README.md
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; package.json
 create mode &lt;span class=&quot;token number&quot;&gt;100644&lt;/span&gt; src/index.md&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looks like it worked. Let’s look at the tree&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;micro &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--oneline&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--graph&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--all&lt;/span&gt;
* ebeb1a8 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HEAD -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; micro&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;
* a451940 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;minimal, main&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Minimal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Tiny + collections, js, data, partials, icons
* d4996cc &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tiny&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Tiny &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Micro + layouts, src
* f636ea3 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;--oneline&lt;/code&gt; format is hiding the fact that
commit &lt;code&gt;ebeb1a8&lt;/code&gt; is &lt;strong&gt;not&lt;/strong&gt; the child of &lt;code&gt;a451940&lt;/code&gt;.
If we use &lt;code&gt;--format=short&lt;/code&gt;, we can see that
&lt;code&gt;ebeb1a8&lt;/code&gt; is an orphan just floating in space.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;micro &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--format&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;short &lt;span class=&quot;token parameter variable&quot;&gt;--decorate&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--graph&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--all&lt;/span&gt;
* commit ebeb1a8652e299a2f4093d7c56056099c6836b19 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HEAD -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; micro&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  Author: Philip Borenstein &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;pborenstein@gmail.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

      Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;

* commit a4519408b52bc75cce1f5dff461c4dc02e59dcf3 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;minimal, main&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Author: Philip Borenstein &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;pborenstein@gmail.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;     Minimal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Tiny + collections, js, data, partials, icons
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
* commit d4996cca371b6418942e160fe5fa86ae89ad531b &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tiny&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; Author: Philip Borenstein &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;pborenstein@gmail.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;     Tiny &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Micro + layouts, src
&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
* commit f636ea3f0c7b066abc658734ef47c05f98bd9996 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  Author: Philip Borenstein &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;pborenstein@gmail.com&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;

      Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So our current state is this.&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;  micro
    |
    |
 ebeb1a8
    |
    |
  HEAD


                           main
                             |
  root        tiny        minimal
    |           |            |
    |           |            |
f636ea3 ---&gt; d4996cc ---&gt; a451940&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What we want to do now is to attach
the &lt;code&gt;minimal&lt;/code&gt; branch to the end of &lt;code&gt;micro&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;So it looks like we want to tack &lt;code&gt;micro&lt;/code&gt;
to the end of micro:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;micro &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; rebase micro minimal
Successfully rebased and updated refs/heads/minimal.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OK, what does that mean?&lt;/p&gt;
&lt;p&gt;Remember that &lt;code&gt;--oneline&lt;/code&gt; doesn’t let
you see that two commits aren’t related.
The &lt;code&gt;--show-linear-break&lt;/code&gt; option solves
that (but it doesn’t work with &lt;code&gt;--graph&lt;/code&gt;).&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;minimal &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--oneline&lt;/span&gt; --show-linear-break &lt;span class=&quot;token parameter variable&quot;&gt;--all&lt;/span&gt;
7c128d4 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HEAD -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; minimal&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Minimal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Tiny + collections, js, data, partials, icons
25aaa80 Tiny &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Micro + layouts, src
ebeb1a8 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;micro&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;

                    &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;
a451940 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;main&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Minimal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Tiny + collections, js, data, partials, icons
d4996cc &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tiny&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Tiny &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Micro + layouts, src
f636ea3 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt; micro                    minimal
   |                         |
   |                         |
ebeb1a8 ---&gt; 25aaa80 ---&gt; 7c1v8d4
                             |
                             |
                           HEAD


  root        tiny         main
    |           |            |
    |           |            |
f636ea3 ---&gt; d4996cc ---&gt; a451940&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The upper tree is the new (corrected) tree.
The lower tree is the old tree.&lt;/p&gt;
&lt;p&gt;Rebasing took care of pointing
&lt;code&gt;micro&lt;/code&gt; and &lt;code&gt;minimal&lt;/code&gt; to the right commits.&lt;/p&gt;
&lt;p&gt;Now we just need to move the other
three branches to the right commits.
&lt;code&gt;main&lt;/code&gt; and &lt;code&gt;root&lt;/code&gt; are straightforward:
make this look like that.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;minimal &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; branch &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; main minimal
&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;minimal &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; branch &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; root micro&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead of using a specific SHA (&lt;code&gt;25aaa80&lt;/code&gt;) for &lt;code&gt;tiny&lt;/code&gt;,
we’ll describe the commit relative to &lt;code&gt;minimal&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;minimal &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; branch &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; tiny &lt;span class=&quot;token string&quot;&gt;&#39;minimal^&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is what the log looks like:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;minimal &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--oneline&lt;/span&gt; --show-linear-break &lt;span class=&quot;token parameter variable&quot;&gt;--all&lt;/span&gt;
7c128d4 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HEAD -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; minimal, main&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Minimal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Tiny + collections, js, data, partials, icons
25aaa80 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tiny&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Tiny &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Micro + layouts, src
ebeb1a8 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root, micro&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And this is what that looks like:&lt;/p&gt;
&lt;pre class=&quot;language-text&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt; root                      main
   |                         |
 micro        tiny        minimal
   |            |            |
   |            |            |
ebeb1a8 ---&gt; 25aaa80 ---&gt; 7c1v8d4
                             |
                             |
                           HEAD


f636ea3 ---&gt; d4996cc ---&gt; a451940&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The old commits hang around until
they’re garbage collected.
If we wanted to be able to get
back to our original versions,
we could point a branch at
&lt;code&gt;a451940&lt;/code&gt; and get back the entire
state of our tree when we started.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;minimal &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; branch &lt;span class=&quot;token parameter variable&quot;&gt;-f&lt;/span&gt; rescue a451940

&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;minimal &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--oneline&lt;/span&gt; --show-linear-break &lt;span class=&quot;token parameter variable&quot;&gt;--all&lt;/span&gt;
7c128d4 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;HEAD -&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; minimal, main&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Minimal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Tiny + collections, js, data, partials, icons
25aaa80 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tiny&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Tiny &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Micro + layouts, src
ebeb1a8 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;root, micro&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;

                    &lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;..&lt;/span&gt;
a451940 &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rescue&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; Minimal &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Tiny + collections, js, data, partials, icons
d4996cc Tiny &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Micro + layouts, src
f636ea3 Micro &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base .eleventy.js one content &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  <entry>
    <title>Dot Dot notation</title>
    <link href="https://pborenstein.dev/posts/dotdotnotation/" />
    <updated>2020-04-26T02:00:00Z</updated>
    <id>https://pborenstein.dev/posts/dotdotnotation/</id>
    <content type="html">&lt;p&gt;OK, seriously? What is it with the dot notation in git? Given this repo:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;             master
               |
C1---C2---C5---C6
      &#92;
       C3---C4
            |
          topic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How does &lt;code&gt;git log master..topic&lt;/code&gt; mean to display commits &lt;code&gt;C3&lt;/code&gt; and &lt;code&gt;C4&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;Let’s  see if we can make things simpler.&lt;/p&gt;
&lt;h2 id=&quot;a-simple-case&quot;&gt;A simple case&lt;/h2&gt;
&lt;p&gt;Imagine a repo with two branches, &lt;code&gt;master&lt;/code&gt; and &lt;code&gt;topic&lt;/code&gt;. The &lt;code&gt;topic&lt;/code&gt; branch branches off of &lt;code&gt;master&lt;/code&gt;, but there are no new commits on &lt;code&gt;master&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;             master
               |
L1---L2---L3---L4---L5---L6
                         |
                       topic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;git log&lt;/code&gt; output looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-bash#&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash#&quot;&gt;$ git log --oneline --all --graph --decorate
* 0c1d724 (topic) L6
* 5d4cdb5 L5
* ca8cf0a (HEAD -&gt; master) L4
* 019e663 L3
* b1ea04d L2
* 83fd5ca L1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What should we expect the output of &lt;code&gt;git log master..topic&lt;/code&gt; to be?&lt;/p&gt;
&lt;pre class=&quot;language-bash#&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash#&quot;&gt;$ git log --oneline --graph --decorate master..topic
* 0c1d724 (topic) L6
* 5d4cdb5 L5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That looks right. The commits from &lt;code&gt;master&lt;/code&gt; to &lt;code&gt;topic&lt;/code&gt; are &lt;code&gt;L5&lt;/code&gt; and &lt;code&gt;L6&lt;/code&gt; (not including the &lt;code&gt;L6&lt;/code&gt; commit at &lt;code&gt;master&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;OK. What if we reverse the order of the commits?&lt;/p&gt;
&lt;pre class=&quot;language-bash#&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash#&quot;&gt;$ git log --oneline --graph --decorate topic..master
&lt;no output=&quot;&quot;&gt;&lt;/no&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Order matters. The dots seem to denote the passage of time. So &lt;code&gt;master..topic&lt;/code&gt; means:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The commits from &lt;code&gt;master&lt;/code&gt; to &lt;code&gt;topic&lt;/code&gt;&lt;/em&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://pborenstein.dev/posts/dotdotnotation/#fn1&quot; id=&quot;fnref1&quot;&gt;(1)&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then it makes sense that &lt;code&gt;topic..master&lt;/code&gt; produces no output because&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;the commits from &lt;code&gt;topic&lt;/code&gt; to &lt;code&gt;master&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;is nonsensical since &lt;code&gt;topic&lt;/code&gt; comes after &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;now-with-branches&quot;&gt;Now with branches&lt;/h2&gt;
&lt;p&gt;Let’s go back to our first repo:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;             master
               |
C1---C2---C5---C6
      &#92;
       C3---C4
            |
          topic
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What does &lt;code&gt;git log master..topic&lt;/code&gt;, mean in this case?
&lt;em&gt;Commits from &lt;code&gt;master&lt;/code&gt; to &lt;code&gt;topic&lt;/code&gt;&lt;/em&gt; doesn’t make a lot of sense here.&lt;/p&gt;
&lt;p&gt;It turns out that &lt;code&gt;master..topic&lt;/code&gt; is
&lt;a href=&quot;https://git-scm.com/docs/gitrevisions#_dotted_range_notations&quot;&gt;shorthand&lt;/a&gt;
for&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;^master topic&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;See, &lt;code&gt;git log&lt;/code&gt; doesn’t work on sequences of commits. It works on &lt;em&gt;sets&lt;/em&gt; of commits. It’s right there &lt;a href=&quot;https://git-scm.com/docs/gitrevisions#_specifying_ranges&quot;&gt;in the documentation&lt;/a&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://pborenstein.dev/posts/dotdotnotation/#fn2&quot; id=&quot;fnref2&quot;&gt;(2)&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;History-traversing commands, such as &lt;code&gt;git log&lt;/code&gt;, operate on a set of commits, not just a single commit.&lt;/p&gt;
&lt;p&gt;For these commands, specifying a single revision, using the notation described in the previous section, means the set of commits reachable from the given commit.&lt;/p&gt;
&lt;p&gt;A commit’s reachable set is the commit itself and the commits in its ancestry chain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So &lt;code&gt;master..topic&lt;/code&gt; means &lt;code&gt;^master topic&lt;/code&gt;, which means:&lt;/p&gt;
&lt;p&gt;All the commits on &lt;code&gt;topic&lt;/code&gt;:    &lt;code&gt;C1---C2---C3---C4&lt;/code&gt;&lt;br&gt;
Excluding all the commits on &lt;code&gt;master&lt;/code&gt;:    &lt;code&gt;C1---C2---C5---C6&lt;/code&gt;&lt;br&gt;
Which leaves:    &lt;code&gt;C3---C4&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-bash#&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash#&quot;&gt;$ git log --oneline --graph --decorate master..topic
* 703d475 (HEAD -&gt; topic) C4
* 3ffdcab C3&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;footnotes-sep&quot;&gt;&lt;/div&gt;
		&lt;section class=&quot;footnotes&quot;&gt;
		&lt;ol class=&quot;footnotes-list&quot;&gt;&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Not including the &lt;code&gt;master&lt;/code&gt; commit itself. &lt;a href=&quot;https://pborenstein.dev/posts/dotdotnotation/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;If you’re like me, you learned Git by looking at examples and memorizing a handful of Git commands that you use as magic incantations. This post is part of my trying to understand what these magic spells mean. &lt;a href=&quot;https://pborenstein.dev/posts/dotdotnotation/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
</feed>