<?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: Mohsen Seyedkazemi Ardebili</title>
    <description>The latest articles on DEV Community by Mohsen Seyedkazemi Ardebili (@mskazemi).</description>
    <link>https://dev.to/mskazemi</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%2F3997511%2Ff85584b3-05ee-47b7-b358-34484bbd147a.png</url>
      <title>DEV Community: Mohsen Seyedkazemi Ardebili</title>
      <link>https://dev.to/mskazemi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mskazemi"/>
    <language>en</language>
    <item>
      <title>Our linter's "safe" autofix would have silently disabled RBAC</title>
      <dc:creator>Mohsen Seyedkazemi Ardebili</dc:creator>
      <pubDate>Sun, 20 Sep 2026 21:54:58 +0000</pubDate>
      <link>https://dev.to/mskazemi/our-linters-safe-autofix-would-have-silently-disabled-rbac-log</link>
      <guid>https://dev.to/mskazemi/our-linters-safe-autofix-would-have-silently-disabled-rbac-log</guid>
      <description>&lt;p&gt;KubeIntellect is an AI agent that runs &lt;code&gt;kubectl&lt;/code&gt; against a live cluster, so its tools carry a role check and a human-approval gate. Both depend on one thing: the tool actually receiving the run config the graph injects. This is the parameter that receives it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RunnableConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InjectedToolArg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# type: ignore[assignment]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That line is wrong in every way a reviewer is trained to notice. The default is &lt;code&gt;None&lt;/code&gt;, but the annotation does not say &lt;code&gt;| None&lt;/code&gt;. mypy complains, which is why there is a &lt;code&gt;type: ignore&lt;/code&gt; sitting on it. Ruff wants to rewrite the &lt;code&gt;Optional[...]&lt;/code&gt; spelling of it. Every instinct says clean this up.&lt;/p&gt;

&lt;p&gt;Cleaning it up disables role-based access control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the annotation is load-bearing
&lt;/h2&gt;

&lt;p&gt;LangChain finds the parameter to inject by walking the type hints and comparing with &lt;code&gt;is&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;type_hints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;type_&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;RunnableConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is an identity comparison against one exact class object. &lt;code&gt;RunnableConfig | None&lt;/code&gt; is a &lt;code&gt;UnionType&lt;/code&gt;, not that object. It does not match, so no parameter is selected, so nothing is injected.&lt;/p&gt;

&lt;p&gt;Three functions, run against langchain-core 1.6.2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RunnableConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InjectedToolArg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;widened&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RunnableConfig&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;InjectedToolArg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;optional_form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;RunnableConfig&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;InjectedToolArg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bare           -&amp;gt; injected param: 'config'
widened        -&amp;gt; injected param: None
optional_form  -&amp;gt; injected param: None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No error. No warning. The tool still runs. It just receives &lt;code&gt;config=None&lt;/code&gt; forever.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is actually lost
&lt;/h2&gt;

&lt;p&gt;The caller's role comes off that config, and the fallback is the problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user_role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;user_role&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configurable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the config gone, &lt;code&gt;config&lt;/code&gt; is falsy and every call executes as &lt;code&gt;admin&lt;/code&gt;. A &lt;code&gt;readonly&lt;/code&gt; API key stops being read-only. The check that returns &lt;code&gt;[Permission Denied] Your API key has read-only access&lt;/code&gt; is still there, still covered by its unit tests, still passing — and it never fires, because the role it compares against is no longer the caller's role.&lt;/p&gt;

&lt;p&gt;To be precise about the other half, since overstating this would be easy: the human-approval gate does not break the same way. &lt;code&gt;hitl_bypass&lt;/code&gt; also comes off the config and defaults to &lt;code&gt;False&lt;/code&gt;, so losing the config makes the tool prompt for approval &lt;em&gt;more&lt;/em&gt; often, not less. The RBAC default is the one that fails open.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that makes it a trap rather than a bug
&lt;/h2&gt;

