<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: alapha888</title>
    <description>The latest articles on DEV Community by alapha888 (@alapha888).</description>
    <link>https://dev.to/alapha888</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4153828%2F6afb4be1-2a52-4c73-a96a-cf85e344659f.png</url>
      <title>DEV Community: alapha888</title>
      <link>https://dev.to/alapha888</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alapha888"/>
    <language>en</language>
    <item>
      <title>My session-handoff skill was rejected from awesome-copilot — the maintainer had a point</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Thu, 22 Oct 2026 07:46:03 +0000</pubDate>
      <link>https://dev.to/alapha888/my-session-handoff-skill-was-rejected-from-awesome-copilot-the-maintainer-had-a-point-4kod</link>
      <guid>https://dev.to/alapha888/my-session-handoff-skill-was-rejected-from-awesome-copilot-the-maintainer-had-a-point-4kod</guid>
      <description>&lt;p&gt;Today (October 22, 2026) my pull request to add the &lt;code&gt;session-handoff&lt;/code&gt; skill to GitHub's awesome-copilot collection was closed. The maintainer, Aaron Powell, left one sentence of reasoning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This isn't ideal as it's introducing rules that can conflict/contradict with the process that the harness has in place for handling compaction, sub-agent spawning, and memory management.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is a fair criticism, and it is aimed at a real weakness in how I had positioned the skill.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the criticism lands
&lt;/h2&gt;

&lt;p&gt;The kit's pitch was universal: end every session with a structured handoff note, so the next session starts from facts instead of a degraded, over-full context. Inside a harness that already owns compaction, sub-agent spawning, and memory management, an extra set of handoff rules is not neutral. It can contradict the machinery that is already doing that job, and the agent is left following two processes at once.&lt;/p&gt;

&lt;p&gt;A listing in awesome-copilot is read as "this fits the Copilot way of working." By that standard, a blanket handoff ritual does not fit, and the PR was correctly closed. The full exchange is public: &lt;a href="https://github.com/github/awesome-copilot/pull/5097" rel="noopener noreferrer"&gt;https://github.com/github/awesome-copilot/pull/5097&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where a written handoff still earns its keep
&lt;/h2&gt;

&lt;p&gt;The rejection narrows the claim; it does not erase the use case. A short, structured handoff note still does work that no single harness owns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Switching between different agents or tools.&lt;/strong&gt; Claude Code, Codex, and Gemini CLI do not share memory. When work moves from one to another, a written handoff is the only continuity there is — no harness spans that gap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resuming after days, not minutes.&lt;/strong&gt; Harness memory serves the agent. A handoff note also serves the human: a readable record of what was decided and why, which you can audit before the next session spends tokens re-deriving it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harnesses with no built-in handling.&lt;/strong&gt; Not every agent runtime compacts or persists memory. In those, the ritual is not duplication; it is the only version of the process that exists.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What I changed today
&lt;/h2&gt;

&lt;p&gt;I added a "When you may not need this" section to the kit's README, stating plainly that if your harness already handles compaction and memory well, you should skip the skill and let the harness do its job — with the awesome-copilot review credited as the source of that point. The universal pitch is gone; the three gaps above are now the stated scope.&lt;/p&gt;

&lt;p&gt;The kit itself is unchanged and still free (MIT):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/alapha888/session-handoff-kit" rel="noopener noreferrer"&gt;https://github.com/alapha888/session-handoff-kit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Install: &lt;code&gt;npx skills add alapha888/session-handoff-kit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;skills.sh: &lt;a href="https://skills.sh/alapha888/session-handoff-kit" rel="noopener noreferrer"&gt;https://skills.sh/alapha888/session-handoff-kit&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A rejection with a specific reason is the most useful review a listing PR can get. This one cost nothing, took a day, and made the README more honest than I had managed on my own.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Day 4 of the ubuntu-latest rollout: weekly workflows get their first chance at the new image — cadence decides when it reaches you</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Wed, 21 Oct 2026 17:50:32 +0000</pubDate>
      <link>https://dev.to/alapha888/day-4-of-the-ubuntu-latest-rollout-weekly-workflows-get-their-first-chance-at-the-new-image--1gf3</link>
      <guid>https://dev.to/alapha888/day-4-of-the-ubuntu-latest-rollout-weekly-workflows-get-their-first-chance-at-the-new-image--1gf3</guid>
      <description>&lt;p&gt;The ubuntu-latest migration window opened on October 19, 2026 and runs to November 19. Inside that window, &lt;code&gt;ubuntu-latest&lt;/code&gt; moves from Ubuntu 24.04 to Ubuntu 26.04 in stages, so any single run may land on either image. Day 1 covered the workflows that run on every push. Day 3 covered the ones that had not run at all. Day 4 is about cadence: a workflow on a weekly schedule has a first run inside the window, and for a Thursday or Friday schedule that first run is still ahead of you — or happens tonight.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why cadence decides when this can reach you
&lt;/h2&gt;

&lt;p&gt;The rollout cannot reach a workflow that does not run. Push-triggered workflows had their first chance to land on 26.04 on day 1, and have had many chances since. A workflow that runs every Monday has had at most one scheduled run inside the window, and that run may or may not have landed on the new image. A workflow scheduled for Thursdays has not run at all since the window opened — tonight is its first chance, under whatever your &lt;code&gt;cron&lt;/code&gt; line says, quite possibly while nobody is watching.&lt;/p&gt;

&lt;p&gt;The same applies to anything rarer: release-only workflows, monthly maintenance jobs, manually dispatched checks. Each has its own first chance, and it is the day it next runs, not October 19.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where my own re-walk stands
&lt;/h2&gt;

&lt;p&gt;I have re-run my scanner (RunnerDriftAudit v0.3.8) against a frozen October 13 baseline on October 20 and again on October 21. Both re-walks reproduced the baseline exactly — 4/2, 4/2, 0/2 across the three targets, no rows moved, no migration-effect rows yet. The scanner reads workflow files, and those files have not changed — that part is cadence-independent. What cadence changes is when a different machine first executes those files, and that shows up in run results, not in a scan. That gap between "files unchanged" and "has it actually run on 26.04 yet" is precisely what this cadence check exists to close.&lt;/p&gt;

&lt;h2&gt;
  
  
  The day-4 check (about 10 minutes)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;List your scheduled and dispatch-only workflows — anything that does not trigger on push or pull request. Note each one's next scheduled run.&lt;/li&gt;
&lt;li&gt;For the ones that have already run since October 19, compare that run's result against the last pre-October 19 run. A failure that starts exactly at the first post-window run is a rollout candidate, not a coincidence.&lt;/li&gt;
&lt;li&gt;For the ones that have not run yet, consider dispatching them manually today, while the pre-migration state is still fresh in mind and both runner images are still in rotation. A controlled first run beats a scheduled surprise.&lt;/li&gt;
&lt;li&gt;Keep the macos-14 retirement separate: those labels retire on November 2, 2026 — 11 days from today (October 22) — and jobs on them will fail outright, not drift. Different problem, different fix, same calendar pressure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tool
&lt;/h2&gt;

