<?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>davep</title>
    <link>https://blog.davep.org</link>
    <description>Latest posts from davep</description>
    <atom:link href="https://blog.davep.org/feed.xml" rel="self"/>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Sat, 14 Mar 2026 14:32:05 +0000</lastBuildDate>
    <item>
      <title>BlogMore v1.14.0</title>
      <link>https://blog.davep.org/2026/03/14/blogmore-1-14-0.html</link>
      <description>&lt;p&gt;Somehow minor version numbers are tracking the day of the month at the
moment, and that isn't on purpose, but here we are on March 14th with
&lt;a href="https://blogmore.davep.dev" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt; v1.14.0&lt;sup id="fnref:136-1"&gt;&lt;a class="footnote-ref" href="#fn:136-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;This release has a couple of changes: one is directly practical and the
other a little more experimental/hopeful.&lt;/p&gt;
&lt;p&gt;For starters, I've added a &lt;a href="https://blogmore.davep.dev/configuration/#minify_html" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;minify_html&lt;/code&gt;
option&lt;/a&gt;. Having added
minification for CSS and JavaScript files, it made sense to finally do this
for all the HTML that's output too. So, if &lt;code&gt;minify_html&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt; in
the configuration file, &lt;a href="https://blogmore.davep.dev/command_line/#-minify-html" rel="noopener noreferrer" target="_blank"&gt;or &lt;code&gt;--minify-html&lt;/code&gt; is passed on the command
line&lt;/a&gt;, any generated
HTML file will be squished down as much as possible to reduce its overall
byte size.&lt;/p&gt;
&lt;p&gt;Every little helps, right?&lt;/p&gt;
&lt;p&gt;The second change comes from &lt;a href="https://github.com/davep/blogmore/discussions/268" rel="noopener noreferrer" target="_blank"&gt;a
request&lt;/a&gt; that I don't
directly know how to handle, so this is an experiment with allowing for it.
The request was for "themes". Now, from the start, I created BlogMore such
that the templates can be overridden and that custom stylesheets can be
used, but the idea of "themes" suggests something more formal. Allowing for
this and planning for this isn't straightforward because, honestly, I'm no
web developer and no designer.&lt;/p&gt;
&lt;p&gt;So what I have done &lt;a href="https://github.com/davep/blogmore/pull/275" rel="noopener noreferrer" target="_blank"&gt;is try and ensure that the templates and stylesheet
are as sensible as possible&lt;/a&gt; and
then also expand the documentation to &lt;a href="https://blogmore.davep.dev/theming/" rel="noopener noreferrer" target="_blank"&gt;try and make it possible for someone
to step in and write their own theme&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I've also tried to ensure that there are adequate instructions for agents in
the codebase such that no breaking change will be made in the templates and
styling, without this being obvious. The plan here is to keep the core of
the theme support as stable as possible and to adequately alert people to
any breaking change (and, ideally, to never make any breaking change).&lt;/p&gt;
&lt;p&gt;On top of all of that, I've got Copilot to also &lt;a href="https://github.com/davep/blogmore/tree/main/examples/themes" rel="noopener noreferrer" target="_blank"&gt;make three example
themes&lt;/a&gt;. None
are that radical, and I might see if I can coax it into making one or two
more that are a bit wilder, but they should at least be helpful for someone
with skills who feels more adventurous than me (or they might at least work
as examples for an agent so that more themes can be AI-generated).&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:136-1"&gt;
&lt;p&gt;If only it was v3.14... 🥧&amp;#160;&lt;a class="footnote-backref" href="#fnref:136-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/14/blogmore-1-14-0.html</guid>
      <category>Coding</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>BlogMore</category>
      <pubDate>Sat, 14 Mar 2026 14:30:00 +0000</pubDate>
    </item>
    <item>
      <title>BlogMore v1.13.0</title>
      <link>https://blog.davep.org/2026/03/13/blogmore-1-13-0.html</link>
      <description>&lt;p&gt;I wasn't intending to make any changes to
&lt;a href="https://blogmore.davep.dev" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt; today, but as luck would have it
&lt;a href="https://mastodon.me.uk/@andyc" rel="noopener noreferrer" target="_blank"&gt;@andyc&lt;/a&gt; had &lt;a href="https://github.com/davep/blogmore/issues/263" rel="noopener noreferrer" target="_blank"&gt;a feature
request&lt;/a&gt; which made sense and
seemed easy enough to prompt for, &lt;a href="https://github.com/davep/blogmore/pull/266" rel="noopener noreferrer" target="_blank"&gt;so I
did&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So the change is this: if you happen to configure BlogMore such that the
post URLs end up being something that ends in &lt;code&gt;index.html&lt;/code&gt;, if you turn on
&lt;a href="https://blogmore.davep.dev/configuration/#clean_urls" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;clean_urls&lt;/code&gt;&lt;/a&gt;, all
emitted URLs will leave off the &lt;code&gt;index.html&lt;/code&gt;. The result of this is that a
URL that would look like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;https://blog.example.com/posts/my-first-post/index.html&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;can then always look like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;https://blog.example.com/posts/my-first-post/&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words: it gives you a way to have &lt;a href="https://en.wikipedia.org/wiki/Clean_URL" rel="noopener noreferrer" target="_blank"&gt;clean
URLs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is carried through all generated pages and the
&lt;a href="https://blogmore.davep.dev/building/#xml-sitemap" rel="noopener noreferrer" target="_blank"&gt;sitemap&lt;/a&gt; too.&lt;/p&gt;
&lt;p&gt;It's not something I'd personally use for this blog (because it's been
around long enough and has a specific URL layout that I want to keep
working) but I can see it being useful for any future project, and of course
I can see it being useful for anyone else wanting to use BlogMore.&lt;/p&gt;
&lt;p&gt;Another wee change is to make sure that the rebuild-on-change feature of the
local test server always loads any new values set in the configuration file.
While it was reacting to some properties changing, it wasn't reacting to
all; so I &lt;a href="https://github.com/davep/blogmore/issues/267" rel="noopener noreferrer" target="_blank"&gt;asked Copilot to check all the values and make sure all are
handled&lt;/a&gt;.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/13/blogmore-1-13-0.html</guid>
      <category>Coding</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>BlogMore</category>
      <pubDate>Fri, 13 Mar 2026 19:07:00 +0000</pubDate>
    </item>
    <item>
      <title>BlogMore v1.12.0</title>
      <link>https://blog.davep.org/2026/03/12/blogmore-1-12-0.html</link>
      <description>&lt;p&gt;Another day, another tweak to &lt;a href="https://blogmore.davep.dev" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt;. This