&lt;p&gt;Nobody has to be careless to introduce this. The tooling volunteers it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ruff check &lt;span class="nt"&gt;--select&lt;/span&gt; UP045 probe.py
&lt;span class="go"&gt;UP045 [*] Use `X | None` for type annotations
&lt;/span&gt;&lt;span class="gp"&gt; --&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;probe.py:5:35
&lt;span class="go"&gt;help: Convert to `X | None`
[*] 1 fixable with the `--fix` option.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;[*]&lt;/code&gt; means ruff classifies that rewrite as a &lt;strong&gt;safe&lt;/strong&gt; fix. Not &lt;code&gt;--unsafe-fixes&lt;/code&gt;. Plain &lt;code&gt;ruff check --fix&lt;/code&gt; — the command people run without reading the diff — converts a working authorization boundary into a no-op.&lt;/p&gt;

&lt;p&gt;A behavioral test will not save you either. The tools most likely to get "cleaned up" are the ones that never read &lt;code&gt;config&lt;/code&gt; at all: they pass every test they have while silently receiving &lt;code&gt;None&lt;/code&gt;. We found exactly that shape in four of our own read verbs. Harmless there, because those verbs make no authorization decision — but it is the same defect, one file away from a place where it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we did instead of a comment
&lt;/h2&gt;

&lt;p&gt;There is a comment on the line. Comments do not fail CI.&lt;/p&gt;

&lt;p&gt;The guard is a test that asserts the annotation itself. It scans every &lt;code&gt;config: Annotated[..., InjectedToolArg]&lt;/code&gt; parameter in the source and fails if any is not bare &lt;code&gt;RunnableConfig&lt;/code&gt;. Alongside it are two dynamic canaries that build a real tool with each spelling and assert, against whatever langchain version is actually installed, that the required form &lt;em&gt;is&lt;/em&gt; injected and the forbidden form is &lt;em&gt;not&lt;/em&gt; — so the day the library changes its matching rule, a test says so instead of production.&lt;/p&gt;

&lt;p&gt;There is also a test asserting the scanner finds the known sites, because a regex that matched nothing would make every other assertion in the file vacuously true.&lt;/p&gt;

&lt;h2&gt;
  
  
  The general version
&lt;/h2&gt;

&lt;p&gt;When a framework dispatches on type identity, your annotation is not documentation. It is runtime configuration written in the type language — and anything that "improves" your types can change behavior: a linter, a type checker, an IDE quick-fix, or an agent asked to clean up implicit &lt;code&gt;Optional&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you have a line like that, the fix is not a louder comment. It is a test that fails when someone improves it.&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="https://github.com/MSKazemi/kubeintellect" rel="noopener noreferrer"&gt;https://github.com/MSKazemi/kubeintellect&lt;/a&gt;&lt;br&gt;
The guard: &lt;code&gt;v4/tests/test_injected_config_invariant.py&lt;/code&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>security</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>A 25-verifier panel measured an effective size of 1.00</title>
      <dc:creator>Mohsen Seyedkazemi Ardebili</dc:creator>
      <pubDate>Sun, 20 Sep 2026 21:48:15 +0000</pubDate>
      <link>https://dev.to/mskazemi/a-25-verifier-panel-measured-an-effective-size-of-100-lgg</link>
      <guid>https://dev.to/mskazemi/a-25-verifier-panel-measured-an-effective-size-of-100-lgg</guid>
      <description>&lt;p&gt;Generation got cheap. Trustworthy review did not.&lt;/p&gt;

&lt;p&gt;So we add reviewers. More eyes on the PR, more verifiers in the gate, a panel of LLM judges instead of one. The assumption underneath is that each additional reviewer adds independent evidence.&lt;/p&gt;

&lt;p&gt;That assumption is measurable. I measured it, and it did not hold.&lt;/p&gt;