&lt;p&gt;I run these checks with RunnerDriftAudit, a free static scanner for GitHub Actions workflow files (it reads the YAML; it does not execute your jobs, and it cannot see runtime-only behaviour):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/alapha888/runner-drift-audit" rel="noopener noreferrer"&gt;https://github.com/alapha888/runner-drift-audit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Current release: v0.3.8 (October 20, 2026) — &lt;a href="https://gist.github.com/alapha888/263d0f3741ff5f9389d11203b8c4fb97" rel="noopener noreferrer"&gt;https://gist.github.com/alapha888/263d0f3741ff5f9389d11203b8c4fb97&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Multi-repo edition (one combined report for a whole local workspace), $29 one-time: &lt;a href="https://alapha888.gumroad.com/l/mepra" rel="noopener noreferrer"&gt;https://alapha888.gumroad.com/l/mepra&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Day-4 field note (Gist): &lt;a href="https://gist.github.com/alapha888/adc3560a1b50a7e970a882407c27c078" rel="noopener noreferrer"&gt;https://gist.github.com/alapha888/adc3560a1b50a7e970a882407c27c078&lt;/a&gt;&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>devops</category>
      <category>ci</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Day 3 of the ubuntu-latest rollout: the new image reaches repos at different times — re-run, don't assume</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Wed, 21 Oct 2026 13:00:10 +0000</pubDate>
      <link>https://dev.to/alapha888/day-3-of-the-ubuntu-latest-rollout-the-new-image-reaches-repos-at-different-times-re-run-dont-2h73</link>
      <guid>https://dev.to/alapha888/day-3-of-the-ubuntu-latest-rollout-the-new-image-reaches-repos-at-different-times-re-run-dont-2h73</guid>
      <description>&lt;p&gt;The ubuntu-latest migration window opened on October 19, 2026 and runs to November 19. Inside that window, &lt;code&gt;ubuntu-latest&lt;/code&gt; moves from Ubuntu 24.04 to Ubuntu 26.04 — but not for every repository at the same moment. The rollout is staged, so on day 3 the honest status for your repos is "unknown", not "fine".&lt;/p&gt;

&lt;h2&gt;
  
  
  What I can verify from my own estate
&lt;/h2&gt;

&lt;p&gt;On October 20 I re-ran my scanner (v0.3.7) against the three targets from my frozen October 13 baseline. The baseline reproduced exactly — 4 HIGH / 2 WARN, 4 HIGH / 2 WARN, 0 HIGH / 2 WARN — with no finding changing state and no migration-effect rows yet.&lt;/p&gt;

&lt;p&gt;On October 21 I ran the same check again, with scanner v0.3.8. Same result, row for row: 4/2, 4/2, 0/2, the two manual rows (container images, locale/timezone defaults) still inert, and still no migration-effect rows. That tells me the rollout had not changed anything &lt;em&gt;for those targets&lt;/em&gt; by October 21. It says nothing about your repos — and a static scan cannot see the moment the image flips for a given repository anyway. A real migration effect would show up as a CI behaviour change on deliberately floated jobs, not as a count delta in a table like this.&lt;/p&gt;

&lt;p&gt;Two failure modes hide in that gap:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The workflow that hasn't run.&lt;/strong&gt; If a workflow has not executed since October 19, it has never touched the 26.04 image. Its next run — possibly a release run — is the first test. The two images differ in 22 toolset entries (default versions moved, some tools removed), so "it was green last week" is evidence about the old image only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The silent tool change.&lt;/strong&gt; A workflow that did run may have picked up a new default tool version and stayed green by luck — a deprecation warning today, a hard failure when the old version disappears. Green is not the same as unaffected.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The day-3 check (about 10 minutes)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Re-run a scan of your workflow files today and compare the finding counts against a baseline you trust. If the counts moved and you didn't edit anything, the rollout reached you — read the moved rows first.&lt;/li&gt;
&lt;li&gt;Look specifically for findings about default tool versions and removed tools. Those are the rows that turn into failures without any commit of yours.&lt;/li&gt;
&lt;li&gt;For every floating label, decide on purpose: pin it (label or tool version) or keep floating and accept the drift. Either is defensible; drifting by accident is not.&lt;/li&gt;
&lt;li&gt;Write the result down in one line — date, scanner version, counts. The next check is only useful if this one left a record.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The other clock
&lt;/h2&gt;

&lt;p&gt;Separate from the Ubuntu move: the macos-14 runner image retires on November 2, 2026 — 12 days from today (October 21). The October 19 brownouts were the rehearsal. Any workflow still referencing macos-14 (including indirectly, through a matrix variable or a reusable workflow) stops working entirely on that date, not gradually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool
&lt;/h2&gt;

&lt;p&gt;I run these checks with RunnerDriftAudit, a free static scanner for GitHub Actions workflow files (it reads the YAML; it does not execute your jobs, and it cannot see runtime-only behaviour):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/alapha888/runner-drift-audit" rel="noopener noreferrer"&gt;https://github.com/alapha888/runner-drift-audit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Current release: v0.3.8 (October 20, 2026) — &lt;a href="https://gist.github.com/alapha888/263d0f3741ff5f9389d11203b8c4fb97" rel="noopener noreferrer"&gt;https://gist.github.com/alapha888/263d0f3741ff5f9389d11203b8c4fb97&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Multi-repo edition (one combined report for a whole local workspace), $29 one-time: &lt;a href="https://alapha888.gumroad.com/l/mepra" rel="noopener noreferrer"&gt;https://alapha888.gumroad.com/l/mepra&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full day-3 field report: &lt;a href="https://gist.github.com/alapha888/cffe20f75f6d4984949a4534f3b6e8ca" rel="noopener noreferrer"&gt;https://gist.github.com/alapha888/cffe20f75f6d4984949a4534f3b6e8ca&lt;/a&gt;&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>devops</category>
      <category>ci</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Migration Window, Morning One: My Scanner Caught One of My Own Repos Still on macos-14</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Tue, 20 Oct 2026 14:56:14 +0000</pubDate>
      <link>https://dev.to/alapha888/migration-window-morning-one-my-scanner-caught-one-of-my-own-repos-still-on-macos-14-5gnf</link>
      <guid>https://dev.to/alapha888/migration-window-morning-one-my-scanner-caught-one-of-my-own-repos-still-on-macos-14-5gnf</guid>
      <description>&lt;p&gt;Yesterday, October 19, two GitHub runner changes started on the same morning: the &lt;code&gt;ubuntu-latest&lt;/code&gt; label began its rolling move to Ubuntu 26.04 (through November 19), and the first &lt;code&gt;macos-14&lt;/code&gt; brownout ran that night, 14:00–24:00 UTC, ahead of the November 2 retirement of that image.&lt;/p&gt;

&lt;p&gt;Before writing anything else about either change, I ran my own scanner — RunnerDriftAudit v0.3.7 — on the five repositories I maintain that actually have workflows. Six workflow files. The result was not a victory lap.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the scan found at home
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Repo&lt;/th&gt;
&lt;th&gt;HIGH&lt;/th&gt;
&lt;th&gt;What it was&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;photoveil-ios&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;RETIRED_LABEL&lt;/code&gt; — CI still on &lt;code&gt;macos-14&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cn-ai-coding-workflow-lite&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Floating &lt;code&gt;ubuntu-latest&lt;/code&gt; / &lt;code&gt;macos-latest&lt;/code&gt; / &lt;code&gt;windows-latest&lt;/code&gt; in the install-test matrix, plus a standalone &lt;code&gt;windows-latest&lt;/code&gt; job&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cn-ai-coding-workflow&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;The same four as the lite repo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pubaudit-windows&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Floating &lt;code&gt;windows-latest&lt;/code&gt; in both workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;runner-drift-audit&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;— (2 WARN: &lt;code&gt;actions/checkout@v4&lt;/code&gt; not pinned to a SHA)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Eleven HIGH findings in total (1 + 4 + 4 + 2 + 0 across the table), all floating or retired labels — in the repos of the person who wrote the scanner. Separate from those, almost every file also carried a WARN: &lt;code&gt;actions/checkout&lt;/code&gt; referenced by the mutable &lt;code&gt;v4&lt;/code&gt; tag instead of a full commit SHA.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one that would have gone red that night
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;photoveil-ios&lt;/code&gt; finding was the real one. Its CI was still running on &lt;code&gt;macos-14&lt;/code&gt; — the image that started failing on purpose that night during the brownout window and stops working entirely on November 2. Nothing about the repo had changed; the label underneath it was expiring.&lt;/p&gt;

