<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Python on tsvinc</title>
		<link>https://tsvinc.dev/tags/python/</link>
		<description>Recent content in Python on tsvinc</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
		
			<lastBuildDate>Mon, 26 Oct 2026 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://tsvinc.dev/tags/python/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>One space in a path, and Hermes blocked echo hi</title>
				<link>https://tsvinc.dev/posts/space-in-hermes-home/</link>
				<pubDate>Mon, 26 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/space-in-hermes-home/</guid>
				<description>&lt;p&gt;&lt;em&gt;Builds on &lt;a href=&#34;https://tsvinc.dev/posts/guard-missed-bash-lc/&#34;&gt;My guard blocked bash -c. Models write bash -lc.&lt;/a&gt;, which explains the guard that Hermes runs as a hook here.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;echo hi&lt;/code&gt; was blocked. So was every other terminal command and every file read and write Hermes Agent tried. The guard in my agent-config templates is supposed to stop destructive commands, and on this install it stopped everything, which is one way to be secure.&lt;/p&gt;&#xA;&lt;p&gt;Hermes runs my guard as a &lt;code&gt;pre_tool_call&lt;/code&gt; shell hook, with &lt;code&gt;fail_closed: true&lt;/code&gt;. That setting is deliberate: if the guard can&#39;t give a verdict, the tool call doesn&#39;t run. A guard that fails open is a guard that an unlucky crash switches off. The cause was the install&#39;s &lt;code&gt;HERMES_HOME&lt;/code&gt;, the directory Hermes keeps its config and hooks in: it had a space in its name.&lt;/p&gt;</description>
			</item>
			<item>
				<title>A text search OOM-killed the whole tmux pane</title>
				<link>https://tsvinc.dev/posts/text-search-oom-killed-the-pane/</link>
				<pubDate>Sat, 24 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/text-search-oom-killed-the-pane/</guid>
				<description>&lt;p&gt;22:57:55: eight lines of Python start searching a scratch directory for one log line.&lt;/p&gt;&#xA;&lt;p&gt;23:01:49: the kernel kills them. They hold 15.3 GiB of RAM and another 1.4 GiB of swap.&lt;/p&gt;&#xA;&lt;p&gt;By 23:01:51, systemd has stopped everything else in that tmux pane: the interactive session, a context probe nearly four minutes into a 262k-token request, a &lt;code&gt;go test -count=100&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;All of it to find one log line.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-search-and-what-it-walked-into&#34;&gt;The search, and what it walked into&lt;a class=&#34;heading-anchor&#34; href=&#34;#the-search-and-what-it-walked-into&#34; aria-label=&#34;Link to section: The search, and what it walked into&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fs&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;walk&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;agent-work&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;review-cutting&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;root&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;client-research&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;root&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;errors&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;replace&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;splitlines&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;host a9: engine&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;up after&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;l&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;200&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It was checking a single fact for a blog post: which log lines said when a GPU box&#39;s engine had come up. The command eight seconds before it had filtered by extension, &lt;code&gt;.log .txt .out .err&lt;/code&gt;. This one didn&#39;t. It walked the whole scratch tree, which held, among the logs, a 2.7 GB GGUF model downloaded that evening for another job.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The power went out twice. My UPS log saw it once.</title>
				<link>https://tsvinc.dev/posts/bluetti-ac180-ups-over-bluetooth/</link>
				<pubDate>Wed, 14 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/bluetti-ac180-ups-over-bluetooth/</guid>
				<description>&lt;p&gt;Thirty lines of log, one outage. Twenty-two lines on grid, seven on battery, one back on grid. Clean, readable, and short by one event: the plug came out of the wall twice.&lt;/p&gt;&#xA;&lt;p&gt;The setup itself works. A BLUETTI AC180 portable power station sits between the wall and my workstation as a UPS. Linux reads it over Bluetooth LE, through an encrypted link, with no account and no pairing, in about nine seconds per read. What it can&#39;t do is tell you about anything that happens between two of those reads. Neither can anything else built on polling. This one put it in writing.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