&lt;h2&gt;
  
  
  What IDKMesh is
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/MSKazemi/idkmesh" rel="noopener noreferrer"&gt;IDKMesh&lt;/a&gt; is an open-source research project (Apache-2.0, Python 3.11+) asking how humans, AI agents, tools, and heterogeneous compute can coordinate on uncertain goals and turn proposals into &lt;em&gt;verified useful work&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It is a research preview, not production software, and the repository is deliberately conservative about what it claims: every number below traces to a committed experiment record you can re-run.&lt;/p&gt;

&lt;p&gt;The thesis in one line: &lt;strong&gt;reviewer count is not independent evidence count.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The coordination model treats generation as cheap and verification as the scarce resource:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Work arrives as a &lt;strong&gt;bounded Work Unit&lt;/strong&gt; that must declare its security bounds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replaceable workers&lt;/strong&gt; attempt it. Multiple attempts are expected; candidates are disposable.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;separate, verifier-owned evaluation plan&lt;/strong&gt; judges those candidates. Worker completion is not acceptance.&lt;/li&gt;
&lt;li&gt;Results become &lt;strong&gt;reproducible evidence&lt;/strong&gt; - result manifests, verification results, provenance digests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration is an explicit decision&lt;/strong&gt; gated on that evidence, not on a green impression.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bundled demo makes the boundary concrete: it runs the real validators against committed fixtures and &lt;em&gt;deliberately rejects&lt;/em&gt; four invalid ones - including a task with no security contract, and a worker result that accepts itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring a gate
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;idkmesh gate-audit&lt;/code&gt; takes verdicts you have already collected and reports what the panel is actually worth. Here is the bundled example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gate-audit-report-v0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"gate_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example-five-verifier-gate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"evidence_class"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"synthetic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"inputs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"candidates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"verifiers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"known_good"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"known_bad"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"panel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nominal_votes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mean_verifier_accuracy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mean_pairwise_error_correlation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0916&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"effective_votes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.6944&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"heuristic_n_eff"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.6588&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"probes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"breached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"breach_rate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.667&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"warnings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"2/3 seeded known-bad probes were accepted by the panel"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the third key before the interesting one: &lt;code&gt;"evidence_class": "synthetic"&lt;/code&gt;. Those five reviewers are invented, and &lt;code&gt;1.69&lt;/code&gt; is a demonstration of the arithmetic, not a measurement of anything real. The project keeps a hard line between synthetic demonstration and observed evidence - so here is the observed side.&lt;/p&gt;

&lt;h2&gt;
  
  
  The observed result
&lt;/h2&gt;

&lt;p&gt;Experiment E017 built a panel where every verifier is a &lt;strong&gt;program&lt;/strong&gt;, not a model: a &lt;em&gt;partial test oracle&lt;/em&gt; that draws inputs from one named region of a problem's input domain (&lt;code&gt;tiny&lt;/code&gt;, &lt;code&gt;small&lt;/code&gt;, &lt;code&gt;large&lt;/code&gt;, &lt;code&gt;extreme&lt;/code&gt;, &lt;code&gt;duplicate&lt;/code&gt;) and accepts a candidate only if it matches a reference implementation on all of them.&lt;/p&gt;

&lt;p&gt;5 regions x 5 seeds = &lt;strong&gt;25 verifiers&lt;/strong&gt;, run over a 72-candidate corpus whose ground truth comes from executing hidden tests. Every verifier's Youden &lt;em&gt;J&lt;/em&gt; is significantly positive after Bonferroni correction - mean accuracy &lt;code&gt;0.7956&lt;/code&gt;. So the panel genuinely works, individually.&lt;/p&gt;

&lt;p&gt;Error correlation between them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;same region (declared dependent)     mean rho = +0.8924
diff region (declared independent)   mean rho = +0.5263
all pairs                            mean rho = +0.5873
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verifiers that share &lt;em&gt;no declared attribute&lt;/em&gt; still share 53% of their errors. A metadata group boundary is not an independence boundary.&lt;/p&gt;