&lt;p&gt;The fix was one line, &lt;code&gt;macos-14&lt;/code&gt; → &lt;code&gt;macos-15&lt;/code&gt;, pushed the same morning. CI on the new image passed in 32 seconds (core tests and iOS typecheck; run 39146373675 in that repo's history, if you want to check rather than take my word for it).&lt;/p&gt;

&lt;p&gt;That is the whole argument for scanning before the window, not after the first red build: this class of finding is invisible until the day it turns red, and for &lt;code&gt;macos-14&lt;/code&gt; that day was October 19.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I deliberately did not fix
&lt;/h2&gt;

&lt;p&gt;The other floating labels stayed floating — by decision, now written down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The two &lt;code&gt;cn-ai-coding-workflow&lt;/code&gt; install-test matrices exist to prove an install script works on whatever "latest" currently means across three operating systems. Pinning those labels would defeat the test. If a leg goes red during the rollout, that red &lt;em&gt;is&lt;/em&gt; the signal the job exists to produce.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;windows-latest&lt;/code&gt; jobs ride no announced migration in this window, so they stay floating for now, recorded as checked-and-inert rather than unexamined.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And one honest non-fix: the unpinned &lt;code&gt;actions/checkout@v4&lt;/code&gt; warnings are still open, including in the scanner's own self-test workflow. The scanner reports it; I have not done that pass yet. It is recorded as not-yet-fixed, not quietly dropped from the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you have not scanned yet
&lt;/h2&gt;

&lt;p&gt;The window is still open: &lt;code&gt;ubuntu-latest&lt;/code&gt; keeps rolling through November 19, and &lt;code&gt;macos-14&lt;/code&gt; retires on November 2. A scan takes under a minute per repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 runner_drift_audit.py path/to/your-repo &lt;span class="nt"&gt;--json&lt;/span&gt; day1.json &lt;span class="nt"&gt;--summary-file&lt;/span&gt; day1-summary.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scanner is free and open source (MIT, single-file Python, standard library only): &lt;a href="https://github.com/alapha888/runner-drift-audit" rel="noopener noreferrer"&gt;https://github.com/alapha888/runner-drift-audit&lt;/a&gt; — the full morning scan, including the rows I left alone and why, is in &lt;code&gt;field-reports/2026-10-19-day1-self-scan.md&lt;/code&gt;. The next day I re-ran the frozen October 13 baseline inventory for the scheduled comparison with a reader who walked the same checklist on his own machine; nothing in that baseline inventory moved (the &lt;code&gt;photoveil-ios&lt;/code&gt; fix above was part of the day-1 scan, not of that baseline), and why that is itself the finding is written up here: &lt;a href="https://dev.to/alapha888/post-cutover-re-walk-nothing-moved-and-why-that-is-the-finding-287o"&gt;https://dev.to/alapha888/post-cutover-re-walk-nothing-moved-and-why-that-is-the-finding-287o&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you maintain many repositories, a paid batch edition ($29 one-time) scans a whole workspace into one merged HTML report: &lt;a href="https://alapha888.gumroad.com/l/mepra" rel="noopener noreferrer"&gt;https://alapha888.gumroad.com/l/mepra&lt;/a&gt; — the free single-repo tool stays free either way.&lt;/p&gt;

&lt;p&gt;One repo, one retired label, one line fixed before the window opened. I would rather read about where the checklist bends on your repos than hear it was all green.&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>cicd</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Post-Cutover Re-Walk: Nothing Moved — and Why That Is the Finding</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Tue, 20 Oct 2026 14:01:07 +0000</pubDate>
      <link>https://dev.to/alapha888/post-cutover-re-walk-nothing-moved-and-why-that-is-the-finding-287o</link>
      <guid>https://dev.to/alapha888/post-cutover-re-walk-nothing-moved-and-why-that-is-the-finding-287o</guid>
      <description>&lt;p&gt;On October 13, before the migration window opened, I froze a baseline: three of my own workflow files, scanned with RunnerDriftAudit v0.3.2, every row written down. The agreement — made in the open, in a comment thread with a reader who ran the same checklist on his own machine — was that after the window opened, we would both re-run the same inventory and compare second reports line by line.&lt;/p&gt;

&lt;p&gt;The window opened yesterday, October 19: &lt;code&gt;ubuntu-latest&lt;/code&gt; began its rolling move to Ubuntu 26.04 (through November 19), and the first &lt;code&gt;macos-14&lt;/code&gt; brownout ran last night. This morning I re-ran the frozen inventory. Here is the whole result:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;HIGH&lt;/th&gt;
&lt;th&gt;WARN&lt;/th&gt;
&lt;th&gt;Delta vs baseline&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;cn-ai-coding-workflow &lt;code&gt;test-install.yml&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;none — identical rows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cn-ai-coding-workflow-lite &lt;code&gt;test-install.yml&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;none — identical rows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;runner-drift-audit self-test&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;none — identical rows&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No row moved. Nothing flipped from checked-inert to flagged. The two manual rows I track alongside the scan — container images pulled by tag, and locale/timezone defaults — are still inert, grep-verified on the day: this inventory pulls no container images, and its steps still only count files and grep frontmatter.&lt;/p&gt;

&lt;h2&gt;
  
  
  A null result is still a result — if the baseline was frozen
&lt;/h2&gt;

&lt;p&gt;It would be easy to read that table as "nothing happened, nothing to write." That reading is wrong in a specific way, and the specificity is the point of freezing a baseline before the event instead of reconstructing one after it.&lt;/p&gt;

&lt;p&gt;The scanner flags the floating &lt;code&gt;ubuntu-latest&lt;/code&gt; label itself. Its counts therefore do not change when the image underneath the label flips — by design. A count delta was never the signal this inventory could produce. Any real migration effect would show up as a behaviour change in CI on the jobs I deliberately left floating (the install-test matrices exist to go red if "latest" breaks the install script), not as a new row in this table.&lt;/p&gt;

&lt;p&gt;So the honest statement is narrow: on day one of the window, the platform switch produced no scanner-visible change in this inventory, and the floated jobs have not gone red. That is a dated, checkable claim — the run script, the raw scanner output, and the scanner's SHA256 are all in the repo — not a vibe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Version honesty, because the scanner changed too
&lt;/h2&gt;

&lt;p&gt;One trap in any before/after comparison: the measuring tool moved between measurements. Mine did, and the report separates that from platform effects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Baseline scanner: v0.3.2 (October 13). Re-walk scanner: v0.3.7, test suite 64 passed on the day.&lt;/li&gt;
&lt;li&gt;v0.3.3–v0.3.6 changed output formats only (Marketplace metadata, SARIF export, JSON export, Markdown summary) — no rule changes that affect counts.&lt;/li&gt;
&lt;li&gt;v0.3.7 did add one rule: &lt;code&gt;RETIRED_LABEL&lt;/code&gt;, a HIGH for workflows pinned to the retiring &lt;code&gt;macos-14&lt;/code&gt; labels. None of the three baseline targets pin &lt;code&gt;macos-14&lt;/code&gt;, so the new rule changed no count here. It is listed in the report anyway, so that a future &lt;code&gt;macos-14&lt;/code&gt; finding is never mistaken for a migration effect.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your own before/after numbers moved, the first question is which of those two columns moved them: the platform, or your tooling.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is still open
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The other half of the exchange is pending: my counterpart's second report has not arrived yet. My reply, with the filled comparison template, goes into the original thread today; his rows will be recorded as a dated addendum when they land, including any line where we disagree.&lt;/li&gt;
&lt;li&gt;The deliberately floated jobs stay floating through the window (until November 19). If one goes red, that red is the signal the job exists to produce, and it will get its own field report.&lt;/li&gt;
&lt;li&gt;The unpinned &lt;code&gt;actions/checkout@v4&lt;/code&gt; warnings are still open, including in the scanner's own self-test. Still recorded as not-yet-fixed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The scanner is free and open source (MIT, single-file Python, standard library only): &lt;a href="https://github.com/alapha888/runner-drift-audit" rel="noopener noreferrer"&gt;https://github.com/alapha888/runner-drift-audit&lt;/a&gt; — the full re-walk, including the rows that did not move and the version-honesty table, is in &lt;code&gt;field-reports/2026-10-20-post-cutover-self-audit.md&lt;/code&gt;. If you maintain many repositories, a paid batch edition ($29 one-time) scans a whole workspace into one merged HTML report: &lt;a href="https://alapha888.gumroad.com/l/mepra" rel="noopener noreferrer"&gt;https://alapha888.gumroad.com/l/mepra&lt;/a&gt; — the free single-repo tool stays free either way.&lt;/p&gt;

&lt;p&gt;If you froze a baseline before the window opened, I would like to compare rows — especially if yours moved and mine did not.&lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>cicd</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Your Agent Forgets Nothing — That's the Problem. End Sessions With a Handoff Note</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Tue, 13 Oct 2026 01:10:18 +0000</pubDate>
      <link>https://dev.to/alapha888/your-agent-forgets-nothing-thats-the-problem-end-sessions-with-a-handoff-note-5f79</link>
      <guid>https://dev.to/alapha888/your-agent-forgets-nothing-thats-the-problem-end-sessions-with-a-handoff-note-5f79</guid>
      <description>&lt;p&gt;Long sessions with a coding agent often follow a familiar shape. The first hour is sharp. A few hours in, the context is full of dead ends: files you opened and rejected, approaches you tried and abandoned, a refactor you rolled back. The agent still carries all of it in context — and its answers tend to get worse, because the useful state is buried under stale exploration.&lt;/p&gt;

&lt;p&gt;The usual fixes are blunt. &lt;code&gt;/clear&lt;/code&gt; throws away the state along with the noise. &lt;code&gt;/compact&lt;/code&gt; lets the model summarize itself, and the next session starts from that summary — with whatever the summary left out. Starting fresh usually means re-explaining the context by hand.&lt;/p&gt;

&lt;p&gt;There is a smaller habit that works better: before you reset, capture the state in a format the next session can execute from.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a useful handoff note contains
&lt;/h2&gt;

&lt;p&gt;Not a transcript, and not a summary of everything that happened. Five things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Goal state&lt;/strong&gt; — what you were trying to do, and how far it got.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decisions, with reasons&lt;/strong&gt; — especially the approaches you rejected, so the next session doesn't retry them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Files touched&lt;/strong&gt; — what changed, and what's mid-change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open loops&lt;/strong&gt; — unverified assumptions, failing tests, questions nobody answered yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next action&lt;/strong&gt; — one concrete step, not a list of possibilities.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Writing this down at the end of a session is quicker than re-deriving it at the start of the next one. And because the note is plain text, it works the same when the "next session" is a different agent, or you next week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it a skill instead of a resolution
&lt;/h2&gt;

&lt;p&gt;Habits that depend on remembering to do them tend to last a week. So I packaged the routine as an installable agent skill: &lt;strong&gt;Session Handoff Kit&lt;/strong&gt; (free, MIT).&lt;/p&gt;

&lt;p&gt;It contains three files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SKILL.md&lt;/code&gt; — the skill itself. When context fills up or a session ends, the agent produces a structured handoff note in the five-part format above.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;context-hygiene-checklist.md&lt;/code&gt; — a one-page decision guide: when to &lt;code&gt;/clear&lt;/code&gt;, when to &lt;code&gt;/compact&lt;/code&gt;, when to start fresh, plus the 2-minute routine to run before any reset.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;handoff-template.md&lt;/code&gt; — a fill-in template with per-section guidance, for working without the skill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install with the skills CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add alapha888/session-handoff-kit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or copy &lt;code&gt;SKILL.md&lt;/code&gt; into a &lt;code&gt;session-handoff&lt;/code&gt; folder in your agent's skills directory. It works with Claude Code, Codex, and Cursor-style skill setups.&lt;/p&gt;

&lt;p&gt;The kit is listed on &lt;a href="https://www.skills.sh/alapha888/session-handoff-kit" rel="noopener noreferrer"&gt;skills.sh&lt;/a&gt;, and the source is on GitHub: &lt;a href="https://github.com/alapha888/session-handoff-kit" rel="noopener noreferrer"&gt;alapha888/session-handoff-kit&lt;/a&gt;. Feedback and issues are welcome there.&lt;/p&gt;

&lt;p&gt;You can also read the checklist on its own as a Gist: &lt;a href="https://gist.github.com/alapha888/7c7f0241ccd23d8a479a47ccaacf4b83" rel="noopener noreferrer"&gt;Context Hygiene Checklist for AI Coding Agents&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The point isn't the tooling — a plain text file works fine. The point is the order of operations: capture state &lt;em&gt;before&lt;/em&gt; you reset, in a format the next session can act on without re-asking you everything.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>ai</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>What's Hidden in Your Photos: Understanding EXIF Metadata Before You Share</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Tue, 13 Oct 2026 01:09:51 +0000</pubDate>
      <link>https://dev.to/alapha888/whats-hidden-in-your-photos-understanding-exif-metadata-before-you-share-43ll</link>
      <guid>https://dev.to/alapha888/whats-hidden-in-your-photos-understanding-exif-metadata-before-you-share-43ll</guid>
      <description>&lt;p&gt;Whenever you snap a photo with a smartphone, the file captures more than just visual pixels. Bundled inside the container is EXIF (Exchangeable Image File Format) data—a structured set of technical headers generated automatically by the camera hardware and operating system.&lt;/p&gt;

&lt;p&gt;Most messaging apps and major social platforms re-encode images and strip this metadata on upload. However, when sharing original files directly—via AirDrop, email attachments, shared cloud folders, or web upload forms—those headers travel along untouched.&lt;/p&gt;

&lt;p&gt;Here is a closer look at what EXIF carries, what cleaning it achieves, and where automated metadata removal fits into everyday file sharing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What EXIF Metadata Contains
&lt;/h2&gt;

&lt;p&gt;Modern smartphone cameras log granular operational telemetry at the exact millisecond of capture. A standard raw export typically contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Precise Geolocation&lt;/strong&gt;: Exact GPS latitude, longitude, altitude, and sometimes even the compass direction the lens was facing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamps&lt;/strong&gt;: The precise local date, time, and timezone offset of when the shutter opened, as well as modification timestamps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hardware Identifiers&lt;/strong&gt;: Device make, model, lens specifications, focal length, aperture, shutter speed, and sensor ISO settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Software Signatures&lt;/strong&gt;: Operating system build version, camera firmware, and identifiers for any third-party editing tools used prior to export.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Individually, these fields help photo library managers organize albums chronologically and geographically. Taken together in shared files, they construct a reliable pattern of routine, location, and equipment.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Concrete Scenario: The Rental Application
&lt;/h2&gt;

&lt;p&gt;Consider submitting paperwork for a rental application or verifying an identity online. The property manager or platform asks for a snapshot of a utility bill, proof of address, or a government ID card.&lt;/p&gt;

&lt;p&gt;You take a photo on your living room table and attach the original JPEG or HEIC file directly to an email or a form portal.&lt;/p&gt;

&lt;p&gt;Beyond the visual document on the table, the file header now confirms:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The exact coordinates of your private residence.&lt;/li&gt;
&lt;li&gt;The exact time of day you took the picture.&lt;/li&gt;
&lt;li&gt;The specific phone hardware you own.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In contexts where you only intended to submit the visual document, the attached telemetry provides unnecessary, persistent data points to whatever third-party server stores that file.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Metadata Cleaning Can and Cannot Do
&lt;/h2&gt;

&lt;p&gt;It is important to be precise about what metadata scrubbing actually accomplishes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What it can do&lt;/strong&gt;: It removes header dictionaries—such as EXIF, TIFF, GPS, IPTC, and XMP payloads—leaving an image container that contains only raw visual pixel arrays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What it cannot do&lt;/strong&gt;: It does not alter the visible content inside the image frame. If your document shows an ID number, a visible house number in the background, or an unredacted signature, metadata stripping does nothing to obscure that information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cleaning metadata isolates visual data from digital forensics. It does not replace deliberate visual redaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Metadata on iOS: The PhotoVeil Approach
&lt;/h2&gt;

&lt;p&gt;Checking and stripping metadata on iOS usually involves third-party tools, shortcuts, or exporting through intermediary utilities. When evaluating tools for this workflow, the primary technical consideration is whether cleaning degrades image quality or routes files through remote infrastructure.&lt;/p&gt;

&lt;p&gt;We are currently building &lt;strong&gt;PhotoVeil&lt;/strong&gt;, an upcoming iOS utility designed to address these specific workflows locally on-device.&lt;/p&gt;

&lt;p&gt;Its implementation focuses on a few core principles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Inspection Before Export&lt;/strong&gt;: It generates an on-screen EXIF report highlighting potentially sensitive elements (such as embedded coordinates and device identifiers) before you decide to send a file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lossless JPEG Cleaning Where Possible&lt;/strong&gt;: For standard JPEG images that do not require rotation or dimensional transformation, PhotoVeil strips metadata losslessly. It excises the metadata application segments directly and copies the image bitstream byte-for-byte, avoiding re-compression artifacts. Other formats or transformed images are cleanly re-encoded without metadata headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purpose-Bound Watermarking&lt;/strong&gt;: For sensitive document submissions (like identity cards or lease forms), the tool can tile a custom watermark across copies—such as &lt;em&gt;"For rental application only"&lt;/em&gt;—limiting unauthorized reuse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Architecture&lt;/strong&gt;: It utilizes the native iOS system photo picker, requires no accounts, includes no tracking, and performs all processing entirely on-device with zero network transmissions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The free tier includes inspection reports and single-photo metadata removal. A one-time purchase option unlocks batch operations, document watermarking, and format conversions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Waitlist
&lt;/h2&gt;

&lt;p&gt;PhotoVeil is currently in active development for iOS. If you are interested in testing early builds and keeping track of release updates, you can join the waitlist at &lt;a href="https://alapha888.github.io/photoveil-waitlist/" rel="noopener noreferrer"&gt;https://alapha888.github.io/photoveil-waitlist/&lt;/a&gt; .&lt;/p&gt;

</description>
      <category>ios</category>
      <category>privacy</category>
      <category>mobile</category>
      <category>photography</category>
    </item>
    <item>
      <title>Formatting Markdown for WeChat, Zhihu and Juejin from one source file</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Tue, 13 Oct 2026 01:07:52 +0000</pubDate>
      <link>https://dev.to/alapha888/formatting-markdown-for-wechat-zhihu-and-juejin-from-one-source-file-15o9</link>
      <guid>https://dev.to/alapha888/formatting-markdown-for-wechat-zhihu-and-juejin-from-one-source-file-15o9</guid>
      <description>&lt;p&gt;If you write technical posts in Markdown and publish them in Chinese, you know the last step is the annoying one. The article is done — code blocks, tables, a few formulas — and then you paste it into the WeChat Official Account editor and watch the formatting fall apart: code loses its background, tables collapse into plain text, and images need to be re-uploaded one by one. Fixing it by hand can take longer than a final proofread.&lt;/p&gt;

&lt;p&gt;Zhihu and Juejin accept Markdown more gracefully, but each platform still renders slightly differently, so maintaining three hand-adjusted copies of the same post is its own kind of tax.&lt;/p&gt;

&lt;h2&gt;
  
  
  A one-source workflow
&lt;/h2&gt;

&lt;p&gt;The workflow that avoids most of this is boring on purpose:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep one Markdown file as the only source of truth.&lt;/li&gt;
&lt;li&gt;Render it once with a formatter that targets each platform's paste format, instead of editing copies inside each editor.&lt;/li&gt;
&lt;li&gt;Paste, spot-check the risky elements (see below), and publish. Any correction goes back into the source file, not into one platform's copy.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What a formatter has to preserve
&lt;/h2&gt;

&lt;p&gt;When you evaluate any Markdown-to-platform tool — or build your own conversion step — these are the elements that break first, in roughly this order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code blocks&lt;/strong&gt;, including syntax highlighting and readable backgrounds after paste.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tables&lt;/strong&gt;, which several editors silently flatten.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Math formulas&lt;/strong&gt;, where a renderer that drops TeX leaves raw source in the published post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Images&lt;/strong&gt;, including whether they survive the paste or need a separate upload pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inline styles&lt;/strong&gt; such as bold inside list items and links with non-ASCII URLs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A tool that handles headings and paragraphs but fails on the first two is not saving you time; it is moving the manual work to where you notice it last.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tool I use for this
&lt;/h2&gt;

&lt;p&gt;MD Publisher is a browser-based Markdown formatter built on the open-source doocs/md project. It renders one Markdown document into output formatted for WeChat Official Accounts, Zhihu, and Juejin, and it is available as a free Microsoft Edge extension. An optional Pro version adds one-click packaged export for the three platforms.&lt;/p&gt;

&lt;p&gt;It will not write the article for you, and you should still spot-check code blocks and tables after pasting — platform editors change without notice. But it removes the repetitive reformatting step, which is the part that never deserved an hour of your evening in the first place.&lt;/p&gt;

&lt;p&gt;MD Publisher on Microsoft Edge Add-ons: &lt;a href="https://microsoftedge.microsoft.com/addons/detail/md-%E6%8E%92%E7%89%88%E5%8A%A9%E6%89%8B/ggimifkpgpbnpempalpkmnnlplklgkdi" rel="noopener noreferrer"&gt;https://microsoftedge.microsoft.com/addons/detail/md-%E6%8E%92%E7%89%88%E5%8A%A9%E6%89%8B/ggimifkpgpbnpempalpkmnnlplklgkdi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>markdown</category>
      <category>writing</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Publisher support ends tomorrow: a 30-minute rescue checklist for your .pub archive</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Mon, 12 Oct 2026 08:32:11 +0000</pubDate>
      <link>https://dev.to/alapha888/publisher-support-ends-tomorrow-a-30-minute-rescue-checklist-for-your-pub-archive-32o9</link>
      <guid>https://dev.to/alapha888/publisher-support-ends-tomorrow-a-30-minute-rescue-checklist-for-your-pub-archive-32o9</guid>
      <description>&lt;p&gt;Microsoft removed Publisher from Microsoft 365 on October 1, 2026. Tomorrow, October 13, 2026, support for perpetual Publisher (Office 2021) ends.&lt;/p&gt;

&lt;p&gt;Your installed copy will not vanish overnight, and your &lt;code&gt;.pub&lt;/code&gt; files will not be deleted. The app simply stops receiving security updates. However, almost no modern software outside of Microsoft Office opens &lt;code&gt;.pub&lt;/code&gt; files natively. If you leave your archive as-is, you risk discovering years from now that your legacy templates, newsletters, or flyers are effectively locked away.&lt;/p&gt;

&lt;p&gt;Here is a practical, 30-minute checklist to rescue your &lt;code&gt;.pub&lt;/code&gt; archive before support lapses.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 1: Inventory your &lt;code&gt;.pub&lt;/code&gt; files (5 minutes)
&lt;/h3&gt;

&lt;p&gt;Search your local drives, shared network folders, and cloud sync directories for every file ending in &lt;code&gt;.pub&lt;/code&gt;. Gather them into a single working folder (or note their paths) so you know the exact scope of what needs preservation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Set up a local converter (5 minutes)
&lt;/h3&gt;

&lt;p&gt;You do not need to upload confidential files to random web converters. LibreOffice contains &lt;code&gt;libmspub&lt;/code&gt;, an open-source library that parses Publisher files and converts them locally to PDF. Install LibreOffice if you do not already have it on your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Run a local batch conversion to PDF (10 minutes)
&lt;/h3&gt;

&lt;p&gt;Export your &lt;code&gt;.pub&lt;/code&gt; files to standard PDF format. PDF ensures that fonts, layouts, and vector artwork remain viewable on any modern operating system indefinitely. Run your conversions locally so your documents never leave your machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Watch out for silent conversion failures (5 minutes)
&lt;/h3&gt;

&lt;p&gt;Do not assume a batch script succeeded just because it finished without errors. Automated converters can exit with status code &lt;code&gt;0&lt;/code&gt; while producing no PDF at all (a behavior verified with truncated files). Even worse, a renamed plain text file can pass through and fake-convert into an empty or corrupt shell.&lt;/p&gt;

&lt;p&gt;Always verify output:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confirm that an output PDF actually exists on disk.&lt;/li&gt;
&lt;li&gt;Check that file size is non-zero.&lt;/li&gt;
&lt;li&gt;Ensure the converted file contains actual rendered text or visual elements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 5: Review the conversion status (5 minutes)
&lt;/h3&gt;

&lt;p&gt;A reliable migration uses a verification report that classifies every source file into one of three buckets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OK&lt;/strong&gt;: The PDF exists, contains expected text content, and converted cleanly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REVIEW&lt;/strong&gt;: The conversion completed, but the output contains unusually little text (for example, image-heavy posters or scanned assets) and requires manual visual inspection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAILED&lt;/strong&gt;: The process produced no PDF or threw an unhandled error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inspect the items flagged for &lt;strong&gt;REVIEW&lt;/strong&gt; and &lt;strong&gt;FAILED&lt;/strong&gt; while you still have access to a working desktop environment.&lt;/p&gt;




&lt;h3&gt;
  
  
  The silent-failure trap
&lt;/h3&gt;

&lt;p&gt;Blindly looping &lt;code&gt;libreoffice --headless --convert-to pdf&lt;/code&gt; in a shell script feels fast, but silent failures will burn you. Because &lt;code&gt;libmspub&lt;/code&gt; parsers may exit cleanly even when encountering truncated headers or malformed streams, checking process exit codes alone is not enough. You need automated post-conversion checks on file size and extracted content to ensure your archive was genuinely preserved rather than silently skipped.&lt;/p&gt;




&lt;p&gt;If you want an automated tool that handles the batch run and validation in one step, check out &lt;a href="https://github.com/alapha888/pubaudit" rel="noopener noreferrer"&gt;PubAudit&lt;/a&gt;. It is a free, MIT-licensed CLI that batch-converts a folder locally, classifies every file as OK / REVIEW / FAILED, and generates CSV and HTML reports. Your files are never uploaded anywhere.&lt;/p&gt;

&lt;p&gt;Take thirty minutes today to turn your &lt;code&gt;.pub&lt;/code&gt; archives into readable PDFs while you still have the tools to verify them.&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>ubuntu-latest moves to Ubuntu 26.04 on October 19 — 22 toolset differences that can break your CI</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Fri, 09 Oct 2026 23:51:16 +0000</pubDate>
      <link>https://dev.to/alapha888/ubuntu-latest-moves-to-ubuntu-2604-on-october-19-22-toolset-differences-that-can-break-your-ci-4fch</link>
      <guid>https://dev.to/alapha888/ubuntu-latest-moves-to-ubuntu-2604-on-october-19-22-toolset-differences-that-can-break-your-ci-4fch</guid>
      <description>&lt;p&gt;Between &lt;strong&gt;October 19 and November 19, 2026&lt;/strong&gt;, GitHub moves the &lt;code&gt;ubuntu-latest&lt;/code&gt; runner label from Ubuntu 24.04 to Ubuntu 26.04. Nothing in your repository changes — the machine underneath your CI does.&lt;/p&gt;

&lt;p&gt;I diffed the official &lt;code&gt;actions/runner-images&lt;/code&gt; toolsets (&lt;code&gt;toolset-2404.json&lt;/code&gt; vs &lt;code&gt;toolset-2604.json&lt;/code&gt;) on 2026-10-10 and found &lt;strong&gt;22 differences&lt;/strong&gt;. These are the ones most likely to break or silently change a build:&lt;/p&gt;

&lt;h2&gt;
  
  
  Removed outright
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;mercurial (&lt;code&gt;hg&lt;/code&gt;)&lt;/strong&gt;, &lt;code&gt;mediainfo&lt;/code&gt;, &lt;code&gt;sphinxsearch&lt;/code&gt;, &lt;code&gt;haveged&lt;/code&gt; — removed from the image&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Globally preinstalled Node tools&lt;/strong&gt;: only &lt;code&gt;n&lt;/code&gt; and &lt;code&gt;yarn&lt;/code&gt; remain. &lt;code&gt;webpack&lt;/code&gt;, &lt;code&gt;gulp&lt;/code&gt;, &lt;code&gt;grunt&lt;/code&gt;, &lt;code&gt;parcel&lt;/code&gt;, &lt;code&gt;lerna&lt;/code&gt;, &lt;code&gt;newman&lt;/code&gt;, and &lt;code&gt;tsc&lt;/code&gt; (typescript) are no longer preinstalled globally — a workflow that calls them without a local install or &lt;code&gt;npx&lt;/code&gt; step will fail&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Java 8&lt;/strong&gt; — removed; &lt;code&gt;gcc-12&lt;/code&gt; / &lt;code&gt;gfortran-12&lt;/code&gt; and &lt;code&gt;clang-16&lt;/code&gt; / &lt;code&gt;clang-17&lt;/code&gt; — removed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p7zip&lt;/code&gt; is renamed to &lt;code&gt;7zip&lt;/code&gt;; the &lt;code&gt;fastlane&lt;/code&gt; gem is no longer bundled with rubygems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Default versions that move under you
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;24.04&lt;/th&gt;
&lt;th&gt;26.04&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Java (default)&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node (default)&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;8.3&lt;/td&gt;
&lt;td&gt;8.5 only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clang (default)&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go (default)&lt;/td&gt;
&lt;td&gt;1.24&lt;/td&gt;
&lt;td&gt;1.26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker / Compose&lt;/td&gt;
&lt;td&gt;28 / 2.38&lt;/td&gt;
&lt;td&gt;29.4.2 / 5.1.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CMake&lt;/td&gt;
&lt;td&gt;pinned at 3.31.6&lt;/td&gt;
&lt;td&gt;latest&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The CMake row deserves attention: on 24.04 it was deliberately held at 3.31.6 to avoid CMake 4.0 compatibility issues. On 26.04 it tracks latest, so CMake 4 behaviour may apply to projects that never opted in.&lt;/p&gt;

&lt;p&gt;None of this matters if you pin a runner (&lt;code&gt;ubuntu-24.04&lt;/code&gt;) and pin your tool versions with setup actions. It matters a lot if you use &lt;code&gt;ubuntu-latest&lt;/code&gt; and rely on whatever happens to be installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  A 30-second check
&lt;/h2&gt;

&lt;p&gt;I packaged the toolset diff as a small open-source scanner, &lt;strong&gt;runner-drift-audit&lt;/strong&gt; (MIT, single-file Python, standard library only, no dependencies):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alapha888/runner-drift-audit" rel="noopener noreferrer"&gt;https://github.com/alapha888/runner-drift-audit&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 runner_drift_audit.py /path/to/repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It scans workflow files line by line and reports floating runner labels, invocations of removed tools, default-version drift where no setup action pins the version, and actions referenced by mutable tag instead of a full SHA. Exit code is 1 when any HIGH finding exists, so it can gate a CI job.&lt;/p&gt;

&lt;p&gt;Tested behaviour, from the sample workflows bundled in the repo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A workflow using &lt;code&gt;ubuntu-latest&lt;/code&gt;, calling &lt;code&gt;java&lt;/code&gt;, &lt;code&gt;hg&lt;/code&gt;, and a global &lt;code&gt;webpack&lt;/code&gt;, and invoking &lt;code&gt;cmake&lt;/code&gt; reports &lt;strong&gt;3 HIGH&lt;/strong&gt; (floating label, mercurial removed, webpack no longer preinstalled) and &lt;strong&gt;3 WARN&lt;/strong&gt; (unpinned &lt;code&gt;actions/checkout@v4&lt;/code&gt;, Java default drift 17→25, CMake unpinned).&lt;/li&gt;
&lt;li&gt;A workflow pinned to &lt;code&gt;ubuntu-24.04&lt;/code&gt;, with &lt;code&gt;actions/checkout&lt;/code&gt; pinned by full SHA and Java pinned via &lt;code&gt;actions/setup-java&lt;/code&gt;, reports &lt;strong&gt;0 HIGH&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;This is a line scanner with shell-aware heuristics (quotes, &lt;code&gt;sudo&lt;/code&gt;/&lt;code&gt;env&lt;/code&gt;/&lt;code&gt;VAR=val&lt;/code&gt; prefixes, multi-line &lt;code&gt;run:&lt;/code&gt; blocks), not a full YAML/shell parser. Treat findings as a review checklist, not a proof. It does not execute anything and does not phone home.&lt;/p&gt;

&lt;p&gt;If your CI is green today on &lt;code&gt;ubuntu-latest&lt;/code&gt;, the cheapest time to find out which of the 22 differences hits you is before October 19 — while you can still pin deliberately instead of debugging a runner you did not choose.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>githubactions</category>
      <category>ci</category>
      <category>devops</category>
    </item>
    <item>
      <title>Microsoft Publisher is gone from Microsoft 365 — batch conversion isn't the hard part, verification is</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Fri, 09 Oct 2026 20:54:04 +0000</pubDate>
      <link>https://dev.to/alapha888/microsoft-publisher-is-gone-from-microsoft-365-batch-conversion-isnt-the-hard-part-verification-5d00</link>
      <guid>https://dev.to/alapha888/microsoft-publisher-is-gone-from-microsoft-365-batch-conversion-isnt-the-hard-part-verification-5d00</guid>
      <description>&lt;p&gt;On October 1, 2026, Microsoft removed Publisher from Microsoft 365. Support for the perpetual version ends October 13, 2026.&lt;/p&gt;

&lt;p&gt;That leaves a lot of &lt;code&gt;.pub&lt;/code&gt; files behind — especially outside large companies. For roughly thirty years, Publisher was the default desktop-publishing tool for schools, churches, clubs, and small offices: newsletters, certificates, flyers, directories. Those archives do not disappear just because the application did.&lt;/p&gt;

&lt;p&gt;The standard advice is to convert everything to PDF. That part is genuinely easy. The hard part is knowing which conversions silently failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The silent failure problem
&lt;/h2&gt;

&lt;p&gt;A typical batch script looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;file &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.pub&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;soffice &lt;span class="nt"&gt;--headless&lt;/span&gt; &lt;span class="nt"&gt;--convert-to&lt;/span&gt; pdf &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Converted: &lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The flaw is the exit code. An exit code of &lt;code&gt;0&lt;/code&gt; does not guarantee a PDF exists.&lt;/p&gt;

&lt;p&gt;I ran into two concrete cases while testing with real Publisher files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Exit 0, no output.&lt;/strong&gt; A truncated &lt;code&gt;.pub&lt;/code&gt; file made the converter exit with code 0 — and produce no PDF at all. A script that trusts the exit code logs a success for a document that is simply gone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The fake &lt;code&gt;.pub&lt;/code&gt;.&lt;/strong&gt; A plain text file renamed to &lt;code&gt;.pub&lt;/code&gt; will happily "convert" as a text document in some pipelines. The output exists, the exit code is 0, and the PDF contains none of the original layout — because there never was one. The check that catches this is the OLE2 header: a real Publisher file has one; a renamed text file does not.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is a quieter third case: a PDF is produced, but its text did not survive conversion. That file looks fine in a file listing and is useless as an archive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why local matters here
&lt;/h2&gt;

&lt;p&gt;The obvious alternative — uploading files to an online converter — is a poor fit for exactly the archives Publisher leaves behind. School and church files can contain directories, rosters, and contact details accumulated over decades. Converting locally keeps those files on your own machine, and most online converters process one file at a time anyway, which is not workable for a folder of hundreds.&lt;/p&gt;

&lt;h2&gt;
  
  
  A verification pass: OK / REVIEW / FAILED
&lt;/h2&gt;

&lt;p&gt;What a batch migration actually needs is a report, not just a pile of PDFs. The approach I settled on classifies every file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OK&lt;/strong&gt; — PDF produced, has pages, and contains extractable text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REVIEW&lt;/strong&gt; — PDF produced, but little or no extractable text. Check it visually before deleting the original &lt;code&gt;.pub&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAILED&lt;/strong&gt; — No usable PDF: silent failure, corrupted file, or not a real Publisher file in the first place.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One honest limit: this verifies that a PDF exists, has pages, and carries text. It cannot prove the layout &lt;em&gt;looks&lt;/em&gt; right. Conversion quality is whatever the underlying converter (in this case LibreOffice's libmspub) produces, and complex multi-column layouts are known to convert imperfectly — which is precisely why the REVIEW category exists instead of a binary pass/fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tool
&lt;/h2&gt;

&lt;p&gt;I packaged this as a small open-source CLI, &lt;strong&gt;PubAudit&lt;/strong&gt; (MIT, Python standard library only, uses LibreOffice + poppler-utils):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alapha888/pubaudit" rel="noopener noreferrer"&gt;https://github.com/alapha888/pubaudit&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 pubaudit.py /path/to/folder
&lt;span class="c"&gt;# PDFs + pubaudit-report.csv / pubaudit-report.html land in&lt;/span&gt;
&lt;span class="c"&gt;# /path/to/folder/pubaudit-output/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tested behaviour, from a run over five real Publisher flyers, one renamed text file, and one truncated file: the five real files came back OK with page counts and extracted text; both bad files came back FAILED — including the truncated one whose converter had exited 0.&lt;/p&gt;

&lt;p&gt;If you are sitting on a folder of &lt;code&gt;.pub&lt;/code&gt; files before the October 13 support deadline, converting them is the easy part. Verify the outputs before you delete anything.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>python</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A 5-Axis Code Review Checklist for AI Coding Agents</title>
      <dc:creator>alapha888</dc:creator>
      <pubDate>Thu, 08 Oct 2026 14:49:58 +0000</pubDate>
      <link>https://dev.to/alapha888/a-5-axis-code-review-checklist-for-ai-coding-agents-7ch</link>
      <guid>https://dev.to/alapha888/a-5-axis-code-review-checklist-for-ai-coding-agents-7ch</guid>
      <description>&lt;p&gt;AI coding agents write fluent, syntactically clean code that compiles on the first attempt. That fluency is precisely why reviewing it is tricky: humans tend to equate smooth phrasing with correctness. In practice, agent-generated code fails in remarkably predictable patterns. It skips edge cases, hallucinates parameters on older SDKs, introduces subtle N+1 queries, and writes tautological tests that pass without actually verifying anything.&lt;/p&gt;

&lt;p&gt;Reviewing agent output with vague impressions or casual skimming does not work. You need a fixed, repeatable checklist that targets the specific blind spots agents exhibit most often.&lt;/p&gt;

&lt;p&gt;Here are eight checks across five critical axes, along with the concrete prompt to fix each one.&lt;/p&gt;




&lt;h3&gt;
  
  
  Axis 1: Correctness
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Empty Collections and Boundary Handling
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mistake:&lt;/strong&gt; Agents default to the happy path. When iterating, slicing, or computing aggregate values, they rarely account for empty arrays, &lt;code&gt;null&lt;/code&gt; payloads, or single-element collections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correction Prompt:&lt;/strong&gt; &lt;em&gt;"Refactor &lt;code&gt;calculateInvoiceTotals&lt;/code&gt; to handle empty arrays, null line items, and negative quantities without throwing."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Plausible but Nonexistent API Signatures
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mistake:&lt;/strong&gt; Agents frequently invent convenience methods or pass modern flags into older library versions that your project actually pins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correction Prompt:&lt;/strong&gt; &lt;em&gt;"Verify whether &lt;code&gt;client.fetchWithRetry()&lt;/code&gt; exists in our pinned SDK version; if not, rewrite it using standard &lt;code&gt;fetch()&lt;/code&gt; and our internal retry utility."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Axis 2: Security
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3. String-Interpolated Queries and Commands
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mistake:&lt;/strong&gt; When combining dynamic filters or calling system utilities, agents often revert to string template literals instead of parameterized queries or argument arrays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correction Prompt:&lt;/strong&gt; &lt;em&gt;"Convert the string interpolation in &lt;code&gt;getUserRecords&lt;/code&gt; into parameterized SQL using indexed positional placeholders."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Permissive Defaults and Fallback Credentials
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mistake:&lt;/strong&gt; To ensure sample code works immediately, agents often insert placeholder fallback secrets (&lt;code&gt;process.env.KEY || 'default_secret'&lt;/code&gt;) or default permissions to &lt;code&gt;0777&lt;/code&gt; or wildcard CORS headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correction Prompt:&lt;/strong&gt; &lt;em&gt;"Remove all hardcoded fallback secrets in &lt;code&gt;authConfig&lt;/code&gt;; fail fast at startup if required environment variables are unset."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Axis 3: Readability &amp;amp; Architecture
&lt;/h3&gt;

&lt;h4&gt;
  
  
  5. Premature Abstraction Sprawl
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mistake:&lt;/strong&gt; Given a straightforward requirement, an agent will often generate unnecessary interfaces, factory classes, and strategy wrappers for what should be a ten-line pure function.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correction Prompt:&lt;/strong&gt; &lt;em&gt;"Inline &lt;code&gt;DataTransformerFactory&lt;/code&gt; and replace the strategy classes with a single pure mapping function in &lt;code&gt;transformers.ts&lt;/code&gt;."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Axis 4: Performance
&lt;/h3&gt;

&lt;h4&gt;
  
  
  6. Hidden N+1 Queries and Unbounded In-Memory Filtering
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mistake:&lt;/strong&gt; Agents routinely execute database calls or network requests inside loops, or pull an entire database table into memory only to filter it with &lt;code&gt;.filter()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correction Prompt:&lt;/strong&gt; &lt;em&gt;"Move the query outside the &lt;code&gt;for&lt;/code&gt; loop in &lt;code&gt;syncProfiles&lt;/code&gt; and batch it into a single &lt;code&gt;WHERE id IN (...)&lt;/code&gt; operation."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Axis 5: Test Quality
&lt;/h3&gt;

&lt;h4&gt;
  
  
  7. Assertions That Verify Nothing
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mistake:&lt;/strong&gt; Agents optimize for getting tests to pass. They frequently write tests that only verify an HTTP 200 status code, without checking response bodies, updated database state, or emitted events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correction Prompt:&lt;/strong&gt; &lt;em&gt;"Update &lt;code&gt;testUpdateUser&lt;/code&gt; to assert the updated database row values and response payload fields, not just the HTTP status code."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  8. Mocking the System Under Test
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Mistake:&lt;/strong&gt; To avoid complex setup, agents sometimes mock the internal business logic of the exact function they are supposed to be testing, creating an entirely circular pass.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correction Prompt:&lt;/strong&gt; &lt;em&gt;"Remove the mocks on &lt;code&gt;calculateTaxRate&lt;/code&gt; within its own test suite and verify the actual calculation logic against fixed test fixtures."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  The Output Protocol
&lt;/h3&gt;

&lt;p&gt;When using an agent to review code—or when formatting your own review comments—enforce a strict output rule:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Findings First:&lt;/strong&gt; Order every finding strictly by severity (Critical, Major, Minor). Do not bury blockers under complimentary opening remarks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anchor to Source:&lt;/strong&gt; Every comment must include an exact file path and line reference (&lt;code&gt;path/to/file.ts#L42-L48&lt;/code&gt;). If you cannot point to the line, do not file the comment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Invented Problems or Style Nitpicks:&lt;/strong&gt; Prohibit speculative feedback and leave formatting to automated linters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cap Diff Size:&lt;/strong&gt; If an agent submits a diff exceeding 400 lines, reject it immediately and require the agent to split the work into smaller, isolated PRs before reviewing.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;The complete checklist prompts and operational review skills are open-source and free to read on GitHub at &lt;a href="https://github.com/alapha888/agent-skills-en" rel="noopener noreferrer"&gt;https://github.com/alapha888/agent-skills-en&lt;/a&gt; . If you prefer a condensed, printable reference for your desk or tablet, a PDF and PNG bundle containing this code-review checklist alongside a conventional git commit cheat sheet is available on Gumroad at &lt;a href="https://alapha888.gumroad.com/l/zjayxe" rel="noopener noreferrer"&gt;https://alapha888.gumroad.com/l/zjayxe&lt;/a&gt; for $19. It contains the same material formatted for quick visual reference while reviewing pull requests.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>ai</category>
      <category>codereview</category>
    </item>
  </channel>
</rss>