bump adds a couple of features relating to headings. The main change being
that &lt;a href="https://github.com/davep/blogmore/pull/260" rel="noopener noreferrer" target="_blank"&gt;I've added support for custom IDs for
links&lt;/a&gt;. To &lt;a href="https://blogmore.davep.dev/writing_a_post/#heading-ids-and-anchor-links" rel="noopener noreferrer" target="_blank"&gt;borrow from the
docs&lt;/a&gt;:&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;If you need a specific &lt;code&gt;id&lt;/code&gt; — for example because the auto-generated one is
too long, or because you want a stable &lt;code&gt;id&lt;/code&gt; that won't change if you reword
the heading — you can set it explicitly by appending &lt;code&gt;{#your-id}&lt;/code&gt; to the end
of the heading line:&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="gu"&gt;### My Great Heading {#custom-id}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;This produces:&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;custom-id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;My Great Heading&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h3&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;The custom &lt;code&gt;id&lt;/code&gt; overrides the auto-generated one. Headings without a &lt;code&gt;{#…}&lt;/code&gt;
suffix keep their auto-generated IDs as usual.&lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Headings, of course, have a default "slugged" ID if a custom one isn't
provided.&lt;/p&gt;
&lt;p&gt;The other main change is that it's now easier for a reader to discover a
link to a heading should they want to link someone to a specific part of a
post or page. Again, to borrow from the docs:&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;To make it easy for readers to share a link to a specific section, BlogMore
renders a small &lt;/em&gt;&lt;em&gt;¶&lt;/em&gt;&lt;em&gt; symbol at the end of every heading. The symbol is
invisible by default and appears when the reader moves the mouse over the
heading. Clicking the symbol navigates the browser to that heading's URL
fragment, where the address can be copied from the browser's location bar.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The anchor appears and disappears with a smooth fade and does not affect
the layout of the page in any way.&lt;/em&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Another small change I added was to the "&lt;em&gt;Generated by BlogMore"&lt;/em&gt; text that
appears at the bottom of every generated page. I always think it's nice if
some tool lets you turn that sort of thing off, and I'd not paid attention
to that yet. So as of v1.12.0 you can add this to the configuration file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;with_advert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and you then don't have to have that at the bottom of each page.&lt;/p&gt;
&lt;p&gt;Credit BlogMore if you want, but you don't have to.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/12/blogmore-1-12-0.html</guid>
      <category>Coding</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>BlogMore</category>
      <pubDate>Thu, 12 Mar 2026 21:37:00 +0000</pubDate>
    </item>
    <item>
      <title>BlogMore v1.11.0</title>
      <link>https://blog.davep.org/2026/03/11/blogmore-1-11-0.html</link>
      <description>&lt;p&gt;I was going to call this one "Yet more BlogMore" but I think, even after two
posts with that naming scheme, the "...more BlogMore" thing has had its day.
But here I am: another day, another wee change to the blogging engine I'm
building as an experiment with developing using AI.&lt;/p&gt;
&lt;p&gt;Just a couple of simple changes in this release. The first comes from the
fact that I was updating my blog to include more of the "socials" icons (the
ones you'll see towards the bottom of the sidebar if you're on a wide enough
display, or in the collapsible header if not) and when I deployed some were
missing. Which, after a moment of puzzling, made sense.&lt;/p&gt;
&lt;p&gt;See: I made a change a while back such that &lt;a href="https://github.com/davep/blogmore/pull/155" rel="noopener noreferrer" target="_blank"&gt;I stopped using the full
FontAwesome stylesheet, and instead only used a specially-built
subset&lt;/a&gt;. This is handy in that
it really reduces how much data goes into a page. But the downside, of
course, is the browser will cache this file; so if you then add more
"brands" to the list their icons will be missing until the cached version of
the old generation of the CSS file goes stale.&lt;/p&gt;
&lt;p&gt;So in this release &lt;a href="https://github.com/davep/blogmore/pull/253" rel="noopener noreferrer" target="_blank"&gt;I've added a generation-based cache
buster&lt;/a&gt;; it's just the simple
&lt;code&gt;?v=thing&lt;/code&gt; approach but it should work fine for what I need here.&lt;/p&gt;
&lt;p&gt;The other change is &lt;a href="https://github.com/davep/blogmore/pull/252" rel="noopener noreferrer" target="_blank"&gt;I've added the generated FontAwesome CSS file to the
list of files that get optionally minified at generation
time&lt;/a&gt;. While it's not a massive
change in terms of the total amount of data that gets pulled down, every
little helps.&lt;/p&gt;
&lt;p&gt;I feel like, at this point, I've managed to add everything I could possibly
want from this little static site generator; yet somehow each day I have a
new idea and off I go again.&lt;/p&gt;
&lt;p&gt;It'll be finished soon. I'm sure.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/11/blogmore-1-11-0.html</guid>
      <category>Coding</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>BlogMore</category>
      <pubDate>Wed, 11 Mar 2026 20:39:00 +0000</pubDate>
    </item>
    <item>
      <title>Even more BlogMore</title>
      <link>https://blog.davep.org/2026/03/10/even-more-blogmore.html</link>
      <description>&lt;p&gt;While the additions have, for sure, slowed down, I'm still tinkering away
with &lt;a href="https://blogmore.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt;. Recent changes stem from the
fact that someone else has been mad enough to want to experiment with
rebuilding their blog with it too, which, if I'm honest, is massively
helpful with the ongoing GitHub Copilot experiment. Somehow it feels a
little different, ganging up with the agent to implement changes for someone
else's benefit.&lt;/p&gt;
&lt;p&gt;Recent changes include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tweaking the size and layout of the "social" icons that appear in the
  sidebar (this one was for my benefit)&lt;/li&gt;
&lt;li&gt;Making it possible to customise the title for the socials section in the
  sidebar (also for my benefit)&lt;/li&gt;
&lt;li&gt;Providing &lt;a href="https://blogmore.davep.dev/configuration/#post_path" rel="noopener noreferrer" target="_blank"&gt;control over the path used for
  posts&lt;/a&gt; -- this one
  was a request that made a ton of sense, it's at this point it stops being
  a tool for me and starts being a more general tool&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next up is the first breaking change where I'm going to remove a feature.
This came from my very initial experiment last month, where I was
concentrating purely on building a tool for my blog and my blog alone. I'd
made it such that the &lt;code&gt;/attachments&lt;/code&gt; directory in the content directory had
special status, and it would be copied over to the output directory in full.
Oddly, however, this never made it into the documentation.&lt;/p&gt;
&lt;p&gt;Meanwhile, the &lt;code&gt;/extras&lt;/code&gt; directory &lt;em&gt;also&lt;/em&gt; had special status with its
content, full hierarchy included, being copied over but &lt;em&gt;moved up one level&lt;/em&gt;
in the output. So, for example, &lt;code&gt;extras/humans.txt&lt;/code&gt; became &lt;code&gt;/humans.txt&lt;/code&gt; in
the resulting site, etc.&lt;/p&gt;
&lt;p&gt;Presumably, at this point, you can see where this is going. Why the heck did
I have a special &lt;code&gt;attachments&lt;/code&gt; folder being copied over, when a folder of
any name could live below &lt;code&gt;extras&lt;/code&gt; and also get copied over?&lt;/p&gt;
&lt;p&gt;So, now, my blog, which uses &lt;code&gt;/attachments&lt;/code&gt; for all inline images and
covers, has been updated so that &lt;a href="https://github.com/davep/davep.github.com/tree/main/content/extras" rel="noopener noreferrer" target="_blank"&gt;the attachments live under
extras&lt;/a&gt;
and it all works as it did before; no special messing with a special folder
name.&lt;/p&gt;
&lt;p&gt;Given all this, the next release of BlogMore will remove treating
&lt;code&gt;/attachments&lt;/code&gt; as a special case, making it less hard-coded for my habits
and more of a general tool that could be useful for others.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Mildly related to this: I did a lunchtime talk at work today, having turned
&lt;a href="https://blog.davep.org/2026/02/20/five-days-with-copilot.html"&gt;Five days with Copilot&lt;/a&gt; into a
20-25 minute presentation. It was fun to do. I've not written or given a
talk or presentation in a long time -- probably the last time was when I
helped run Newton's Astronomical Society in the early 2000s -- so the
preparation for this was a little daunting to start with.&lt;/p&gt;
&lt;p&gt;While doing this, not wanting to break a long streak of never having used
PowerPoint, I discovered and gave &lt;a href="https://sli.dev" rel="noopener noreferrer" target="_blank"&gt;sli.dev&lt;/a&gt; a go. Writing a
single Markdown file to power the talk was exactly my kind of approach. I
don't have any experience with any other such tools, but if you're ever
looking for something like this I recommend giving it a try.&lt;/p&gt;
&lt;p&gt;I'm also open to suggestions of other options, given I might end up doing
this some more.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/10/even-more-blogmore.html</guid>
      <category>Coding</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>BlogMore</category>
      <pubDate>Tue, 10 Mar 2026 20:58:00 +0000</pubDate>
    </item>
    <item>
      <title>You get what you pay for</title>
      <link>https://blog.davep.org/2026/03/10/you-get-what-you-pay-for.html</link>
      <description>&lt;p&gt;Just recently I saw a post go past on Mastodon, complaining about the
author's perception that there was a breakdown of trust in the FOSS world,
in respect to the use of AI to work on FOSS projects, or at least the
willingness to accept AI-assisted contributions. The post also highlighted
the author's reliance on FOSS projects and how they're driven by ethical and
financial motivations (some emphasis was placed on how they had no money to
spend on these things so it wasn't even necessarily a choice to FOSS up
their environment).&lt;/p&gt;
&lt;p&gt;This was, of course, in response to the &lt;a href="https://hachyderm.io/@AndrewRadev/116175986749599825" rel="noopener noreferrer" target="_blank"&gt;current fuss about how Vim is being
developed these days&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I don't want to comment on the Vim stuff -- &lt;a href="https://elisp.dev/" rel="noopener noreferrer" target="_blank"&gt;I've got no dog in that
fight&lt;/a&gt; -- but something about the post I mention above
got me thinking, and troubled me.&lt;/p&gt;
&lt;p&gt;Back when I first ran into the concept of &lt;a href="https://www.gnu.org/philosophy/free-sw.en.html" rel="noopener noreferrer" target="_blank"&gt;Free
Software&lt;/a&gt;, before the
concept of Open Source had ever been thought of, I can remember reading
stuff opposed to the idea that mostly worked along the lines of &lt;em&gt;"you get
what you pay for"&lt;/em&gt; -- the implication being that Free Software would be bad
software. I think it's fair to say that history has now shown that this
isn't the case.&lt;/p&gt;
&lt;p&gt;But... I think it's fair to say that you &lt;em&gt;do&lt;/em&gt; get what you pay for, but in a
different sense.&lt;/p&gt;
&lt;p&gt;If your computing environment is fully reliant on the time, money and effort
of others; reliant on people who are willing to give all of that without the
realistic expectation of any contribution back from you; I feel it's safe to
say that you are getting a bloody good deal. To then question the
motivations and abilities of those people, &lt;em&gt;because they are exploring and
embracing other methods of working&lt;/em&gt;, is at best a bad-faith argument and at
worst betrays a deep sense of entitlement.&lt;/p&gt;
&lt;p&gt;What I also found wild was, the post went on to document the author's
concerns that they now have to worry about the ability of FOSS project
maintainers to detect bad contributions. This for me suggests a lack of
understanding of how non-trivial FOSS projects have worked ever since it was
a thing.&lt;/p&gt;
&lt;p&gt;I mean, sure, there are some projects that are incredibly useful and which
have a solo developer working away (sometimes because nobody else wants to
contribute, but also sometimes because that solo developer doesn't play well
with others -- you pick which scenario you think is more healthy), but for
the most part the "important" projects have multitudes working on them, with
contributions coming from many people of varying levels of ability. The
point here being that, all along, you've been relying on the discernment and
mentoring abilities of those maintainers.&lt;/p&gt;
&lt;p&gt;To suggest they're suddenly unworthy of your trust because they might be
"using the AIs" is... well, it feels driven by dogma and it reads like a
disingenuous take.&lt;/p&gt;
&lt;p&gt;Don't get me wrong though: you are &lt;em&gt;right&lt;/em&gt; to be suspicious, you are right
to want to question the trust you place in those who donate so much to you;
almost always &lt;a href="https://opensource.org/licenses" rel="noopener noreferrer" target="_blank"&gt;this is made explicit in the licence they extended to you in
the first place&lt;/a&gt;. But to suggest that
suddenly they're unworthy of your trust because they're donating so much
value &lt;em&gt;to you&lt;/em&gt; in a way &lt;em&gt;you&lt;/em&gt; don't approve of...&lt;/p&gt;
&lt;p&gt;...well, perhaps it's time for you to pay it back?&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/10/you-get-what-you-pay-for.html</guid>
      <category>AI</category>
      <category>AI</category>
      <category>LLM</category>
      <category>FOSS</category>
      <pubDate>Tue, 10 Mar 2026 09:00:00 +0000</pubDate>
    </item>
    <item>
      <title>An eager fix</title>
      <link>https://blog.davep.org/2026/03/09/an-eager-fix.html</link>
      <description>&lt;p&gt;&lt;img alt="An eager fix" src="https://blog.davep.org/attachments/2026/03/09/changes.png#centre" /&gt;&lt;/p&gt;
&lt;p&gt;Yesterday, &lt;a href="https://blog.davep.org/2026/03/09/seen-by-me-revived.html"&gt;while looking at starting to post to my photoblog
again&lt;/a&gt;, I noticed I'd missed a trick
when I added the &lt;a href="https://blog.davep.org/2026/03/03/original-seen-by-davep-rescued.html"&gt;first&lt;/a&gt;
and &lt;a href="https://blog.davep.org/2026/03/02/seen-by-rescued.html"&gt;second&lt;/a&gt; sets of photos when I
created &lt;a href="https://seen-by.davep.dev" rel="noopener noreferrer" target="_blank"&gt;seen-by.davep.dev&lt;/a&gt;: I'd left off any
&lt;code&gt;cover&lt;/code&gt; frontmatter from all of the posts!&lt;/p&gt;
&lt;p&gt;While I doubt it's super important -- I can't imagine people will be sharing
photos from the blog after all, especially not older ones -- it felt like
I'd failed to use &lt;a href="https://blogmore.davep.dev/writing_a_post/#cover" rel="noopener noreferrer" target="_blank"&gt;a useful
feature&lt;/a&gt; that I'd made
sure &lt;a href="https://blogmore.davep.dev" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt; had.&lt;/p&gt;
&lt;p&gt;This was obviously easy to fix. I could just write a tool that would go
through all of the Markdown files, find the image that is being displayed in
the post, pull out the path to the file, and add a &lt;code&gt;cover&lt;/code&gt; to the
frontmatter. Not exactly the hardest thing to write, but kind of boring for
a one-off fix.&lt;/p&gt;
&lt;p&gt;So this felt like another good time to get Copilot to do the hard work.
Liking this plan, I &lt;a href="https://github.com/davep/seen-by/issues/7" rel="noopener noreferrer" target="_blank"&gt;wrote an issue for the
prompt&lt;/a&gt; and set it to work.&lt;/p&gt;
&lt;p&gt;The result was unexpected, and in retrospect this is how I should have
approached it in the first place; Copilot wrote the script, then ran it, and
then submitted the PR &lt;em&gt;including the script and all of the changes after
running it!&lt;/em&gt; It's like it was super eager to do the fix so went ahead and
just did it.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The resulting PR" src="https://blog.davep.org/attachments/2026/03/09/cover-eager.png#centre" /&gt;&lt;/p&gt;
&lt;p&gt;This, for me, highlights a trick/approach I'm still not fully mindful of:
where I might once have written some throwaway code to do a job, run the
code, and then made use of the result, when it comes to using an agent I
always have the option of saying &lt;em&gt;what&lt;/em&gt; I want done to the content of the
repository and just let it do it.&lt;/p&gt;
&lt;p&gt;When I'm next faced with a problem like this, I think this is the approach
I'll take: rather than ask it to write the tool to do the work, I'll just
say what the work is I want done and let it go about it. &lt;em&gt;This&lt;/em&gt; feels like
where an agent should shine and where it's really useful.&lt;/p&gt;
&lt;p&gt;Meanwhile I can get on with the fun stuff.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/09/an-eager-fix.html</guid>
      <category>AI</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>GitHub</category>
      <pubDate>Mon, 09 Mar 2026 12:56:00 +0000</pubDate>
    </item>
    <item>
      <title>Seen by davep revived</title>
      <link>https://blog.davep.org/2026/03/09/seen-by-me-revived.html</link>
      <description>&lt;p&gt;&lt;img alt="A different glen" src="https://blog.davep.org/attachments/2026/03/09/a-different-glen.jpeg#centre" /&gt;&lt;/p&gt;
&lt;p&gt;Following on from the &lt;a href="https://blog.davep.org/2026/03/02/seen-by-rescued.html"&gt;rescue of my
photoblog&lt;/a&gt;, followed by the &lt;a href="https://blog.davep.org/2026/03/03/original-seen-by-davep-rescued.html"&gt;rescue of the
original incarnation&lt;/a&gt;, I've
been thinking that I should get into the habit of posting the odd image here
and there again, when the desire takes me.&lt;/p&gt;
&lt;p&gt;The problem is the workflow. The point and purpose of the last two
incarnations was that I just had to take image, manipulate image, post image
and then lots of other things would happen. As I've mentioned in the posts
linked to here, and &lt;a href="https://blog.davep.org/tag/photoblog.html"&gt;others here on this blog&lt;/a&gt;, it's
much harder these days to achieve that seamless and frictionless workflow we
used to enjoy during the rise and the peak of "Web 2.0".&lt;/p&gt;
&lt;p&gt;So yesterday I decided on an approach that, while it's neither seamless nor
frictionless (yet), it feels like it will work. So here's the plan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Take photo&lt;/li&gt;
&lt;li&gt;Manipulate photo&lt;sup id="fnref:138-1"&gt;&lt;a class="footnote-ref" href="#fn:138-1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;In Apple Photos add a description to the image&lt;/li&gt;
&lt;li&gt;Export JPEG file to a &lt;code&gt;Photoblog Inbox&lt;/code&gt; folder in iCloud Drive&lt;/li&gt;
&lt;li&gt;Later, when I'm at my desk, &lt;a href="https://github.com/davep/seen-by/blob/main/impimg.py" rel="noopener noreferrer" target="_blank"&gt;import the image into the
  photoblog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Publish the updated blog&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, yeah, more manual steps are required, at least for the moment. I suspect
though that if this works well I might be able to increase the automation
involved &lt;em&gt;and&lt;/em&gt; do it in such a way that I'm in control of the steps and
services (or at least I'll be able to do it in a way that I can swap out a
step should whatever service being be lost).&lt;/p&gt;
&lt;p&gt;As an aside, for anyone who might have been following along with &lt;a href="https://blog.davep.org/tag/copilot.html"&gt;my
experiments with GitHub Copilot&lt;/a&gt;: the import tool I link
to above was &lt;a href="https://github.com/davep/seen-by/issues/5" rel="noopener noreferrer" target="_blank"&gt;written from a
prompt&lt;/a&gt;. This, for me, feels like
the ideal use for such a tool. Writing that script &lt;em&gt;was&lt;/em&gt; going to be a chore,
I wanted to get on with the bigger picture thing, so asking Copilot to write
it while I attended to other things felt sensible and useful.&lt;/p&gt;
&lt;p&gt;I'll likely tidy up the code soon, but for now what was produced works and
it let me try all of this out in the time I had available on an otherwise
busy Sunday afternoon.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:138-1"&gt;
&lt;p&gt;Still using &lt;a href="https://en.wikipedia.org/wiki/Snapseed" rel="noopener noreferrer" target="_blank"&gt;Snapseed&lt;/a&gt;.
Snapseed is always fun for evoking the mood.&amp;#160;&lt;a class="footnote-backref" href="#fnref:138-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/09/seen-by-me-revived.html</guid>
      <category>Creative</category>
      <category>blogging</category>
      <category>photography</category>
      <category>BlogMore</category>
      <category>posterous</category>
      <category>photoblog</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <pubDate>Mon, 09 Mar 2026 09:00:00 +0000</pubDate>
    </item>
    <item>
      <title>More BlogMore</title>
      <link>https://blog.davep.org/2026/03/07/more-blogmore.html</link>
      <description>&lt;p&gt;I've just released v1.7.0 of &lt;a href="https://blogmore.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt;, my
ongoing experiment with &lt;a href="https://blog.davep.org/tag/copilot.html"&gt;GitHub Copilot&lt;/a&gt;. Since &lt;a href="https://blog.davep.org/2026/03/03/blogmore-1-5-0.html"&gt;the last
release I wrote about&lt;/a&gt; I've made a couple
of cosmetic changes, and also addressed a couple of bugs.&lt;/p&gt;
&lt;p&gt;The first cosmetic change relates to how the blog appears on mobile
devices&lt;sup id="fnref:150-1"&gt;&lt;a class="footnote-ref" href="#fn:150-1"&gt;1&lt;/a&gt;&lt;/sup&gt;. In such a circumstance, before the change, the sidebar content
would, by design, relocate to the top of the page. This made sense, it meant
that the information was still available, but it also had the unfortunate
effect of pushing the actual post content way down the screen, sometimes off
the bottom of the screen.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The expanded view" src="https://blog.davep.org/attachments/2026/03/07/mobile-expanded.png#centre" /&gt;&lt;/p&gt;
&lt;p&gt;Not great.&lt;/p&gt;
&lt;p&gt;So I decided to &lt;a href="https://github.com/davep/blogmore/pull/202" rel="noopener noreferrer" target="_blank"&gt;try and improve the mobile
layout&lt;/a&gt;. As I have done so many
times now, I &lt;a href="https://github.com/davep/blogmore/issues/201" rel="noopener noreferrer" target="_blank"&gt;started out with an issue that served as a
prompt&lt;/a&gt; and assigned it to
Copilot; despite the fairly vague request and the fact that I gave it an
image to consider, and essentially gave it a hand-waved ASCII diagram of
what I wanted, it mostly managed to one-shot the problem.&lt;/p&gt;
&lt;p&gt;Now, when I visit the site on my phone, I see a lot less "admin" stuff at
the start.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The collapsed view" src="https://blog.davep.org/attachments/2026/03/07/mobile-collapsed.png#centre" /&gt;&lt;/p&gt;
&lt;p&gt;As a reader I can still toggle the "sidebar" information into view and out
of the way again, but the important thing is I can get into the post itself
right away.&lt;/p&gt;
&lt;p&gt;Another change that's mostly cosmetic, although has a purpose too, is an
index in the archive page. I've created this to &lt;em&gt;only&lt;/em&gt; be available on wider
displays; a tool to make use of any "dead" space on the right hand side of
the page. This gives a table of contents of years and months so the reader
can skip around the archives faster.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The archive table of contents" src="https://blog.davep.org/attachments/2026/03/07/archive.png#centre" /&gt;&lt;/p&gt;
&lt;p&gt;There have been some under-the-hood changes too. One was an effort to
&lt;a href="https://github.com/davep/blogmore/issues/220" rel="noopener noreferrer" target="_blank"&gt;reduce the repeated boilerplate that I noticed was creeping into the
templates&lt;/a&gt;. While I'm mainly
building this tool for myself and the "out of the box" design is how I want
my blog to look, I do want the templates to be usable and as efficient and
as easy to modify as possible.&lt;/p&gt;
&lt;p&gt;As mentioned earlier, there's also been a couple of bug fixes; one example
being &lt;a href="https://github.com/davep/blogmore/issues/212" rel="noopener noreferrer" target="_blank"&gt;tackling some misbehaviour on
GNU/Linux&lt;/a&gt; when it comes to
site generation. That issue was an interesting one in that I wasn't able to
reproduce the problem, so I decided to let Copilot have at it and make its
best deduction. From what I can tell it came through (I still need
confirmation that it has solved the problem; but it does seem to have
identified an actual edge-case that was worth taking care of).&lt;/p&gt;
&lt;p&gt;At this point I'd also like to give a shout out to
&lt;a href="https://mastodon.me.uk/@andyc" rel="noopener noreferrer" target="_blank"&gt;@andyc&lt;/a&gt;. He's been a great source of testing
and feedback as I've been toying with this experiment. While I set out to
build a useful tool for me and me alone, he's raised a few good issues that
should push it in the direction of being of more general use.&lt;/p&gt;
&lt;p&gt;I highly recommend &lt;a href="https://www.yakshaving.co.uk/posts/fun-with-static-site-generators/" rel="noopener noreferrer" target="_blank"&gt;having a read of his post reviewing a good number of
static site
generators&lt;/a&gt;.
As I keep tinkering with BlogMore I'll be keeping this post in mind.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:150-1"&gt;
&lt;p&gt;Okay fine any narrow viewport but you know what I mean!&amp;#160;&lt;a class="footnote-backref" href="#fnref:150-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/07/more-blogmore.html</guid>
      <category>Coding</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>BlogMore</category>
      <pubDate>Sat, 07 Mar 2026 11:06:00 +0000</pubDate>
    </item>
    <item>
      <title>Zensical</title>
      <link>https://blog.davep.org/2026/03/06/zensical.html</link>
      <description>&lt;p&gt;After first getting involved with &lt;a href="https://blog.davep.org/tag/textual.html"&gt;Textual&lt;/a&gt;, &lt;a href="https://blog.davep.org/2022/10/05/on-to-something-new-redux.html"&gt;back in
2022&lt;/a&gt;, I became acquainted with
&lt;a href="https://www.mkdocs.org" rel="noopener noreferrer" target="_blank"&gt;MkDocs&lt;/a&gt;/&lt;a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener noreferrer" target="_blank"&gt;mkdocs-material&lt;/a&gt;.
It was being used for the (then still being written) &lt;a href="https://textual.textualize.io/" rel="noopener noreferrer" target="_blank"&gt;Textual
docs&lt;/a&gt;, and I really liked how they looked.&lt;/p&gt;
&lt;p&gt;Eventually I adopted this combination for &lt;a href="https://github.com/davep?tab=repositories&amp;amp;q=&amp;amp;type=source&amp;amp;language=python&amp;amp;sort=" rel="noopener noreferrer" target="_blank"&gt;many of my own
projects&lt;/a&gt;,
&lt;a href="https://blog.davep.org/2023/08/11/the-reboot-begins.html"&gt;and even adopted it for the replacement for
davep.org&lt;/a&gt;. It's turned into one of
those tools that I heavily rely on, but seldom actually interact with. It's
just there, it does its job and it does it really well.&lt;/p&gt;
&lt;p&gt;Recently though, while working on &lt;a href="https://oldnews.davep.dev" rel="noopener noreferrer" target="_blank"&gt;OldNews&lt;/a&gt;,
something changed. When I was working on or building the docs, I saw this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="MkDocs warning" src="https://blog.davep.org/attachments/2026/03/06/mkdocs.png#centre" /&gt;&lt;/p&gt;
&lt;p&gt;This was... new. So I visited &lt;a href="https://squidfunk.github.io/mkdocs-material/blog/2026/02/18/mkdocs-2.0/" rel="noopener noreferrer" target="_blank"&gt;the
link&lt;/a&gt;
and I was, if I'm honest, none the wiser. I've read it a few times since,
and done a little bit of searching, and I still really don't understand what
the heck is going on or why a tool I'm using is telling me not to use itself
but to use a different tool. Like, really, why would MkDocs tell me not to
use MkDocs but to use a different tool? Or was it actually MkDocs telling me
this?&lt;sup id="fnref:135-1"&gt;&lt;a class="footnote-ref" href="#fn:135-1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Really, I don't get it.&lt;/p&gt;
&lt;p&gt;Anyway, I decided to wave it away as some FOSS drama&lt;sup id="fnref:135-2"&gt;&lt;a class="footnote-ref" href="#fn:135-2"&gt;2&lt;/a&gt;&lt;/sup&gt;, muse about it for
a moment, and carry on and worry about it later. However, I did &lt;a href="https://fosstodon.org/@davep/116108463886885742" rel="noopener noreferrer" target="_blank"&gt;toot about
my confusion&lt;/a&gt; and the
&lt;a href="https://blog.davep.org/2025/02/28/documenting-fspicker.html"&gt;ever&lt;/a&gt;-&lt;a href="https://blog.davep.org/2025/02/28/mkdocs-gh-pages-redux.html"&gt;helpful&lt;/a&gt;
&lt;a href="https://fosstodon.org/@pawamoy" rel="noopener noreferrer" target="_blank"&gt;Timothée&lt;/a&gt; gave a couple of pointers. He
&lt;a href="https://fosstodon.org/@pawamoy/116108984879010894" rel="noopener noreferrer" target="_blank"&gt;mentioned&lt;/a&gt; that
&lt;a href="https://zensical.org" rel="noopener noreferrer" target="_blank"&gt;Zensical&lt;/a&gt; was a drop-in replacement here.&lt;/p&gt;
&lt;p&gt;Again, not having paid too much attention to what the heck was going on, I
filed away this bit of advice and promised myself I'd come back to this at
some point soon.&lt;/p&gt;
&lt;p&gt;Fast-forward to yesterday and, having bumped into &lt;a href="https://www.reddit.com/r/Python/comments/1rl5kuq/anyone_know_whats_up_with_httpx/" rel="noopener noreferrer" target="_blank"&gt;another little bit of
FOSS
drama&lt;/a&gt;,
I was reminded that I should go back and look at Zensical (because I was
reminded that there's always the chance your "supply chain" can let you
down). Given that &lt;a href="https://blogmore.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt; is the thing I'm
actively messing with at the moment, and given &lt;a href="https://blog.davep.org/2026/03/05/documentation-generation.html"&gt;the documentation is in a
state of flux&lt;/a&gt;, I thought I'd
drop the "drop-in" into that project.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/davep/blogmore/pull/215/changes" rel="noopener noreferrer" target="_blank"&gt;The result&lt;/a&gt; was, more
or less, that it was a drop-in replacement. I &lt;em&gt;did&lt;/em&gt; have to change
&lt;code&gt;$(mkdocs) serve --livereload&lt;/code&gt; to drop the &lt;code&gt;--livereload&lt;/code&gt; switch (Zensical
doesn't accept it, and I'd only added it to MkDocs recently because it
seemed to stop doing that by default), but other than that... tool name swap
and that's it.&lt;/p&gt;
&lt;p&gt;Testing locally the resulting site -- while themed slightly differently (and
I do like how it looks) -- worked just as it did before; which is exactly
what I was wanting to see.&lt;/p&gt;
&lt;p&gt;There was one wrinkle though: when it came to publishing to GitHub pages:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;uv run zensical gh-deploy

Usage: zensical [OPTIONS] COMMAND [ARGS]...
Try &amp;#39;zensical --help&amp;#39; for help.

Error: No such command &amp;#39;gh-deploy&amp;#39;.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Oh! No support for deploying to the &lt;code&gt;gh-pages&lt;/code&gt; branch, like MkDocs has! For
a moment this felt like a bit of a show-stopper; but then I remembered that
&lt;a href="https://blog.davep.org/2025/02/28/mkdocs-gh-pages-redux.html"&gt;MkDocs' publishing command&lt;/a&gt; simply
makes use of &lt;a href="https://github.com/c-w/ghp-import" rel="noopener noreferrer" target="_blank"&gt;ghp-import&lt;/a&gt; and so &lt;a href="https://github.com/davep/blogmore/pull/216/changes" rel="noopener noreferrer" target="_blank"&gt;I
swapped to that&lt;/a&gt; and I
was all good.&lt;/p&gt;
&lt;p&gt;So, yeah, so far... I think it's fair to say that Zensical &lt;em&gt;has&lt;/em&gt; been a
drop-in replacement for the MkDocs/mkdocs-material combo. Moreover, if the
impending problems are as bad as the blog post in the warning suggests, I'm
grateful to this effort; in the long run this is going to save a lot of
faffing around.&lt;/p&gt;
&lt;p&gt;The next test will be to try &lt;a href="https://hike.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;the docs for something like
Hike&lt;/a&gt;. They're a little bit more involved, with
&lt;a href="https://github.com/davep/hike/blob/f5748ee97ee2e6928c08f28b1fb4e6e607db6b5e/docs/source/index.md#L3-L4" rel="noopener noreferrer" target="_blank"&gt;SVG-based screenshots being generated at build
time&lt;/a&gt;,
etc. If that just works out of the box too, without incident, I think I'm
all sorted.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:135-1"&gt;
&lt;p&gt;Turns out that it was Material for MkDocs doing this; I wish the
warning had said this.&amp;#160;&lt;a class="footnote-backref" href="#fnref:135-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:135-2"&gt;
&lt;p&gt;It's not the first I've seen in my years, and I doubt it'll be the
last.&amp;#160;&lt;a class="footnote-backref" href="#fnref:135-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/06/zensical.html</guid>
      <category>Coding</category>
      <category>documentation</category>
      <category>GitHub</category>
      <category>mkdocs</category>
      <category>mkdocstrings</category>
      <category>gh-pages</category>
      <pubDate>Fri, 06 Mar 2026 11:35:00 +0000</pubDate>
    </item>
    <item>
      <title>Documentation generation</title>
      <link>https://blog.davep.org/2026/03/05/documentation-generation.html</link>
      <description>&lt;p&gt;While I've written a &lt;em&gt;lot&lt;/em&gt; of documentation in my life, it's not something I
enjoy. I want documentation to read well, I want documentation to be useful,
I want documentation to be accurate. I also want there to be documentation
at all and sometimes the other parts mean it doesn't get done for FOSS
projects&lt;sup id="fnref:155-1"&gt;&lt;a class="footnote-ref" href="#fn:155-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;When &lt;a href="https://blog.davep.org/2026/02/20/five-days-with-copilot.html"&gt;I started the experiment that is
BlogMore&lt;/a&gt;, I very quickly &lt;a href="https://github.com/davep/blogmore/pull/100" rel="noopener noreferrer" target="_blank"&gt;hashed
out some ideas on how it might generate some
documentation&lt;/a&gt;, and the result
was okay. In fact, if anything, it was a bit too much and there was a lot of
repeated information.&lt;/p&gt;
&lt;p&gt;So, this morning, before I sat down for the day's work, I &lt;a href="https://github.com/davep/blogmore/issues/209" rel="noopener noreferrer" target="_blank"&gt;quickly wrote an
issue&lt;/a&gt; that would act as a
prompt to Copilot to rewrite the documentation. This time I tried to be very
clear about what I wanted where, but also left it to work out all the
details.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/davep/blogmore/pull/210" rel="noopener noreferrer" target="_blank"&gt;The result&lt;/a&gt; genuinely impressed
me. While I'll admit I haven't read it all in detail (and because of this
have left the same warning right at the start), on the surface it looks a
lot clearer and feels like a better journey to learning how to use BlogMore.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blogmore.davep.dev" rel="noopener noreferrer" target="_blank"&gt;blogmore.davep.dev&lt;/a&gt; hosts the result of this.&lt;/p&gt;
&lt;p&gt;I have a plan to work through the documentation and be sure it's all correct
and all makes sense, but if it's as correct and as useful as I think, I
might have to consider the idea of taking this approach more often. Writing
down the &lt;em&gt;plan&lt;/em&gt; for the documentation and then letting it appear in the
background while I get on with my actual day makes a lot of sense.&lt;/p&gt;
&lt;p&gt;I fear I might be warming to these tools, a little bit. :-/&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:155-1"&gt;
&lt;p&gt;Although I've made a point of doing it for almost every one of my
recent &lt;a href="https://blog.davep.org/tag/textual.html"&gt;Textual&lt;/a&gt;-based projects.&amp;#160;&lt;a class="footnote-backref" href="#fnref:155-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/05/documentation-generation.html</guid>
      <category>AI</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>GitHub</category>
      <category>BlogMore</category>
      <pubDate>Thu, 05 Mar 2026 16:26:00 +0000</pubDate>
    </item>
    <item>
      <title>BlogMore v1.5.0</title>
      <link>https://blog.davep.org/2026/03/03/blogmore-1-5-0.html</link>
      <description>&lt;p&gt;Since switching over on the &lt;a href="https://blog.davep.org/2026/02/19/a-new-engine.html"&gt;19th of last
month&lt;/a&gt; I've been making lots of changes to
BlogMore. While there's been a good few bug fixes and QoL changes, I've also
been adding new features that I've found myself wanting.&lt;/p&gt;
&lt;p&gt;Here's a list of some of the significant additions I've added in the last
couple of weeks (and, yes, as per the experiment, &lt;em&gt;all&lt;/em&gt; of these have been
developed by me prompting GitHub Copilot):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All parts of a date in a post's timestamp can be clicked to get to an
  archive of that point in time.&lt;/li&gt;
&lt;li&gt;Added fully-client-side full text search (I'm finding this especially
  useful).&lt;/li&gt;
&lt;li&gt;Added sitemap generation.&lt;/li&gt;
&lt;li&gt;Added a general fallback description for any page that doesn't have one.&lt;/li&gt;
&lt;li&gt;Added fallback keywords for any page that doesn't have any.&lt;/li&gt;
&lt;li&gt;Added author metadata to the header of all pages.&lt;/li&gt;
&lt;li&gt;Hugely optimised the use of FontAwesome.&lt;/li&gt;
&lt;li&gt;Made best possible use of all the usual &lt;code&gt;og:&lt;/code&gt; type metadata in the &lt;code&gt;head&lt;/code&gt;
  of all pages.&lt;/li&gt;
&lt;li&gt;Added optional CSS minification, improving page load times.&lt;/li&gt;
&lt;li&gt;Added optional JavaScript minification, improving page load times.&lt;/li&gt;
&lt;li&gt;Where appropriate, all pages now have &lt;code&gt;rel="prev"&lt;/code&gt; and &lt;code&gt;rel="next"&lt;/code&gt; tags
  in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Added a &lt;code&gt;rel="canonical"&lt;/code&gt; tag to the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of all pages.&lt;/li&gt;
&lt;li&gt;Improved the style and workings of the pagination of all archive type
  pages.&lt;/li&gt;
&lt;li&gt;Improved the cosmetics of the category and tag clouds.&lt;/li&gt;
&lt;li&gt;Improved how the first paragraph is discovered for a page or post, when
  using it as the default description in the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; of a page.&lt;/li&gt;
&lt;li&gt;Cleaned up the generated HTML so it's more compact.&lt;/li&gt;
&lt;li&gt;Added support for custom 404 pages.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I say, they're just the improvements I've made that have come to mind as
I've used BlogMore. I've also done a lot of bug fixing too. You can read the
full changelog &lt;a href="https://blogmore.davep.dev/changelog/" rel="noopener noreferrer" target="_blank"&gt;over on the BlogMore
website&lt;/a&gt;&lt;sup id="fnref:140-1"&gt;&lt;a class="footnote-ref" href="#fn:140-1"&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;feel&lt;/em&gt; that the pace of updates and additions has started to slow; I
&lt;em&gt;think&lt;/em&gt; I've now got more or less everything I wanted from this. I'm pretty
sure I can do everything I ever bothered to do with Jekyll and Pelican, and
I am enjoying "owning" the code such that, if I have an idea for something I
want, it's easy enough to make it happen.&lt;/p&gt;
&lt;p&gt;I'm also pretty happy with how well the results perform. Despite the fact
I'm not a web developer, and despite this blog being served by GitHub Pages
(which, let's be honest, isn't the most speedy host), &lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer" target="_blank"&gt;the
measurements&lt;/a&gt; for a single page in the blog look
fairly good:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Desktop" src="https://blog.davep.org/attachments/2026/03/03/desktop-speeds.png" /&gt;&lt;/p&gt;
&lt;p&gt;That's measuring loading in a desktop context. Even measured as mobile
(which I've tried to make work well too) it's not too shabby:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Mobile" src="https://blog.davep.org/attachments/2026/03/03/mobile-speeds.png" /&gt;&lt;/p&gt;
&lt;p&gt;I think I can rightfully be satisfied with those values, given this isn't
normally my primary focus when it comes to software development.&lt;/p&gt;
&lt;p&gt;Anyway, if you like messing with static site generators, and one that is
blog-centric sounds useful, and if you're not put off by the fact that this
is &lt;a href="https://blog.davep.org/2026/02/20/five-days-with-copilot.html"&gt;a deliberate &lt;em&gt;"use GitHub Copilot"&lt;/em&gt;
experiment&lt;/a&gt;, feel free to &lt;a href="https://github.com/davep/blogmore" rel="noopener noreferrer" target="_blank"&gt;take a
look&lt;/a&gt;.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:140-1"&gt;
&lt;p&gt;Which, somewhat amusingly, is built with MkDocs.&amp;#160;&lt;a class="footnote-backref" href="#fnref:140-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/03/blogmore-1-5-0.html</guid>
      <category>Coding</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>BlogMore</category>
      <pubDate>Tue, 03 Mar 2026 21:34:00 +0000</pubDate>
    </item>
    <item>
      <title>Hike v1.3.0</title>
      <link>https://blog.davep.org/2026/03/03/hike-1-3-0.html</link>
      <description>&lt;p&gt;I've just released v1.3.0 of &lt;a href="https://hike.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;Hike&lt;/a&gt;, my little
terminal-based Markdown browser. It's about a year now &lt;a href="https://blog.davep.org/2025/02/14/hike.html"&gt;since I made the
first release&lt;/a&gt; and I've been making the odd update
here and there, but mostly it's a pretty stable tool. There's a few other
things I'd like to do with it but I keep getting distracted by different
ideas.&lt;/p&gt;
&lt;p&gt;Today's release sort of rides on the coattails of the current love for all
things Markdown because of "the AI". It seems that some folk are now keen on
the idea of serving Markdown from their websites, when asked for it: &lt;a href="https://www.skeptrune.com/posts/use-the-accept-header-to-serve-markdown-instead-of-html-to-llms/" rel="noopener noreferrer" target="_blank"&gt;as you
can see in this
post&lt;/a&gt;
for example. While that might be handy for some LLM bot or whatever, it's
also pretty handy if you happen to have a web-friendly Markdown browser!&lt;/p&gt;
&lt;p&gt;So v1.3.0 makes a small change to how a URL is looked at when deciding if it
might be a Markdown document, by saying &lt;em&gt;"hey, web server, I like Markdown
more than anything else, so feel free to serve me that up"&lt;/em&gt;. If we get a
Markdown type back, we go ahead and load it into Hike.&lt;/p&gt;
&lt;p&gt;This means that the post mentioned above loads up just fine now:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Viewing a Markdown site in Hike" src="https://blog.davep.org/attachments/2026/03/03/hike.png" /&gt;&lt;/p&gt;
&lt;p&gt;Previously, Hike would have gone &lt;em&gt;"nah, that's not a Markdown document"&lt;/em&gt; and
would have handed off to the environment's web browser.&lt;/p&gt;
&lt;p&gt;Hike is licensed GPL-3.0 and available &lt;a href="https://github.com/davep/hike" rel="noopener noreferrer" target="_blank"&gt;via
GitHub&lt;/a&gt; and also &lt;a href="https://pypi.org/project/hike/" rel="noopener noreferrer" target="_blank"&gt;via
PyPi&lt;/a&gt;. If you have an environment that has
&lt;code&gt;pipx&lt;/code&gt; installed you should be able to get up and going with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pipx&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;hike
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you're more into
&lt;a href="https://docs.astral.sh/uv/getting-started/installation/" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;uv&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;uv&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;hike
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you don't have &lt;code&gt;uv&lt;/code&gt; installed you can use &lt;a href="https://uvx.sh" rel="noopener noreferrer" target="_blank"&gt;uvx.sh&lt;/a&gt; to
perform the installation. For GNU/Linux or macOS or similar:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-LsSf&lt;span class="w"&gt; &lt;/span&gt;uvx.sh/hike/install.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;or on Windows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;powershell&lt;span class="w"&gt; &lt;/span&gt;-ExecutionPolicy&lt;span class="w"&gt; &lt;/span&gt;ByPass&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;irm https://uvx.sh/hike/install.ps1 | iex&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/03/hike-1-3-0.html</guid>
      <category>Coding</category>
      <category>Python</category>
      <category>terminal</category>
      <category>textual</category>
      <category>markdown</category>
      <category>AI</category>
      <category>LLM</category>
      <pubDate>Tue, 03 Mar 2026 17:10:00 +0000</pubDate>
    </item>
    <item>
      <title>Original Seen by davep rescued</title>
      <link>https://blog.davep.org/2026/03/03/original-seen-by-davep-rescued.html</link>
      <description>&lt;p&gt;&lt;img alt="Still Alive" src="https://blog.davep.org/attachments/2026/03/03/still-alive.jpeg#centre" /&gt;&lt;/p&gt;
&lt;p&gt;At the end of &lt;a href="https://blog.davep.org/2026/03/02/seen-by-rescued.html"&gt;yesterday's post&lt;/a&gt; I said I
might see if I can rescue the original photoblog from its &lt;a href="https://seenbydavep.wordpress.com/" rel="noopener noreferrer" target="_blank"&gt;backup on
WordPress&lt;/a&gt;. This was the first photoblog
I played with, posting to the long-dead
&lt;a href="https://en.wikipedia.org/wiki/Posterous" rel="noopener noreferrer" target="_blank"&gt;Posterous&lt;/a&gt; between 2009 and 2013.&lt;/p&gt;
&lt;p&gt;So, yesterday evening, I did an extract of the full feed from WordPress, and
also asked for a full backup of all the media. I then fired up Emacs and
rattled out some Python code that would marry up the two sets of data and
add to the photoblog repository. It took a little bit of working out; it
seems that every post had two entries in the feed: a parent and a child
entry. I've no clue why that's the case; I didn't really care to get too
deeply into it.&lt;/p&gt;
&lt;p&gt;Soon enough &lt;a href="https://seen-by.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;seen-by.davep.dev&lt;/a&gt; was updated with
an extra 1,833 posts! So now &lt;a href="https://seen-by.davep.dev/categories.html" rel="noopener noreferrer" target="_blank"&gt;the
categories&lt;/a&gt; on that blog site are
broken down into &lt;a href="https://seen-by.davep.dev/category/seen-by-me-1.html" rel="noopener noreferrer" target="_blank"&gt;Seen By Me
1&lt;/a&gt; (the original) and
&lt;a href="https://seen-by.davep.dev/category/seen-by-me-2.html" rel="noopener noreferrer" target="_blank"&gt;Seen By Me 2&lt;/a&gt; (the
second incarnation).&lt;/p&gt;
&lt;p&gt;Sadly, for the first blog, tagging wasn't really much of a thing so the &lt;a href="https://seen-by.davep.dev/tags.html" rel="noopener noreferrer" target="_blank"&gt;tag
cloud&lt;/a&gt; hasn't grown too much.&lt;/p&gt;
&lt;p&gt;But, finally, I've got both the photoblogs back up and hosted somewhere I
can point to, and I'm fully in control of their content. While it is &lt;a href="https://github.com/davep/seen-by" rel="noopener noreferrer" target="_blank"&gt;hosted
on GitHub Pages&lt;/a&gt; I've done this in a way
that it would be pretty easy to move elsewhere; this is down to the fact
that it's a simple static site built with
&lt;a href="https://blogmore.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt;.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/03/original-seen-by-davep-rescued.html</guid>
      <category>Creative</category>
      <category>blogging</category>
      <category>photography</category>
      <category>BlogMore</category>
      <category>posterous</category>
      <category>photoblog</category>
      <pubDate>Tue, 03 Mar 2026 09:30:00 +0000</pubDate>
    </item>
    <item>
      <title>Seen by davep rescued</title>
      <link>https://blog.davep.org/2026/03/02/seen-by-rescued.html</link>
      <description>&lt;p&gt;&lt;img alt="Final Message" src="https://blog.davep.org/attachments/2026/03/02/final-message.jpeg#centre" /&gt;&lt;/p&gt;
&lt;p&gt;Since mid-2023 &lt;a href="https://blog.davep.org/2023/08/20/seen-by-davep-broke-again.html"&gt;my photoblog has been
broken&lt;/a&gt;. As I mentioned at the
time, the issue was that this second incarnation of the blog had started
life as a proper
&lt;a href="https://en.wikipedia.org/wiki/Mashup_(web_application_hybrid)" rel="noopener noreferrer" target="_blank"&gt;mashup&lt;/a&gt; of
some web tools, and the heart of it was Twitter.&lt;/p&gt;
&lt;p&gt;It all started to fall apart when Twitter got its new owner, and APIs became
expensive, and other tools would not or could not work with it any more, and
then it really fell apart when I finally nuked my account.&lt;/p&gt;
&lt;p&gt;So since then the blog has been sat about, unused and unloved, with a lot of
broken links and images.&lt;/p&gt;
&lt;p&gt;Thankfully, though, the pipeline that I had going had been designed with
this sort of problem in mind: part of what I had going also made a backup of
the photos I took to Google Drive and to Google Photos. So when I got to a
point the other day where &lt;a href="https://blogmore.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt; was usable
I decided I should rescue the photos and rebuild the blog.&lt;/p&gt;
&lt;p&gt;After downloading the full feed of the Blogger.com-hosted blog, I threw
together some Python code that took the data (thanks to
&lt;a href="https://github.com/kurtmckee/feedparser" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;feedparser&lt;/code&gt;&lt;/a&gt; for helping with
that), matched up the posts with the images I had in Google Drive, slugged
the names, wrote some Markdown and copied some images, and &lt;a href="https://github.com/davep/seen-by" rel="noopener noreferrer" target="_blank"&gt;I had the source
of a fresh blog&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The result of all of this can be seen up on
&lt;a href="https://seen-by.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;seen-by.davep.dev&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I strongly suspect this is going to remain a pretty static site. At the
moment I've given no thought whatsoever as to how I might have this populate
in the way the old version of it did. Quite simply the old version was:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Take photo&lt;/li&gt;
&lt;li&gt;Post to Twitter with a specific hashtag&lt;/li&gt;
&lt;li&gt;Have IFTTT notice this and create the blog post, make backups&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;li&gt;Profit?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I suppose, this time around, I could have something monitor &lt;a href="https://fosstodon.org/@davep" rel="noopener noreferrer" target="_blank"&gt;my Mastodon
account&lt;/a&gt;, or my &lt;a href="https://pixelfed.social/davepearson" rel="noopener noreferrer" target="_blank"&gt;pixelfed
account&lt;/a&gt;, and then trigger a similar
process; but then that would need something akin to IFTTT running and
interacting with GitHub and creating the Markdown and kicking off a build
process and...&lt;/p&gt;
&lt;p&gt;Eh, maybe one day. For now, though, I'll be happy that I've rescued this
particular incarnation of my photoblog and then think about if and how I
carry on with something similar in the future.&lt;/p&gt;
&lt;p&gt;Meanwhile... this has got me thinking. The &lt;em&gt;original&lt;/em&gt; blog is &lt;a href="https://seenbydavep.wordpress.com/" rel="noopener noreferrer" target="_blank"&gt;backed up on
WordPress&lt;/a&gt;. It's been sat there, all sad
and neglected, ever since Posterous disappeared. I wonder if I can export
all the data from there and mash it into this new version...&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/02/seen-by-rescued.html</guid>
      <category>Creative</category>
      <category>blogging</category>
      <category>photography</category>
      <category>BlogMore</category>
      <category>Twitter</category>
      <category>Posterous</category>
      <category>photoblog</category>
      <pubDate>Mon, 02 Mar 2026 17:18:00 +0000</pubDate>
    </item>
    <item>
      <title>Not so elegant</title>
      <link>https://blog.davep.org/2026/03/01/not-so-elegant.html</link>
      <description>&lt;p&gt;One thing I've been noticing with &lt;a href="https://blog.davep.org/2026/02/20/five-days-with-copilot.html"&gt;my current experiment with GitHub
Copilot&lt;/a&gt; is that it seems to know
Python well enough to write code that gets the job done, and sometimes it
knows it well enough to write more modern idiomatic Python code, but it also
seems to write the inelegant version of it.&lt;/p&gt;
&lt;p&gt;It's hard to pin down exactly, and of course it's a matter of taste (my idea
of elegant might burn someone else's eyes), but on occasion, as I review the
code, I find things that make me go "ugh".&lt;/p&gt;
&lt;p&gt;Here's an example: there's a function that Copilot wrote to extract the
first non-markup paragraph of an article (so that it can be used as a page
description). One thing it needs to do is skip any initial images, etc. It
takes a pretty brute force approach of looking at the start of each stripped
line, but it gets the job done -- I can't really argue with that.&lt;/p&gt;
&lt;p&gt;But here's how it does it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Skip markdown image syntax&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stripped&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;![&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;continue&lt;/span&gt;

&lt;span class="c1"&gt;# Skip markdown linked image syntax ([![alt](img)](url))&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stripped&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;[![&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;continue&lt;/span&gt;

&lt;span class="c1"&gt;# Skip HTML img tags&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stripped&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;img&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, this is good: it's using
&lt;a href="https://docs.python.org/3/library/stdtypes.html#str.startswith" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;startswith&lt;/code&gt;&lt;/a&gt;.
There are less-elegant approaches it could have used so I'll give it bonus
points for using that method. The thing is though, it's testing each prefix
one string at a time, pretty much rolling out a load of boilerplate code.&lt;/p&gt;
&lt;p&gt;What bothers me here is that &lt;code&gt;startswith&lt;/code&gt; will take a tuple of strings to
test for. I find it curious that the generated code is idiomatic enough to
know that &lt;code&gt;startswith&lt;/code&gt; is a sensible option here, but at the same time it
still writes the list of things to test out in a long-winded way.&lt;/p&gt;
&lt;p&gt;This is exactly the sort of thing I'd call out in &lt;a href="https://blog.davep.org/2026/02/04/solidarity-empathy-patience.html"&gt;a normal code
review&lt;/a&gt;. Technically, if this
wasn't mostly a &lt;em&gt;"let's see how it goes about this with minimal input from
me"&lt;/em&gt; experiment, I'd have called it out here too (as an experiment, I might
go back prompt it to "think" about this).&lt;/p&gt;
&lt;p&gt;If I ever find myself using this sort of tool for generating code in a work
setting, this is exactly the sort of thing I'll be watching for.&lt;/p&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/03/01/not-so-elegant.html</guid>
      <category>AI</category>
      <category>Python</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>code review</category>
      <pubDate>Sun, 01 Mar 2026 11:33:00 +0000</pubDate>
    </item>
    <item>
      <title>Complexitty v1.1.0</title>
      <link>https://blog.davep.org/2026/02/28/complexitty-1-1-0.html</link>
      <description>&lt;p&gt;&lt;a href="https://complexitty.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;&lt;img alt="Complexitty" src="https://blog.davep.org/attachments/2025/04/20/complexitty-social-banner.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I've just released v1.1.0 of Complexitty, my little Mandelbrot explorer for
the terminal. I first released it &lt;a href="https://blog.davep.org/2025/04/20/complexitty.html"&gt;in April last
year&lt;/a&gt; and have tinkered with it on and off
since. Most of the changes have been to do with easier navigation, some
additional colour schemes, the ability to pass location information on the
command line, that sort of thing; meanwhile, the very heart of it has stayed
the same &lt;em&gt;"it's as fast as it's ever going to be expect it to not be fast"&lt;/em&gt;
approach.&lt;/p&gt;
&lt;p&gt;It's a Python application after all: they can be fast, but something like
this isn't going to compete with the serious Mandelbrot explorers.&lt;/p&gt;
&lt;p&gt;v1.1.0, however, has a little optional speedup. If you install it normally
it'll work at the pace it always did: the more you zoom in, the more you
ramp up the iterations to tease more detail out, the slower it gets. But
now: if you install it as &lt;code&gt;complexitty[faster]&lt;/code&gt; rather than just as
&lt;code&gt;complexitty&lt;/code&gt; it will use &lt;a href="http://numba.pydata.org" rel="noopener noreferrer" target="_blank"&gt;Numba&lt;/a&gt; to speed up the
main calculation.&lt;/p&gt;
&lt;p&gt;On the very first run things will be slow to start up, but from then on I
see a real improvement. As you zoom in and explore and up the detail, the
calculation remains pretty fast. The drop-off of speed that you see without
Numba just isn't there.&lt;/p&gt;
&lt;p&gt;While the whole idea of Complexitty was to see what I could do with Python,
in the terminal, using Textual, and keeping it "pure", I feel this is an
acceptable "cheat" given it's optional.&lt;/p&gt;
&lt;p&gt;I'm considering this an experimental change for now, as I don't know how
well it will work in all places where Complexitty could be otherwise
installed. So give it a go, see if it installs and runs as
&lt;code&gt;complexitty[faster]&lt;/code&gt;, and if it doesn't: fall back to plain old
&lt;code&gt;complexitty&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you're interested you can find the source &lt;a href="https://github.com/davep/complexitty" rel="noopener noreferrer" target="_blank"&gt;over on
GitHub&lt;/a&gt;, with the application
available &lt;a href="https://pypi.org/project/complexitty/" rel="noopener noreferrer" target="_blank"&gt;via PyPI&lt;/a&gt;. If you use
&lt;code&gt;pipx&lt;/code&gt; you should be able to install with either:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pipx&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;complexitty&lt;span class="o"&gt;[&lt;/span&gt;faster&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;or&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pipx&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;complexitty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you're a fan of
&lt;a href="https://docs.astral.sh/uv/getting-started/installation/" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;uv&lt;/code&gt;&lt;/a&gt; (and who
isn't these days?) then try either:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;uv&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;complexitty&lt;span class="o"&gt;[&lt;/span&gt;faster&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;or fall back to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;uv&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;complexitty
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In fact, to squeeze everything you can out of Complexitty, perhaps try:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;uv&lt;span class="w"&gt; &lt;/span&gt;tool&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;complexitty&lt;span class="o"&gt;[&lt;/span&gt;faster&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--python&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;.14
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/02/28/complexitty-1-1-0.html</guid>
      <category>Coding</category>
      <category>Python</category>
      <category>terminal</category>
      <category>textual</category>
      <category>mandelbrot</category>
      <pubDate>Sat, 28 Feb 2026 20:40:00 +0000</pubDate>
    </item>
    <item>
      <title>Brute force and ignorance</title>
      <link>https://blog.davep.org/2026/02/27/brute-force-and-ignorance.html</link>
      <description>&lt;p&gt;My &lt;a href="https://blog.davep.org/2026/02/20/five-days-with-copilot.html"&gt;experiment with coding with an
agent&lt;/a&gt; continues, and from the
point of view of the usability of the results, I'd say it's going well. From
the point of view of learning more about this sort of tool and the pitfalls:
I'd also say it's going well.&lt;/p&gt;
&lt;p&gt;The one thing I'm really starting to get an appreciation for is just how
much it employs a sort of &lt;em&gt;brute force and ignorance&lt;/em&gt; approach to getting to
a solution for some sort of problem. I noticed this on and off as I watched
the agent's chat, as it worked away.&lt;/p&gt;
&lt;p&gt;One example I enjoyed was when it was trying to add a new dependency to
&lt;a href="https://blogmore.davep.dev/" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt;. For reasons I should probably try
and understand&lt;sup id="fnref:153-1"&gt;&lt;a class="footnote-ref" href="#fn:153-1"&gt;1&lt;/a&gt;&lt;/sup&gt; it knew it should be using &lt;code&gt;uv&lt;/code&gt; to add a dependency and
it knew how to use it to update the lock file, but it didn't have &lt;code&gt;uv&lt;/code&gt; to
hand:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The lock file (uv.lock) needs to be updated to include rcssmin. Since uv
isn't available, I'll need to note this in the PR. The lock file should be
generated by uv when the pyproject.toml is updated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So it decided the best solution was probably to... "hand-edit" the lock
file.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The lock file needs to be updated with rcssmin. Since uv is not available
in this environment, I need to update it manually or find another way.&lt;/p&gt;
&lt;p&gt;I need to update the uv.lock file to include rcssmin. The uv.lock file needs to include:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The rcssmin package entry with hashes&lt;/li&gt;
&lt;li&gt;The rcssmin dependency in the blogmore package section&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let me look at the PyPI page for rcssmin 1.2.2 to get the hash.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It then grabs &lt;code&gt;rcssmin&lt;/code&gt; from PyPI and checks out the information it wants;
after which it goes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I need to update the &lt;code&gt;uv.lock&lt;/code&gt; file with the rcssmin package information.
The &lt;code&gt;uv.lock&lt;/code&gt; file uses SHA256 hashes. Let me look at the existing format
in more detail to understand what I need to add, and then I'll query PyPI
for the hashes.&lt;/p&gt;
&lt;p&gt;Actually, let me think about this differently. The &lt;code&gt;uv.lock&lt;/code&gt; file is a
generated file, and updating it manually is error-prone. The proper way to
update it is to run &lt;code&gt;uv sync&lt;/code&gt; or &lt;code&gt;uv lock&lt;/code&gt;. Since uv is not available in
this environment, I have two options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Let the CI update the lock file (risky if CI fails on the locked version)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;So... around this point it has some sort of plan for hand-patching the lock
file, but also recognises that this is a dodgy approach and it should be
using &lt;code&gt;uv&lt;/code&gt; to update the lock file.&lt;/p&gt;
&lt;p&gt;I also really like the part where it says it has two options, then goes on
to provide an exhaustive list of... one.&lt;/p&gt;
&lt;p&gt;After this it runs this code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;json&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;urllib.request&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://pypi.org/pypi/rcssmin/json&amp;#39;&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;1.2.2&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;releases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;releases&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;releases&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;filename: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;filename&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;]}&amp;#39;)&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;  url: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;url&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;]}&amp;#39;)&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;  sha256: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;digests&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;][&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;sha256&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;]}&amp;#39;)&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;  size: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;size&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;]}&amp;#39;)&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;  upload_time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;upload_time_iso_8601&lt;/span&gt;&lt;span class="se"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="s2"&gt;]}&amp;#39;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;after which it concludes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Now I have all the information I need to update the uv.lock file. I need to add:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The rcssmin package entry in the lock file&lt;/li&gt;
&lt;li&gt;Add rcssmin to the blogmore package dependencies&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;I mean... okay, I guess. Again, I'll admit that I'm still getting used to
setting this sort of thing up and working with it (and keep in mind none of
this was done locally; this is all via GitHub Copilot, up on GitHub), but
it's kind of funny and wild that the approach taken was to recognise that
using &lt;code&gt;uv&lt;/code&gt; to remake the lock file was the best approach so... let's
hand-edit the lock file.&lt;/p&gt;
&lt;p&gt;But that's not the best part. This is where it gets really fun. It had
decided that the lock file &lt;em&gt;must&lt;/em&gt; be in alphabetical order. Okay, sure, why
not:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The lock file has packages sorted alphabetically, so rcssmin should go
between pygments and python-dateutil (since "r" comes before "py"
actually... no, wait - "r" comes after "p" in the alphabet. Let me check
the order again).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Since "r" comes before "py."&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Since "r" comes before "py."&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;o_O&lt;/p&gt;
&lt;p&gt;O_o&lt;/p&gt;
&lt;p&gt;Extra credit here for giving me a good giggle. I really appreciate the way
that it catches itself mid-sentence and remembers how the alphabet actually
works.&lt;/p&gt;
&lt;p&gt;As to the outcome of all of this? Sure, &lt;a href="https://github.com/davep/blogmore/issues/158" rel="noopener noreferrer" target="_blank"&gt;the feature I wanted to
add&lt;/a&gt; &lt;a href="https://github.com/davep/blogmore/pull/161" rel="noopener noreferrer" target="_blank"&gt;got
added&lt;/a&gt;; it worked away and got
to a working solution in the end. But the route it took was, I think it's
fair to say, a &lt;em&gt;"brute force and ignorance"&lt;/em&gt; approach.&lt;/p&gt;
&lt;p&gt;I've not been spending too much time reading the agent's own chatter, but
when I have I've found myself amused by the dead ends it'll wander down and
then work its way back out. There is, without question, a recognisable
process here: I believe it would be a dishonest developer who says they've
&lt;em&gt;never&lt;/em&gt; had times in the past, or just one of those off days, where they've
fallen down a rabbit hole of a solution, only to realise it's the right
solution implemented in the worst possible way. There's also a resemblance
here to how more junior developers work a problem until they really develop
their skills.&lt;/p&gt;
&lt;p&gt;I think I'm going to keep an eye on the agent chat a bit more from now on.
While I imagine things will only improve as these tools improve, for the
moment it's a good source of coding comedy.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:153-1"&gt;
&lt;p&gt;Presumably there's things I can be doing to make its life easier.&amp;#160;&lt;a class="footnote-backref" href="#fnref:153-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/02/27/brute-force-and-ignorance.html</guid>
      <category>AI</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>GitHub</category>
      <category>BlogMore</category>
      <pubDate>Fri, 27 Feb 2026 09:45:00 +0000</pubDate>
    </item>
    <item>
      <title>Copilot lied</title>
      <link>https://blog.davep.org/2026/02/21/copilot-lied.html</link>
      <description>&lt;p&gt;This morning, with &lt;a href="https://blog.davep.org/2026/02/20/five-days-with-copilot.html"&gt;my experiment with
Copilot&lt;/a&gt; having settled down a
little bit, I thought I might try and use the result for another little
experiment. For a long time now I've maintained a (currently lapsed)
photoblog. It was always very much tied to &lt;em&gt;"the site formerly known as
twitter"&lt;/em&gt; and, since I fully erased my account after the site turned into a
&lt;a href="https://en.wiktionary.org/wiki/Nazi_bar" rel="noopener noreferrer" target="_blank"&gt;Nazi bar&lt;/a&gt;, I've not done anything
to update how it gets populated.&lt;/p&gt;
&lt;p&gt;So I got to thinking: I have a full backup of all the images in a couple of
places; perhaps with a bit of coding (and some help from "the AIs") I can
revive it using &lt;a href="https://blogmore.davep.dev" rel="noopener noreferrer" target="_blank"&gt;BlogMore&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;I tinkered for a wee bit and mostly got something going (albeit I'm going to
have to do some work to back-port the actual dates and times of some earlier
images, and there's a load of work to do to somehow pull out all the tags).
But then I hit a small hitch.&lt;/p&gt;
&lt;p&gt;When building BlogMore I made the decision to let it write both the code
&lt;em&gt;and&lt;/em&gt; the documentation. It documented a couple of features I never asked
for, but which seemed sensible so I never questioned. On the other hand
neither did I test them at the time (because they weren't important to what
I needed).&lt;/p&gt;
&lt;p&gt;It's the exact reason I added this warning at the start of the
documentation:&lt;/p&gt;
&lt;div class="admonition admonition-warning"&gt;
&lt;div class="admonition-title"&gt;⚠️ Warning&lt;/div&gt;
&lt;div class="admonition-content"&gt;
&lt;p&gt;BlogMore is an experiment in using GitHub Copilot to develop a whole
project from start to finish. As such, almost every part of this
documentation was generated by Copilot and what it knows about the
project. Please keep this in mind.&lt;/p&gt;
&lt;p&gt;From what I can see at the moment the documentation is broadly correct,
and I will update and correct it as I work through it and check it myself.
Of course, I will welcome reports of problems or fixes.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;With this warning in mind, and with the intention of working through the
documentation and testing its claims, I decided to test out one of the
features when building up the new photoblog.&lt;/p&gt;
&lt;p&gt;Whereas with this blog I keep all the posts &lt;a href="https://github.com/davep/davep.github.com/tree/main/content" rel="noopener noreferrer" target="_blank"&gt;in a flat
structure&lt;/a&gt;,
this time around I thought I'd try out this (taken from the
Copilot-generated BlogMore documentation):&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;BlogMore is flexible about how you organise your posts. Here are some common patterns:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Flat structure&lt;/strong&gt; (all posts in one directory):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;posts/
  ├── hello-world.md
  ├── python-tips.md
  └── web-development.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Files can be date-prefixed (e.g., &lt;code&gt;2026-02-18-hello-world.md&lt;/code&gt;) and BlogMore will automatically remove the date prefix from the URL slug. The post will still use the &lt;code&gt;date&lt;/code&gt; field from frontmatter for chronological ordering.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Organised by date&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;posts/
  ├── 2024/
  │   ├── 01/
  │   │   └── hello-world.md
  │   └── 02/
  │       └── python-tips.md
  └── 2025/
      └── 01/
          └── web-development.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Organised by topic&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;posts/
  ├── python/
  │   ├── decorators.md
  │   └── type-hints.md
  └── web/
      ├── css-grid.md
      └── javascript-tips.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr /&gt;
&lt;p&gt;Using the hierarchy approach, especially with dates, seemed ideal! I'd drop
the actual images in such a hierarchy, and also drop the Markdown posts in a
parallel hierarchy too. Perfect!&lt;/p&gt;
&lt;p&gt;So I set it all up to do that, fired up &lt;code&gt;blogmore serve&lt;/code&gt;, visited the URL
and... &lt;code&gt;No posts yet&lt;/code&gt;. What the hell?&lt;/p&gt;
&lt;p&gt;So I checked the code for BlogMore and, sure enough, despite the fact the
documentation was selling me on this handy way to organise my posts, no such
feature existed!&lt;/p&gt;
&lt;p&gt;As an experiment &lt;a href="https://github.com/davep/blogmore/issues/129" rel="noopener noreferrer" target="_blank"&gt;I then asked Copilot what the heck was going
on&lt;/a&gt;. Much as I expected,
rather than coming back with an answer to the question, &lt;a href="https://github.com/davep/blogmore/pull/130" rel="noopener noreferrer" target="_blank"&gt;it went right ahead
and fixed it instead&lt;/a&gt;. Which is
fine, that's where I would have taken this, but I do wish it would answer
the question first.&lt;/p&gt;
&lt;div class="admonition admonition-note"&gt;
&lt;div class="admonition-title"&gt;ℹ️ Note&lt;/div&gt;
&lt;div class="admonition-content"&gt;
&lt;p&gt;I imagine I could get an answer to the question if I took a more
conversational route with Copilot, rather than writing the question in an
issue and then assigning that issue to it. I must remember to try that at
some point.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;So, yeah, unsurprisingly Copilot flat out lied&lt;sup id="fnref:132-1"&gt;&lt;a class="footnote-ref" href="#fn:132-1"&gt;1&lt;/a&gt;&lt;/sup&gt; in the documentation. I'm
not in the least bit shocked by this and, as I said, I fully expected this.
But it was amusing to have an example of this turn up so early in the
documentation, in such a glaring way, and in a way that was so easily fixed
(really, it was just a swap of
&lt;a href="https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;Path.glob&lt;/code&gt;&lt;/a&gt;
to
&lt;a href="https://docs.python.org/3/library/pathlib.html#pathlib.Path.rglob" rel="noopener noreferrer" target="_blank"&gt;&lt;code&gt;Path.rglob&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;As I play with this more it's going to be fun to see what other bold claims
turn out to not be true; or perhaps even the reverse: what neat features
lurk in the code that haven't been documented.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:132-1"&gt;
&lt;p&gt;Yes, as I mentioned yesterday, that's an anthropomorphism. Folk who
take such things as an indication that you don't understand "AI" might
want to think about what it is to be a human when communicating.&amp;#160;&lt;a class="footnote-backref" href="#fnref:132-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/02/21/copilot-lied.html</guid>
      <category>AI</category>
      <category>Python</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>GitHub</category>
      <category>BlogMore</category>
      <pubDate>Sat, 21 Feb 2026 14:47:00 +0000</pubDate>
    </item>
    <item>
      <title>Five days with Copilot</title>
      <link>https://blog.davep.org/2026/02/20/five-days-with-copilot.html</link>
      <description>&lt;h2 id="another-itch-to-scratch"&gt;Another itch to scratch&lt;a aria-label="Link to this heading" class="heading-anchor" href="#another-itch-to-scratch"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As &lt;a href="https://blog.davep.org/2026/02/19/a-new-engine.html"&gt;I mentioned yesterday&lt;/a&gt;, I've been a happy
user of &lt;a href="https://getpelican.com" rel="noopener noreferrer" target="_blank"&gt;Pelican&lt;/a&gt; for a couple or so years now, but
every so often there's a little change or tweak I'd like to make that
requires diving deeper into the templates and the like and... I go &lt;em&gt;"eh,
I'll look at it some time soon"&lt;/em&gt;. Another thought that often goes through my
head at those times is &lt;em&gt;"I should build my own static site generator that
works exactly how I want"&lt;/em&gt; -- because really any hacker with a blog has to
do that at some point.&lt;/p&gt;
&lt;p&gt;Meanwhile... I've had free access to &lt;a href="https://github.com/features/copilot" rel="noopener noreferrer" target="_blank"&gt;GitHub
Copilot&lt;/a&gt; attached to &lt;a href="https://github.com/davep" rel="noopener noreferrer" target="_blank"&gt;my GitHub
account&lt;/a&gt; for some time now, and I've hardly used
it. At the same time -- the past few months especially -- I've been watching
the rise of agents as coding tools, as well as the rise of advocates for
them. Worse still, I've seen people I didn't expect to be advocates for
giving up on coding turning to these tools and suddenly writing rationales
in favour of them.&lt;/p&gt;
&lt;p&gt;So, suddenly, the idea popped into my head: I should write my own static
site generator that I'll use for my blog, and I should try and use GitHub
Copilot to write 100% of the code, and documentation, and see how far I get.
In doing so I might firm up my opinions about where we're all going with
this.&lt;/p&gt;
&lt;p&gt;The requirements were going to be pretty straightforward:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It should be a static site generator that turns Markdown files into a
  website.&lt;/li&gt;
&lt;li&gt;It should be blog-first in its design.&lt;/li&gt;
&lt;li&gt;It should support non-blog-post pages too.&lt;/li&gt;
&lt;li&gt;It should be written in Python.&lt;/li&gt;
&lt;li&gt;It should use Jinja2 for templates.&lt;/li&gt;
&lt;li&gt;It should have a better archive system than I ever got out of my Pelican
  setup.&lt;/li&gt;
&lt;li&gt;It should have categories, tags, and all the usual metadata stuff you'd
  expect from a site where you're going to share content from.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, the requirements would drift and expand as I went along and I had
some new ideas.&lt;/p&gt;
&lt;h2 id="getting-started"&gt;Getting started&lt;a aria-label="Link to this heading" class="heading-anchor" href="#getting-started"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To kick things off, I created &lt;a href="https://github.com/davep/blogmore" rel="noopener noreferrer" target="_blank"&gt;my repo&lt;/a&gt;,
and then opened Copilot and typed out a prompt to get things going. Here's
what I typed:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Build a blog-oriented static site generation engine. It should be built in
Python, the structure of the repository should match that of my preferences
for Python projects these days (see https://github.com/davep/oldnews and
take clues from the makefile; I like uv and ruff and Mypy, etc).&lt;/p&gt;
&lt;p&gt;Important features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Everything is written in markdown&lt;/li&gt;
&lt;li&gt;All metadata for a post should come from frontmatter&lt;/li&gt;
&lt;li&gt;It should use Jinja2 for the output templates&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you can see, rather than get very explicit about every single detail, I
wanted to start out with a vague description of what I was aiming for. I did
want to encourage it to try and build a Python repository how I normally
would, so I pointed it at &lt;a href="https://github.com/davep/oldnews" rel="noopener noreferrer" target="_blank"&gt;OldNews&lt;/a&gt; in the
hope that it might go and comprehend how I go about things; I also
doubled-down in the importance of using &lt;code&gt;uv&lt;/code&gt; and &lt;code&gt;mypy&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The result of this was... &lt;a href="https://github.com/davep/blogmore/pull/1" rel="noopener noreferrer" target="_blank"&gt;actually
impressive&lt;/a&gt;. As you'll see in that
PR, to get to a point where it could be merged, there was some
back-and-forth with Copilot to add things I hadn't thought of initially, and
to get it to iron out some problems, but for the most part it delivered what
I was after. Without question it delivered it faster than I would have.&lt;/p&gt;
&lt;p&gt;Some early issues where I had to point out problems to Copilot included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The order of posts on the home page wasn't obvious to me, and absolutely
  wasn't reverse chronological order.&lt;/li&gt;
&lt;li&gt;Footnotes were showing up kinda odd.&lt;/li&gt;
&lt;li&gt;The main index for the blog was showing just posts titles, not the full
  text of the article as you'd normally expect from a blog.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nothing terrible, and it did get a lot of the heavy lifting done and done
well, but it was worth noting that a lot of dev-testing/QA needed to be done
to be confident about its work, and doing this picked up on little details
that are important.&lt;/p&gt;
&lt;h3 id="an-improvement-to-the-markdown"&gt;An improvement to the Markdown&lt;a aria-label="Link to this heading" class="heading-anchor" href="#an-improvement-to-the-markdown"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;As an aside: during this first PR, I quickly noticed a problem where &lt;a href="https://github.com/davep/blogmore/pull/1#issuecomment-3904192942" rel="noopener noreferrer" target="_blank"&gt;I was
getting this error when generating the site from the
Markdown&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Error generating site: mapping values are not allowed in this context
  in &amp;quot;&amp;lt;unicode string&amp;gt;&amp;quot;, line 3, column 15
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I just assumed it was some bug in the generated code and left Copilot to
work it out. Instead it came back and educated me on something: &lt;a href="https://github.com/davep/blogmore/pull/1#issuecomment-3904197313" rel="noopener noreferrer" target="_blank"&gt;I actually
had bad YAML in the frontmatter of some of my
posts&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;This, by the way, wouldn't be the last time that Copilot found an issue with
my input Markdown and so, having used it, improved my blog.&lt;/p&gt;
&lt;h3 id="a-major-feature-from-a-simple-request"&gt;A major feature from a simple request&lt;a aria-label="Link to this heading" class="heading-anchor" href="#a-major-feature-from-a-simple-request"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Another problem I ran into quickly was that previewing the generated site
wasn't working well at all; all I could do was browse the files in the
filesystem. So, almost as an offhand comment, in the initial PR, &lt;a href="https://github.com/davep/blogmore/pull/1#issuecomment-3904205550" rel="noopener noreferrer" target="_blank"&gt;I
asked&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can we get a serve mode please so I can locally test the site?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Just like that, it went off &lt;a href="https://github.com/davep/blogmore/pull/1/changes/3449eec9b4df88e66eec0f6bba4369926ff1389e" rel="noopener noreferrer" target="_blank"&gt;and wrote a whole server for the
project&lt;/a&gt;.
While the server did need a lot of extra work to really work well&lt;sup id="fnref:143-1"&gt;&lt;a class="footnote-ref" href="#fn:143-1"&gt;1&lt;/a&gt;&lt;/sup&gt;, the
initial version was good enough to get me going and to iterate on the
project as a whole.&lt;/p&gt;
&lt;h2 id="the-main-workflow"&gt;The main workflow&lt;a aria-label="Link to this heading" class="heading-anchor" href="#the-main-workflow"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Having kicked off the project and having had some success with getting
Copilot to deliver what I was asking for, I settled into a new but also
familiar workflow. Whereas normally, when working on a personal project,
I'll write an issue for myself, at some point pick it up and create a PR,
review and test the PR myself then merge, now the workflow turned into:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write an issue but do so in a way that when I assign it to Copilot it has
  enough information to go off and do the work.&lt;/li&gt;
&lt;li&gt;Wait for Copilot to get done.&lt;/li&gt;
&lt;li&gt;Review the PR, making change requests etc.&lt;/li&gt;
&lt;li&gt;Make any fixes that are easier for me to fix by hand that describe to
  Copilot.&lt;/li&gt;
&lt;li&gt;Merge.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In fact, the first step had some sub-steps to it too, I was finding. What I
was doing, more than ever, was writing issues like I'd write sticky notes:
with simple descriptions of a bug or a new feature. I'd then come back to
them later and flesh them out into something that would act as a prompt for
Copilot. I found myself doing this so often I ended up adding a "Needs
prompt" label to my &lt;a href="https://github.com/davep/setup-standard-labels" rel="noopener noreferrer" target="_blank"&gt;usual set of issue
labels&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All of this made for an efficient workflow, and one where I could often get
on with something else as Copilot worked on the latest job (I wasn't just
working on other things on my computer; sometimes I'd be going off and doing
things around the house while this happened), but... it wasn't fun. It was
the opposite of what I've always enjoyed when it comes to building software.
I got to dream up the ideas, I got to do the testing, I got to review the
quality of the work, but I didn't get to actually lose myself in the flow
state of coding.&lt;/p&gt;
&lt;p&gt;One thing I've really come to understand during those 5 days of working on
BlogMore was I &lt;em&gt;really&lt;/em&gt; missed getting lost in the flow state. Perhaps it's
the issue to PR to review to merge cycle I used that amplified this, perhaps
those who converse with an agent in their IDE or in some client application
keep a sense of that (I might have to try that approach out), but this feels
like a serious loss to me when it comes to writing code for personal
enjoyment.&lt;/p&gt;
&lt;h2 id="the-main-problems"&gt;The main problems&lt;a aria-label="Link to this heading" class="heading-anchor" href="#the-main-problems"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I think it's fair to say that I've been surprised at just how well Copilot
understood my (sometimes deliberately vague) requests, at how it generally
managed to take some simple plain English and turn it into actual code that
actually did what I wanted and, mostly, actually worked.&lt;/p&gt;
&lt;p&gt;But my experiences over the past few days haven't been without their
problems.&lt;/p&gt;
&lt;h3 id="the-confidently-wrong-problem"&gt;The confidently wrong problem&lt;a aria-label="Link to this heading" class="heading-anchor" href="#the-confidently-wrong-problem"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Hopefully we all recognise that, with time and experience, we learn where
the mistakes are likely to turn up. Once you've written enough code you've
also written plenty of bugs and been caught out by plenty of edge-cases that
you get a spidey-sense for trouble as you write code. I feel that this kind
of approach can be called cautiously confident.&lt;/p&gt;
&lt;p&gt;Working with Copilot&lt;sup id="fnref:143-2"&gt;&lt;a class="footnote-ref" href="#fn:143-2"&gt;2&lt;/a&gt;&lt;/sup&gt;, however, I often ran into the confidently wrong
issue. On occasion I found it would proudly&lt;sup id="fnref:143-3"&gt;&lt;a class="footnote-ref" href="#fn:143-3"&gt;3&lt;/a&gt;&lt;/sup&gt; request review for some
minor bit of work, proclaiming that it had done the thing or solved the
problem, and I'd test it and nothing had materially changed. On a couple of
occasions, when I pushed back, I found it actually doubting my review before
finally digging in harder and eventually solving the issue.&lt;/p&gt;
&lt;p&gt;I found that this took time and was rather tiring.&lt;/p&gt;
&lt;p&gt;There were also times where it would do the same but not directly in respect
to code. One example I can think of is when it was confident that Python
3.14 was still a pre-release Python as of February 2026 (&lt;a href="https://devguide.python.org/versions/" rel="noopener noreferrer" target="_blank"&gt;it
isn't&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;This problem alone concerns me; this is the sort of thing where people
without a good sense for when the agent is probably bullshitting will get
into serious trouble.&lt;/p&gt;
&lt;h3 id="the-tries-too-hard-problem"&gt;The tries-too-hard problem&lt;a aria-label="Link to this heading" class="heading-anchor" href="#the-tries-too-hard-problem"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A variation on the above problem works the other way: on at least one
occasion I found that Copilot tried too hard to fix a problem that wasn't
really its to fix.&lt;/p&gt;
&lt;p&gt;In this case &lt;a href="https://github.com/davep/blogmore/pull/110" rel="noopener noreferrer" target="_blank"&gt;I was asking it to tidy up some validation issues in the RSS
feed data&lt;/a&gt;. One of the main
problems was root-relative URLs being in the content of the feed; for that
they needed to be made absolute URLs. Copilot did an excellent job of fixing
the problem, but one (and from what I could see only one) relative URL
remained.&lt;/p&gt;
&lt;p&gt;I &lt;a href="https://github.com/davep/blogmore/pull/110#issuecomment-3928257463" rel="noopener noreferrer" target="_blank"&gt;asked it to take a
look&lt;/a&gt;
and it took a real age to work over the issue. To its credit, it dug hard
and it dug deep and it got to the bottom of the problem. The issue here
though was it tried too hard because, having found the cause of the problem
(a typo in my original Markdown, which had always existed) it went right
ahead and built a workaround for this one specific broken link.&lt;/p&gt;
&lt;p&gt;Now, while I'm a fan of &lt;a href="https://en.wikipedia.org/wiki/Robustness_principle" rel="noopener noreferrer" target="_blank"&gt;Postel's
law&lt;/a&gt;, this is taking
things a bit too far. If this was a real person I'd tasked with the job I
would have expected and encouraged them to come back to me with their
finding and say &lt;em&gt;"dude, the problem is in your input data"&lt;/em&gt; and I'd have
fixed my original Markdown.&lt;/p&gt;
&lt;p&gt;Here though it just went right ahead and added this one weird edge case as
something to handle.&lt;/p&gt;
&lt;p&gt;I think this is something to be concerned about and to keep an eye on too. I
feel there's a danger in having the agent rabbit-hole a fix for a problem
that it should simply have reported back to me for further discussion.&lt;/p&gt;
&lt;h3 id="the-never-pushes-back-problem"&gt;The never-pushes-back problem&lt;a aria-label="Link to this heading" class="heading-anchor" href="#the-never-pushes-back-problem"&gt;¶&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Something I did find unsurprising but disconcerting was Copilot's
unwillingness to push back, or at least defend its choices. Sometimes it
would make a decision or a change and I'd simply ask it why it had done it
that way, why it had made that choice. Rather than reply with its reasoning
it would pretty much go &lt;em&gt;"yeah, my bad, let me do it a way you're probably
going to find more pleasing"&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A simple example of this is one time when I saw some code like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@property&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;some_property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SomeValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;blogmore.utils&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;some_utility_function&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I'm not a fan of imports in the body of methods &lt;em&gt;unless&lt;/em&gt; there's a
demonstrable performance reason. I asked Copilot why it had made this choice
here and its reply was simply to say it had gone ahead and changed the code,
moving the import to the top of the module.&lt;/p&gt;
&lt;p&gt;I see plenty of people talk about how working with an agent is like
pair-programming, but I think it misses out on what's got to be the biggest
positive of that approach: the debate and exchange of ideas. This again
feels like a concern to be mindful of, especially if someone less
experienced is bringing code to you where they've used an agent as their
pair buddy.&lt;/p&gt;
&lt;h2 id="the-overall-impression"&gt;The overall impression&lt;a aria-label="Link to this heading" class="heading-anchor" href="#the-overall-impression"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now I'm at the end of the process, and using the result of this experiment
to write this post&lt;sup id="fnref:143-4"&gt;&lt;a class="footnote-ref" href="#fn:143-4"&gt;4&lt;/a&gt;&lt;/sup&gt;, I feel better informed about what these tools offer,
and the pitfalls I need to be mindful of. Sometimes it wasn't a terrible way
of working. For example, on the first day I started with this, at one point
on a chilly but sunny Sunday afternoon, I was sat on the sofa, MacBook on
lap, guiding an AI to write code, while petting the cat, watching the birds
in the garden enjoy the content of the feeder, all while chatting with my
partner.&lt;/p&gt;
&lt;p&gt;That's not a terrible way to write code.&lt;/p&gt;
&lt;p&gt;On the other hand, as I said earlier, I missed the flow state. I &lt;em&gt;love&lt;/em&gt;
getting lost in code for a few hours and this is not that. I also found the
constant loop of prompt, wait, review, test, repeat, really quite
exhausting.&lt;/p&gt;
&lt;p&gt;As best as I can describe it: it feels like the fast food of software
development. It gets the job done, it gets it done fast, but it's really not
fulfilling.&lt;/p&gt;
&lt;p&gt;At the end of the process I have a really useful tool, 100% "built with AI",
under my guidance, which lets me &lt;em&gt;actually&lt;/em&gt; be creative and build things I
do create by hand. That's not a bad thing, I can see why this is appealing
to people. On the other hand the process of building that tool was pretty
boring and, for want of a better word... soulless.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;a aria-label="Link to this heading" class="heading-anchor" href="#conclusion"&gt;¶&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As I write this I have about 24 hours of access to GitHub Copilot Pro left.
It seems this experiment used up my preview time and triggered a &lt;em&gt;"looks
like you're having fun, now you need to decide if you want to buy it"&lt;/em&gt;
response. That's fair.&lt;/p&gt;
&lt;p&gt;So now I'm left trying to decide if I want to pay to keep it going. At the
level I've been using it at for building BlogMore it looks like it costs
$10/mth. That actually isn't terrible. I spend more than that on other
hobbies and other forms of entertainment. So, if I can work within the
bounds of that tier, it's affordable and probably worth it.&lt;/p&gt;
&lt;p&gt;What I'm not sure about yet is if I want to. It's been educational, I can
100% see how and where I'd use this for work (and would of course expect an
employer to foot the bill for it or a similar tool), and I can also see how
and where I might use it to quickly build a personal-use tool to enable
something more human-creative.&lt;/p&gt;
&lt;p&gt;Ultimately though I think I'm a little better informed thanks to this
process, and better aware of some of the wins people claim, and also better
informed so that I can be rightly incredulous when faced with some of the
wilder claims.&lt;/p&gt;
&lt;p&gt;Also, it'll help put &lt;a href="https://raindrop.io/davep/public-46742255/search/sort=-created&amp;amp;perpage=30&amp;amp;page=0&amp;amp;search=%23AI" rel="noopener noreferrer" target="_blank"&gt;some of my
reading&lt;/a&gt;
into perspective.&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:143-1"&gt;
&lt;p&gt;Amusingly I &lt;a href="https://github.com/davep/blogmore/issues/117" rel="noopener noreferrer" target="_blank"&gt;uncovered another
bug&lt;/a&gt; while writing this
post.&amp;#160;&lt;a class="footnote-backref" href="#fnref:143-1" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:143-2"&gt;
&lt;p&gt;I keep saying Copilot, but I think it's probably more correct to say
"Claude Sonnet 4.5" as that's what seemed to be at play under the hood,
if I'm understanding things correctly.&amp;#160;&lt;a class="footnote-backref" href="#fnref:143-2" title="Jump back to footnote 2 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:143-3"&gt;
&lt;p&gt;Yes, of course that's an anthropomorphism, you'll find plenty of them
in this article as it's hard not to write about the subject in any other
way; it's an easy shortcut to explain some ideas&amp;#160;&lt;a class="footnote-backref" href="#fnref:143-3" title="Jump back to footnote 3 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn:143-4"&gt;
&lt;p&gt;Actually I'm writing this post as I always do: in Emacs. But BlogMore
is in the background serving a local copy of my blog so I can check it
in the browser, and rebuilding it every time I save a change.&amp;#160;&lt;a class="footnote-backref" href="#fnref:143-4" title="Jump back to footnote 4 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description>
      <guid isPermaLink="false">https://blog.davep.org/2026/02/20/five-days-with-copilot.html</guid>
      <category>AI</category>
      <category>Python</category>
      <category>Blogging</category>
      <category>AI</category>
      <category>LLM</category>
      <category>Copilot</category>
      <category>GitHub</category>
      <category>BlogMore</category>
      <pubDate>Fri, 20 Feb 2026 15:46:00 +0000</pubDate>
    </item>
  </channel>
</rss>