&lt;p&gt;Then the part that matters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;25-verifier majority error : 0.2083
single verifier            : 0.2044
measured effective size    : 1.00  (of 25 nominal)
N/(1+(N-1)rho) heuristic   : 1.66
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The panel was worth no more than one of its members. Twenty-five nominal votes, an effective size of 1.00, and the standard correlation correction still overstated it by 1.66x.&lt;/p&gt;

&lt;p&gt;The whole measurement ran in about 5 seconds on one laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the usual correction doesn't rescue this
&lt;/h2&gt;

&lt;p&gt;The familiar fix is to discount for correlation with &lt;code&gt;N_eff = N/(1+(N-1)rho)&lt;/code&gt;. Experiment E015 tested that heuristic across a parameter grid and found it exact at &lt;code&gt;rho=0&lt;/code&gt; and &lt;code&gt;rho=1&lt;/code&gt;, wrong in between, and - importantly - &lt;strong&gt;the sign of its error is not fixed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is conservative where verifiers are weak, which is where conservatism is cheap. It is &lt;em&gt;optimistic&lt;/em&gt; where verifiers are accurate and share modest dependence, which is exactly the regime you care about. At &lt;code&gt;p=0.90, rho=0.125&lt;/code&gt; the measured effective size saturates at 4.60 against a heuristic asymptote of 8.00 - and where an independent 9-verifier panel would deliver balanced error &lt;code&gt;0.000891&lt;/code&gt;, the real panel delivers &lt;code&gt;0.0125&lt;/code&gt;. Fourteen times worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not claim
&lt;/h2&gt;

&lt;p&gt;Being precise about scope, because it is easy to over-read:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No AI review panel has been measured in this repository.&lt;/strong&gt; E017's verifiers are programs. Whether LLM reviewers exhibit the same correlation structure is an open question - and the one I most want data on.&lt;/li&gt;
&lt;li&gt;It is a research preview. Not production software.&lt;/li&gt;
&lt;li&gt;It is not on PyPI yet, so installation is from a clone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/MSKazemi/idkmesh &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;idkmesh
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements-phase0.txt
python scripts/demo.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No model account or API key needed.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/MSKazemi/idkmesh" rel="noopener noreferrer"&gt;https://github.com/MSKazemi/idkmesh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have verdict logs from a real review gate - human reviewers, LLM judges, or CI checks - pointing &lt;code&gt;gate-audit&lt;/code&gt; at them is the experiment I would most like to see someone else run. Especially if it disagrees with the above.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>python</category>
      <category>ai</category>
      <category>testing</category>
    </item>
    <item>
      <title>I recorded my Kubernetes AI agent failing, on purpose</title>
      <dc:creator>Mohsen Seyedkazemi Ardebili</dc:creator>
      <pubDate>Sun, 13 Sep 2026 00:22:41 +0000</pubDate>
      <link>https://dev.to/mskazemi/i-recorded-my-kubernetes-ai-agent-failing-on-purpose-1ib2</link>
      <guid>https://dev.to/mskazemi/i-recorded-my-kubernetes-ai-agent-failing-on-purpose-1ib2</guid>
      <description>&lt;p&gt;Most demos of AI-for-infrastructure tools show a clean run. I think that is exactly backwards, and I want to explain why by walking through the thirty seconds of my own demo that a normal product video would have cut.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scene
&lt;/h2&gt;

&lt;p&gt;A deployment is crash-looping. The agent has already diagnosed it. I ask it to restart the deployment.&lt;/p&gt;

&lt;p&gt;It stops and asks for approval. I approve. The restart runs, and the command succeeds.&lt;/p&gt;

&lt;p&gt;Then I ask the follow-up question: did the restart change anything?&lt;/p&gt;

&lt;p&gt;No. The pods fail with the same error. A restart was never going to supply a missing environment variable. The agent re-reads the pods, re-reads the events, and names the same root cause it found at the very beginning: &lt;code&gt;DATABASE_URL&lt;/code&gt; is not set, so the container exits 1.&lt;/p&gt;

&lt;p&gt;The restart was a reasonable thing to try and the wrong thing to fix it, and the system is the one saying so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why that scene is the product
&lt;/h2&gt;

&lt;p&gt;The worst failure for an incident-response tool is not being unhelpful. It is emitting something that &lt;em&gt;looks&lt;/em&gt; like a real diagnosis and is not. At 3am a confident wrong answer costs more than no answer, because it sends a tired human down a wrong path with false authority.&lt;/p&gt;

&lt;p&gt;So the design follows from that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The approval gate is at the tool boundary, not in the prompt.&lt;/strong&gt; A guardrail written into a system prompt is a suggestion, and models can be argued out of suggestions. Instead every mutating operation passes through one chokepoint that returns exactly three answers: do it, ask a human, or refuse. The model does not get a vote, so there is nothing to talk around.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detectors are compiled predicates, not model calls.&lt;/strong&gt; They are always on, they run on every observation, and they cost zero tokens. The LLM is only invoked once a detector actually fires. Watching your cluster is free; thinking about it is the expensive part, so it happens last.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every decision is appended to a hash-chained log.&lt;/strong&gt; A run can be replayed afterwards instead of remembered. If you are going to let software touch production, "what exactly did it do, and why" has to be answerable after the fact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Roles are real.&lt;/strong&gt; readonly, operator, admin and superadmin, enforced per key.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it reads
&lt;/h2&gt;

&lt;p&gt;kubectl for cluster state, Prometheus for metrics via PromQL, and Loki for logs via LogQL. It answers in plain English and quotes the evidence it actually read, so you can check it rather than trust it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The video
&lt;/h2&gt;

&lt;p&gt;Eight minutes, every terminal scene a verbatim recording against a live cluster. Nothing typed by hand, nothing reconstructed. The approval-gate segment starts at 2:27.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/je-K_w3vgGY" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In your browser, nothing to install: &lt;a href="https://kubeintellect.com/demo" rel="noopener noreferrer"&gt;https://kubeintellect.com/demo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pip install kubeintellect&lt;/code&gt; - AGPL-3.0, self-hosted, bring your own LLM provider&lt;/li&gt;
&lt;li&gt;Code: &lt;a href="https://github.com/MSKazemi/kubeintellect" rel="noopener noreferrer"&gt;https://github.com/MSKazemi/kubeintellect&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The v1 architecture is written up in the Journal of Grid Computing (&lt;a href="https://doi.org/10.1007/s10723-026-09837-6" rel="noopener noreferrer"&gt;https://doi.org/10.1007/s10723-026-09837-6&lt;/a&gt;), with a preprint at &lt;a href="https://arxiv.org/abs/2509.02449" rel="noopener noreferrer"&gt;https://arxiv.org/abs/2509.02449&lt;/a&gt;. The repo is several generations past that now.&lt;/p&gt;

&lt;p&gt;If you run Kubernetes in production, the thing I most want to hear is which failure you would throw at it that I have not handled.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Offline voice dictation on Linux, without the cloud</title>
      <dc:creator>Mohsen Seyedkazemi Ardebili</dc:creator>
      <pubDate>Mon, 22 Jun 2026 19:49:15 +0000</pubDate>
      <link>https://dev.to/mskazemi/offline-voice-dictation-on-linux-without-the-cloud-16jd</link>
      <guid>https://dev.to/mskazemi/offline-voice-dictation-on-linux-without-the-cloud-16jd</guid>
      <description>&lt;h1&gt;
  
  
  Offline voice dictation on Linux, without the cloud
&lt;/h1&gt;

&lt;p&gt;Voice dictation is incredibly useful, but most people only meet it through cloud services: Google, Apple, Microsoft, or commercial tools that send audio away from your machine.&lt;/p&gt;

&lt;p&gt;That is convenient, but it is not always ideal.&lt;/p&gt;

&lt;p&gt;Sometimes you want dictation that works locally. Sometimes you are writing code, notes, private messages, medical text, research ideas, or internal company material. Sometimes you simply do not want every voice input to depend on an internet connection, an API key, or a subscription.&lt;/p&gt;

&lt;p&gt;That is why I built &lt;strong&gt;YazSes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YazSes&lt;/strong&gt; is an open-source, offline voice-dictation tool for Linux. You hold a key, speak, release, and your words are transcribed locally with &lt;code&gt;faster-whisper&lt;/code&gt; and typed into the focused app.&lt;/p&gt;

&lt;p&gt;No cloud.&lt;br&gt;
No API key.&lt;br&gt;
No subscription.&lt;br&gt;
Audio stays on your machine.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/MSKazemi/yazses" rel="noopener noreferrer"&gt;https://github.com/MSKazemi/yazses&lt;/a&gt;&lt;br&gt;
Site: &lt;a href="https://mskazemi.github.io/yazses/" rel="noopener noreferrer"&gt;https://mskazemi.github.io/yazses/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem: most dictation is cloud-first
&lt;/h2&gt;

&lt;p&gt;Voice typing has become common, but the default experience is usually cloud-based.&lt;/p&gt;

&lt;p&gt;For many users, that is fine. For others, it is a problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You may not want private speech sent to a third-party service.&lt;/li&gt;
&lt;li&gt;You may want dictation that keeps working offline.&lt;/li&gt;
&lt;li&gt;You may want a tool that is scriptable, inspectable, and open source.&lt;/li&gt;
&lt;li&gt;You may want voice input for Linux, terminals, editors, and custom workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Linux users especially often have fewer polished dictation options than users on macOS or Windows. And for developers, accessibility users, and privacy-conscious users, “just use the cloud dictation built into something else” is not always enough.&lt;/p&gt;
&lt;h2&gt;
  
  
  What YazSes does
&lt;/h2&gt;

&lt;p&gt;YazSes is designed around a simple workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hold a key.&lt;/li&gt;
&lt;li&gt;Speak.&lt;/li&gt;
&lt;li&gt;Release.&lt;/li&gt;
&lt;li&gt;The text appears in the app you are using.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The transcription runs locally using &lt;code&gt;faster-whisper&lt;/code&gt;. The output is then inserted into the currently focused app, so it can work with editors, terminals, browsers, chat apps, notes, and other everyday tools.&lt;/p&gt;

&lt;p&gt;The goal is not to build a big AI assistant. YazSes is intentionally smaller and more predictable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It is offline dictation plus voice commands. It is not an LLM agent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That distinction matters. YazSes does not browse your files, reason over your project, or take autonomous actions. It listens when you trigger it, transcribes locally, and can map specific spoken commands to specific actions.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install and quick setup
&lt;/h2&gt;

&lt;p&gt;For Python users, the basic install is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
pipx install yazses&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;On Linux, you can also use Snap:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
sudo snap install yazses&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A typical first setup flow is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;br&gt;
yazses doctor&lt;br&gt;
yazses enroll&lt;br&gt;
yazses start&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The idea is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;doctor&lt;/code&gt; checks your system setup.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;enroll&lt;/code&gt; helps configure your voice/input workflow.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;start&lt;/code&gt; runs the dictation daemon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After that, you can hold the trigger key, speak, and release to type into the current app.&lt;/p&gt;
&lt;h2&gt;
  
  
  Voice commands and macros
&lt;/h2&gt;

&lt;p&gt;Plain dictation is useful, but developers and power users often need more than text.&lt;/p&gt;

&lt;p&gt;YazSes also supports voice commands for common editor and terminal workflows. For example, phrases can map to actions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“undo that”&lt;/li&gt;
&lt;li&gt;“save file”&lt;/li&gt;
&lt;li&gt;“go to line 42”&lt;/li&gt;
&lt;li&gt;“run the tests”&lt;/li&gt;
&lt;li&gt;“rename this to user_id”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is useful because voice input is not only about writing paragraphs. Sometimes you want to control repetitive editing actions without leaving your flow.&lt;/p&gt;

&lt;p&gt;YazSes also supports macros and personal vocabulary, so the tool can become more useful for your own workflow over time.&lt;/p&gt;
&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;At a high level, the pipeline looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trigger key
   ↓
Record audio while held
   ↓
Voice activity / endpoint handling
   ↓
Local faster-whisper transcription
   ↓
Command grammar or plain text
   ↓
Type into the focused app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important design choice is that the speech-to-text step happens locally. Your audio does not need to be uploaded to a cloud service to become text.&lt;/p&gt;

&lt;p&gt;This makes YazSes useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;private notes&lt;/li&gt;
&lt;li&gt;coding sessions&lt;/li&gt;
&lt;li&gt;terminal workflows&lt;/li&gt;
&lt;li&gt;accessibility experiments&lt;/li&gt;
&lt;li&gt;offline environments&lt;/li&gt;
&lt;li&gt;privacy-focused Linux setups&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;YazSes is still evolving, and I want to be honest about the current scope.&lt;/p&gt;

&lt;p&gt;First, YazSes is &lt;strong&gt;Linux-first&lt;/strong&gt; right now. The repository also contains macOS and Windows backends/install guides, but those builds are still more experimental. I would especially welcome testers on macOS and Windows.&lt;/p&gt;

&lt;p&gt;Second, Linux input behavior can depend on your desktop environment. X11 and Wayland can behave differently, especially around global hotkeys and text injection.&lt;/p&gt;

&lt;p&gt;Third, YazSes is not an LLM agent. It will not plan tasks, browse your repository, or make decisions for you. It is a local dictation and command tool.&lt;/p&gt;

&lt;p&gt;Fourth, accuracy depends on your microphone, environment, model choice, accent, and vocabulary. The goal is to make the setup practical and tunable, but speech recognition is never perfect for everyone out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I made it open source
&lt;/h2&gt;

&lt;p&gt;I wanted a tool that was useful, inspectable, and privacy-friendly.&lt;/p&gt;

&lt;p&gt;Voice input is too important to be locked behind cloud-only systems. It can help with productivity, accessibility, fatigue, coding, writing, and everyday computer use.&lt;/p&gt;

&lt;p&gt;For me, the ideal version of this tool is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simple enough to trust&lt;/li&gt;
&lt;li&gt;local by default&lt;/li&gt;
&lt;li&gt;useful on Linux&lt;/li&gt;
&lt;li&gt;friendly to developers&lt;/li&gt;
&lt;li&gt;helpful for accessibility users&lt;/li&gt;
&lt;li&gt;extensible with commands and macros&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the direction I am trying to take YazSes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/MSKazemi/yazses" rel="noopener noreferrer"&gt;https://github.com/MSKazemi/yazses&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Project site:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mskazemi.github.io/yazses/" rel="noopener noreferrer"&gt;https://mskazemi.github.io/yazses/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pipx install yazses&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Or on Linux with Snap:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo snap install yazses&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I would really appreciate feedback, especially on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transcription accuracy&lt;/li&gt;
&lt;li&gt;setup problems&lt;/li&gt;
&lt;li&gt;Linux desktop compatibility&lt;/li&gt;
&lt;li&gt;X11 vs Wayland behavior&lt;/li&gt;
&lt;li&gt;useful voice commands&lt;/li&gt;
&lt;li&gt;accessibility use cases&lt;/li&gt;
&lt;li&gt;macOS and Windows testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the project is useful to you, a GitHub star, issue, or test report would help a lot.&lt;/p&gt;

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