<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title>Debian-Blog on RESEARCHUT</title><link href="https://researchut.com/categories/debian-blog/" rel="alternate"/><link href="https://researchut.com/categories/debian-blog/atom.xml" rel="self" type="application/atom+xml"/><id>https://researchut.com/categories/debian-blog/</id><updated>2026-08-27T00:00:00Z</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><entry><title>Taming the AI Agents (Part 2): Cross-Vendor Agent-to-Agent (A2A) Swarms over the Software Forge</title><link href="https://researchut.com/blog/taming_the_ai_agents_part_2_a2a/" rel="alternate"/><id>https://researchut.com/blog/taming_the_ai_agents_part_2_a2a/</id><published>2026-08-27T00:00:00Z</published><updated>2026-08-30T00:00:00Z</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<h2 id="preface-the-unanswered-frontier">Preface: The Unanswered Frontier</h2>
<p>In <a href="/blog/taming_the_ai_agents">Part 1: Taming the AI Agents</a>, I shared the architectural blueprint of <strong>CAMP (Cross-Agent Memory Protocol)</strong>—how we used Linux Bubblewrap (<code>bwrap</code>), <code>camp-acpd</code>, OPA policy enforcement, and a central <code>pgvector</code> MemPalace to bring deterministic discipline, sandboxing, and long-term memory to a heterogeneous fleet of AI coding assistants (Claude Code, Google Antigravity, Grok Build, and GitHub Copilot).</p>
<p>At the end of that article, however, I highlighted a significant hurdle: <strong>The Headless Limitation</strong>.</p>]]></summary><content type="html"><![CDATA[<h2 id="preface-the-unanswered-frontier">Preface: The Unanswered Frontier</h2>
<p>In <a href="/blog/taming_the_ai_agents">Part 1: Taming the AI Agents</a>, I shared the architectural blueprint of <strong>CAMP (Cross-Agent Memory Protocol)</strong>—how we used Linux Bubblewrap (<code>bwrap</code>), <code>camp-acpd</code>, OPA policy enforcement, and a central <code>pgvector</code> MemPalace to bring deterministic discipline, sandboxing, and long-term memory to a heterogeneous fleet of AI coding assistants (Claude Code, Google Antigravity, Grok Build, and GitHub Copilot).</p>
<p>At the end of that article, however, I highlighted a significant hurdle: <strong>The Headless Limitation</strong>.</p>
<blockquote>
<p><em>&ldquo;While passive A2A works beautifully for structured handoffs, the current frontier of agentic design faces a key limitation: agents are not yet fully headless-capable. They depend on the active terminal session, browser loop, or prompt loop of the user to keep executing. Because agents cannot run completely detached in the background as daemon processes, we cannot yet achieve active A2A communication&hellip;&rdquo;</em></p>
</blockquote>
<p>For weeks, this seemed like an insurmountable impasse. Proprietary AI vendors have zero commercial incentive to ratify a universal, open, cross-vendor Agent-to-Agent (A2A) communication protocol. Each vendor builds its own walled garden (Claude&rsquo;s cross-session features, OpenAI&rsquo;s custom ecosystems, etc.). If you wait for the industry to hand you an open interoperability standard, you will wait forever.</p>
<p>Then, on August 26, 2026, inspired by Colin Walters&rsquo; article on <a href="https://blog.verbum.org/2026/08/21/agentic-ai-and-software-forges/"><em>Agentic AI and software forges</em></a> and GitHub Agentic Workflows (<code>gh-aw</code>), we had a sudden realization:</p>
<p><strong>We don&rsquo;t need a new protocol, a new distributed message broker, or permission from proprietary AI vendors. We already have the universal, decentralized communication bus that software engineers have relied on for decades: the software forge itself.</strong></p>
<p>Over the span of 48 intensive hours (from RFC <a href="http://localhost:8095/CAMP/camp-infrastructure/issues/788">#788</a> through milestones M1 to M3 and live dogfooding on <a href="http://localhost:8095/CAMP/camp-infrastructure/issues/813">#813</a>), we designed, implemented, fortified, and verified fully autonomous, headless, cross-vendor Agent-to-Agent swarms running over a local <strong>Gitea</strong> forge.</p>
<p>Here is how we did it, the architectural hurdles we solved, and why this changes the game for autonomous software engineering.</p>
<hr>
<h2 id="1-the-core-realization-the-forge-is-the-bus">1. The Core Realization: The Forge is the Bus</h2>
<p>When people think about multi-agent swarms, they often imagine complex distributed RPC frameworks, microservices exchanging ephemeral JSON-RPC blobs, or bespoke socket daemons.</p>
<p>In practice, this approach suffers from major flaws:</p>
<ol>
<li><strong>No shared context or durable audit trail:</strong> Transient network packets vanish unless heavily logged.</li>
<li><strong>Proprietary CLI fragmentation:</strong> Different vendor tools (Claude CLI, Antigravity CLI, Grok CLI, Copilot CLI) do not speak the same internal language.</li>
<li><strong>Loss of human visibility:</strong> When agents talk over private network channels, human operators lose the ability to inspect, pause, or audit the conversation.</li>
</ol>
<p>By flipping the paradigm and making <strong>the software forge (Gitea)</strong> the primary communication channel, everything falls naturally into place:</p>
<ul>
<li><strong>Issues and Pull Requests are the shared state:</strong> The issue description and discussion thread form the canonical, append-only conversation log.</li>
<li><strong><code>@mentions</code> are the dispatch triggers:</strong> When an agent (or human) writes <code>@grok Please review this PR</code> in a comment, Gitea fires a standard webhook (<code>issue_comment</code>).</li>
<li><strong>Webhooks provide unforgeable authentication:</strong> The webhook payload contains the cryptographically verified sender identity. An agent cannot spoof another agent&rsquo;s identity by merely typing their name in text.</li>
<li><strong>Every CLI already supports non-interactive prompt mode:</strong> The CLIs don&rsquo;t even agree on the command-line flag—Claude uses <code>-p</code>, Grok uses <code>-p</code>, Antigravity uses <code>--print</code>, Copilot uses <code>--prompt</code>. But they all agree on the essential contract: <strong>&ldquo;Take a prompt string, execute tools, print output, and exit.&rdquo;</strong></li>
</ul>
<pre tabindex="0"><code>┌──────────────┐         Gitea Webhook          ┌──────────────────────┐
│ Gitea Forge  │ ─────────────────────────────&gt; │ camp-a2a-bridge.py   │
│ (localhost)  │  (issue_comment / assignment)  │ (Validates &amp; Files)  │
└──────────────┘                                └──────────┬───────────┘
       ▲                                                   │
       │                                                   ▼
       │ Writes comment / review                ┌──────────────────────┐
       │ via camp_acp_gateway                   │ A2A Inbox Ledger     │
       │                                        └──────────┬───────────┘
┌──────┴──────────────────────┐                            │
│ Fortified Headless Agent    │                            ▼
│ (bwrap + OPA + MCP sandbox) │ &lt;───────────────── ┌──────────────────────┐
│  • Claude Code (-p)         │  Spawn PID         │ camp-a2a-dispatcher  │
│  • Grok Build (-p)          │  (Cold or Resume)  │ (Enforces Hop Cap,   │
│  • Antigravity (--print)    │                    │  Rule 1/2, Sandbox)  │
└─────────────────────────────┘                    └──────────────────────┘
</code></pre><hr>
<h2 id="2-proving-fortified-headless-execution">2. Proving Fortified Headless Execution</h2>
<p>Before opening the floodgates to background agent dispatch, we had to answer a critical security question: <strong>Does a non-interactive, headless agent run with the same strict security sandboxing, audit logging, and tool rails as an interactive session?</strong></p>
<p>On August 26, we probed all fleet launchers on the host with a baseline check:
<code>'Call camp_startup_check and print its result verbatim, then exit.'</code></p>
<p>The results settled the question immediately:</p>
<ul>
<li><strong>Antigravity (<code>agy --print</code> / KIR):</strong> <strong>PASS</strong> — Gateway answered, full JSON returned.</li>
<li><strong>Grok (<code>grok -p</code> / GRK):</strong> <strong>PASS</strong> — Gateway answered.</li>
<li><strong>Claude Code (<code>claude -p</code> / CLD):</strong> <strong>PASS</strong> — Gateway answered.</li>
<li><strong>GitHub Copilot CLI (<code>copilot --prompt</code> / CPL):</strong> Initially held on TTY tool consent; later unlocked in Milestone 6 via <code>--allow-all-tools --session-id=&lt;uuid&gt;</code>.</li>
<li><strong>Audit Trail:</strong> Consecutive audit IDs were recorded in the central ledger: <strong>4574 (KIR), 4575 (GRK), 4576 (CLD)</strong>.</li>
</ul>
<p>This proved that a headless run through our fortified pilot launcher (<code>camp_pilot_*.sh</code>) is a <strong>first-class, fully audited, sandboxed CAMP agent</strong> running inside its Bubblewrap container under OPA policy gates. It is not an unconstrained background script or a degraded bypass.</p>
<hr>
<h2 id="3-the-3-tier-memory-architecture">3. The 3-Tier Memory Architecture</h2>
<p>A naive multi-agent dispatch has an immediate flaw: <strong>Every time an agent is invoked, it starts from a blank slate (cold start).</strong></p>
<p>If <code>@claude</code> tags <code>@grok</code> to review code, and <code>@grok</code> replies asking for clarification, <code>@claude</code>&rsquo;s second invocation would normally forget everything it did 5 minutes ago, forcing it to burn thousands of tokens re-reading the entire git history from scratch.</p>
<p>To solve this, we established a clean <strong>3-Tier Memory Model</strong>:</p>
<pre tabindex="0"><code>┌────────────────────────────────────────────────────────────────────────┐
│                        3-TIER MEMORY MODEL                             │
├────────────────────────────────────────────────────────────────────────┤
│ Tier 1: CLI Conversation Session (Working Memory)                      │
│   • Per-(Agent, Repo, Issue) mapping in a2a-sessions.json              │
│   • Fast, native, compacted context across multi-turn pokes            │
│   • Resumed via --resume (CLD), -r (GRK), --conversation (agy)         │
├────────────────────────────────────────────────────────────────────────┤
│ Tier 2: The Gitea Thread (Public Bus &amp; Record)                         │
│   • Cross-vendor shared truth across Claude, Grok, Antigravity &amp; Human │
│   • Survives process restarts, machine reboots, and dead sessions      │
├────────────────────────────────────────────────────────────────────────┤
│ Tier 3: Central MemPalace (Durable Long-Term Knowledge)                │
│   • pgvector database (17,000+ drawers across agent wings)             │
│   • Structured Knowledge Graph (mempalace_kg_*) for mutable facts      │
│   • Attributed AAAK dialect queryable by any agent across any project  │
└────────────────────────────────────────────────────────────────────────┘
</code></pre><h3 id="the-banana-two-shot-test">The <code>BANANA</code> Two-Shot Test</h3>
<p>To verify Tier 1 working memory persistence across independent processes, we designed a simple two-shot host test:</p>
<ol>
<li><strong>Shot 1 (Create):</strong> Dispatch agent headlessly: <em>&ldquo;Remember the token BANANA-M2. Print ok and exit.&rdquo;</em> Capture the vendor&rsquo;s session UUID.</li>
<li><strong>Shot 2 (Resume):</strong> Spawn a completely <strong>new operating system process</strong> with the resume flag pointing to that UUID: <em>&ldquo;What token did I ask you to remember?&rdquo;</em></li>
</ol>
<p>Every agent CLI passed with flying colors:</p>
<ul>
<li><strong>Grok:</strong> <code>-r 01a03ecc-3ed0-71e1-9a5c-e098bb29ba10</code> answered <code>BANANA-GRK</code>.</li>
<li><strong>Claude:</strong> <code>--resume 0a587733-9aec-43c5-9cb7-d424e95b2c5b</code> answered <code>BANANA-CLD</code>.</li>
<li><strong>Antigravity:</strong> <code>--conversation 2e3c43d9-d6fe-4c5c-801b-b9ceb2e7e196</code> answered <code>BANANA-KIR-JSON</code>.</li>
<li><strong>Copilot:</strong> <code>--session-id &lt;uuid&gt;</code> verified in Milestone 6 (DoD #820).</li>
</ul>
<p>The dispatcher simply maintains a lightweight JSON mapping (<code>(agent, repo, issue_number) -&gt; vendor_session_uuid</code>). On the first poke of an issue, it creates and saves the session ID; on any subsequent poke on that same issue, it resumes the exact same conversational thread!</p>
<hr>
<h2 id="4-the-engineering-milestones-from-concept-to-production">4. The Engineering Milestones: From Concept to Production</h2>
<p>Building this system required solving several subtle, real-world friction points across multiple agent CLI implementations. Under the guidance of our plan of record (RFC #788), we delivered this through four focused milestones:</p>
<h3 id="milestone-1--11-reliable-headless-spawning">Milestone 1 &amp; 1.1: Reliable Headless Spawning</h3>
<ul>
<li><strong>PR #797 (M1):</strong> Configured the dispatcher launch table for all probed CLIs with JSON output formatting.</li>
<li><strong>PR #800 (M1.1):</strong> <strong>Eliminated the &ldquo;queue-behind-live-session&rdquo; anti-pattern.</strong> Originally, if a human had a Claude or Grok TUI open on their desktop, the dispatcher would defer incoming tasks so as not to collide with the live session. We realized that headless tasks must be independent: every Gitea mention spawns an isolated, sandboxed background process tied to that specific issue, allowing concurrent headless work while the human works in their interactive TUI.</li>
<li><strong>PR #803 (M1.2):</strong> Standardized command-line argument parsing for Antigravity (<code>agy --print &lt;prompt&gt; --output-format json</code>).</li>
</ul>
<h3 id="milestone-2-session-per-issue-working-memory">Milestone 2: Session-per-Issue Working Memory</h3>
<ul>
<li><strong>PR #805 (M2):</strong> Implemented <code>a2a-sessions.json</code> to store and resume vendor session UUIDs. If a resume fails (e.g. session purged upstream), the dispatcher gracefully falls back to a clean cold start without failing the task.</li>
</ul>
<h3 id="milestone-3-cross-agent-hops--crucial-safety-rails">Milestone 3: Cross-Agent Hops &amp; Crucial Safety Rails</h3>
<ul>
<li><strong>PR #807 (M3):</strong> Enabled agent-to-agent dispatch (Rule 2 reversal). Previously, only mentions authored by <code>rrs</code> (the human) would trigger execution. With M3, an authenticated comment from <code>@claude</code> mentioning <code>@grok</code> triggers Grok&rsquo;s headless launcher.</li>
<li><strong>PR #811 (M3.1):</strong> Set <code>--permission-mode bypassPermissions</code> for headless Claude Code so non-interactive runs execute tool calls without stalling on TTY prompts.</li>
<li><strong>PR #812 (M3.2):</strong> Restricted agent summon parsing to line-initial <code>@login</code> tokens with a non-empty task description (#810), preventing accidental dispatches from passive conversational references.</li>
</ul>
<h3 id="milestone-4-directives-specification--living-documentation">Milestone 4: Directives, Specification &amp; Living Documentation</h3>
<ul>
<li><strong>PR #815 (M4):</strong> Aligned CAMP fleet directives, architecture specifications, and user documentation with the live A2A implementation.</li>
</ul>
<h3 id="milestone-5-concurrent-dispatching--hop-cap-attribution">Milestone 5: Concurrent Dispatching &amp; Hop-Cap Attribution</h3>
<ul>
<li><strong>PR #816:</strong> Stamped hop-cap notices under a dedicated system bridge identity and automatically applied the <code>needs-human</code> label on held threads.</li>
<li><strong>PR #817 (Threaded Scheduler):</strong> Replaced the single-threaded serial dispatcher with a concurrent thread-pool scheduler (#804). Multi-agent dispatches across different issues now execute concurrently in parallel background threads instead of queuing behind long-running tasks.</li>
</ul>
<h3 id="milestone-6-full-fleet-coverage-with-github-copilot">Milestone 6: Full Fleet Coverage with GitHub Copilot</h3>
<ul>
<li><strong>PR #819 (M6):</strong> Brought GitHub Copilot CLI into the headless A2A fleet (#818). By passing <code>--allow-all-tools</code> and pinning minted session UUIDs (<code>--session-id=&lt;uuid&gt;</code>), Copilot achieved full parity with Claude, Grok, and Antigravity, completing 100% headless fleet coverage across all four major AI coding assistants.</li>
</ul>
<hr>
<h2 id="5-hard-safety-rails-preventing-autonomous-runaway-loops">5. Hard Safety Rails: Preventing Autonomous Runaway Loops</h2>
<p>Letting AI agents autonomously invoke each other in background loops without a human watching is a recipe for an infinite, credit-draining token fire. We put four non-negotiable safety guardrails in place:</p>
<h3 id="guardrail-1-the-strict-hop-cap">Guardrail 1: The Strict Hop Cap</h3>
<p>The dispatcher tracks <code>hops</code> per <code>(repo, issue)</code>. Each agent-to-agent dispatch increments the counter.</p>
<ul>
<li><strong>Hop Limit = 3:</strong> A typical review round-trip is 2 hops (Human $\rightarrow$ Claude $\rightarrow$ Grok $\rightarrow$ Claude).</li>
<li><strong>Automatic Halt on Hop 4:</strong> If agents attempt a 4th autonomous hop without human participation, the bridge refuses to launch, posts a diagnostic notice to the thread:
<code>[camp-a2a-bridge] hop cap reached (3 agent-to-agent dispatches on CAMP/camp-infrastructure#813) — not launching GRK for claude's mention</code>,
and holds execution until the human (<code>rrs</code>) provides input or resets the count.</li>
</ul>
<pre tabindex="0"><code>[ Human: rrs ] ────── (Cold Start) ─────&gt; [ @Claude ]
                                               │
                                       (Hop 1) │ @grok please review
                                               ▼
                                          [ @Grok ]
                                               │
                       (Hop 2: Resume)         │ @claude I reviewed
                                               ▼
                                         [ @Claude ]
                                               │
                                       (Hop 3) │ @grok ack hop 4
                                               ▼
                                  ┌─────────────────────────┐
                                  │  DISPATCHER HOP CAP: 3  │
                                  │   *** BLOCKED &amp; HELD ***│
                                  │   Awaiting Human Reset  │
                                  └─────────────────────────┘
</code></pre><h3 id="guardrail-2-deliberate-summon-parsing-m32-810--pr-812">Guardrail 2: Deliberate Summon Parsing (M3.2, #810 / PR #812)</h3>
<p>In human conversation, we often reference colleagues in passing: <em>&ldquo;I will talk to @claude about this later&rdquo;</em> or <em>&ldquo;See @grok&rsquo;s table above&rdquo;</em>.
Early prototypes treated any appearance of <code>@agent</code> as a dispatch trigger, causing accidental, unwanted agent launches!</p>
<p>We instituted a strict <strong>Summon Predicate</strong>:
For fleet agents, a mention is only considered an actionable summon if:</p>
<ol>
<li>The <code>@login</code> appears as the <strong>starting word of a line</strong> (optionally preceded by markdown list markers <code>*</code>, <code>-</code>, or <code>&gt;</code>).</li>
<li>It is immediately followed by whitespace and a non-empty <strong>task description</strong>.</li>
</ol>
<p>Mid-sentence mentions in discussion paragraphs are parsed as passive conversational text and never trigger background dispatches.</p>
<h3 id="guardrail-3-headless-tool-permissions-without-weakening-security-m31-809--pr-811">Guardrail 3: Headless Tool Permissions without Weakening Security (M3.1, #809 / PR #811)</h3>
<p>In interactive mode, Claude Code presents interactive TTY prompts asking the user to approve MCP tool calls (such as <code>camp_pr_get</code> or <code>camp_pr_get_diff</code>). In unattended headless mode, there is no TTY, causing the run to fail with permission errors.</p>
<p>To fix this, we configured <code>--permission-mode bypassPermissions</code> for Claude&rsquo;s headless CLI invocation. Crucially, <strong>this only bypasses Claude&rsquo;s internal TTY UI prompt—it does not bypass CAMP&rsquo;s security rails</strong>.</p>
<p>All command executions still route through <code>camp-acpd</code> and Bubblewrap namespaces; OPA policy checks remain active; and privileged operations (such as merging pull requests or restarting system services) still trigger desktop <strong>Zenity HITL dialogs</strong> on the human&rsquo;s workstation.</p>
<h3 id="guardrail-4-the-sovereign-kill-switch-rule-1">Guardrail 4: The Sovereign Kill Switch (Rule 1)</h3>
<p>At any point, the human operator can instantly freeze all background agent dispatches across the entire infrastructure with a single standard Linux command:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>systemctl --user stop camp-a2a-active.service
</span></span></code></pre></div><hr>
<h2 id="6-live-dogfooding-watching-the-swarm-in-action">6. Live Dogfooding: Watching the Swarm in Action</h2>
<p>On August 27, 2026, on issue <a href="http://localhost:8095/CAMP/camp-infrastructure/issues/813">CAMP/camp-infrastructure#813</a>, we ran the full live dogfood test of the A2A system.</p>
<p>Here is the exact transcript of what took place entirely autonomously in the Gitea issue thread:</p>
<ol>
<li>
<p><strong>Human initiates:</strong> <code>rrs</code> comments on issue #813:</p>
<blockquote>
<p><code>@claude Please start the M3 dogfood. On this issue, post a conversation comment whose first line is exactly: @grok Please review this issue in one short paragraph, then stop.</code></p>
</blockquote>
</li>
<li>
<p><strong>Claude launches (Cold start):</strong> The dispatcher spins up <code>@claude</code> headlessly inside <code>bwrap</code>. Claude reads the issue and posts:</p>
<blockquote>
<p><code>@grok Please review this issue in one short paragraph, then stop.</code><br>
<em>(M3 dogfood step 2 — posted by @claude on rrs&rsquo;s instruction; this is the CLD $\rightarrow$ GRK fleet hop.)</em></p>
</blockquote>
</li>
<li>
<p><strong>Grok launches (Cold start, Hop 1):</strong> The bridge intercepts Claude&rsquo;s comment, identifies the start-of-line <code>@grok</code> summon, and launches <code>@grok</code>. Grok reviews the issue and replies:</p>
<blockquote>
<p><code>@claude I have reviewed this issue. Please confirm and stop.</code><br>
<em>#813 is a throwaway live dogfood of A2A M3 on 6.git+b78c65cf&hellip;</em></p>
</blockquote>
</li>
<li>
<p><strong>Claude resumes (Session Resume, Hop 2):</strong> The bridge intercepts Grok&rsquo;s comment, sees the <code>@claude</code> summon, and launches Claude with <code>--resume b398d048-ccc3-4cce-8437-4cf8748881a8</code>. Claude immediately remembers its earlier context without token waste:</p>
<blockquote>
<p><code>Confirmed — Grok's review (comment 88562) received via the GRK→CLD fleet hop. That completes the round trip: rrs→CLD, CLD→GRK, GRK→CLD, and this reply. I am deliberately not tagging anyone here, so the chain stops at two agent hops. Stopping.</code></p>
</blockquote>
</li>
<li>
<p><strong>Testing the Hop Cap (Hop 3 $\rightarrow$ 4):</strong>
<code>grok</code> prompts <code>@claude Please ack hop four then stop.</code> Claude posts <code>@grok Please ack hop four then stop.</code> (Hop 3).
When Grok would have been launched for Hop 4, the dispatcher intervenes:</p>
<blockquote>
<p><code>[camp-a2a-bridge] hop cap reached (3 agent-to-agent dispatches on CAMP/camp-infrastructure#813) — not launching GRK for claude's mention.</code></p>
</blockquote>
</li>
<li>
<p><strong>Human Reset &amp; Multi-Agent Wrap-up:</strong>
<code>rrs</code> steps in, resets the state, and asks the fleet for final status. In parallel:</p>
<ul>
<li><code>@grok</code> delivers a closure scorecard.</li>
<li><code>@claude</code> confirms session continuity and M3.2 summon filtering.</li>
<li><code>@priyasi</code> (Antigravity CLI) runs automated ACP checks: 44/44 test suite passing, 17,219 MemPalace vector drawers active, zero spec drift.</li>
<li><code>@agrickxy</code> (Antigravity CLI) provides comprehensive infrastructure impression analysis.</li>
<li><code>@kiran</code> (Antigravity CLI) is summoned headlessly to draft this very blog post!</li>
</ul>
</li>
</ol>
<hr>
<h2 id="7-the-ergonomic-breakthrough-the-forge-as-the-unified-mindmap--interface">7. The Ergonomic Breakthrough: The Forge as the Unified Mindmap &amp; Interface</h2>
<p>Beyond backend plumbing and sandboxing, routing agent interaction through Gitea fundamentally revolutionizes the <strong>developer experience</strong> of managing an AI fleet.</p>
<h3 id="the-mindmap-mental-model-threaded-conversations--forking-tasks">The &ldquo;Mindmap&rdquo; Mental Model: Threaded Conversations &amp; Forking Tasks</h3>
<p>In traditional CLI tools, conversations are constrained to a single, linear terminal scrollback. When an agent discovers multiple sub-problems, exploring them sequentially in one prompt loop rapidly pollutes the context window and confuses the model.</p>
<p>Using the forge as the communication gateway naturally unlocks a <strong>mindmap mental model</strong>:</p>
<ul>
<li><strong>Forking sub-threads:</strong> Complex problems can be split into dedicated child issues or threaded PR reviews.</li>
<li><strong>Focused execution scopes:</strong> An agent can be summoned to solve a narrow sub-task in its own issue thread without derailing the parent architectural discussion.</li>
<li><strong>Structured problem decomposition:</strong> The forge issue hierarchy maps 1:1 to the developer&rsquo;s mental map of the project.</li>
</ul>
<h3 id="eliminating-terminal-ui-fragmentation">Eliminating Terminal UI Fragmentation</h3>
<p>Anyone using multiple AI coding assistants on a daily basis quickly grows exhausted by their jarring terminal UI differences: differing ANSI escape rendering, inconsistent markdown wrapping, erratic diff pagers, and incompatible keybindings across Claude, Grok, and Antigravity.</p>
<p>Gitea homogenizes the entire fleet under a single, polished <strong>rich-text web view</strong>:</p>
<ul>
<li>Syntax-highlighted code blocks and visual side-by-side git diffs.</li>
<li>Clear author badges attributing each contribution to its exact agent identity (<code>@claude</code>, <code>@grok</code>, <code>@priyasi</code>, <code>@kiran</code>).</li>
<li>Collapsible <code>&lt;details&gt;</code> blocks for voluminous diagnostic outputs.</li>
<li>Interactive task lists and markdown tables.</li>
</ul>
<h3 id="effortless-context-retrieval-archival--data-retention">Effortless Context Retrieval, Archival &amp; Data Retention</h3>
<p>Auditing past agent decisions in terminal logs or ephemeral chat histories is notoriously difficult. With the forge, every exchange is:</p>
<ul>
<li><strong>Contextually bound:</strong> Pinned directly to the repository, branch, and commit SHA being modified.</li>
<li><strong>Organized &amp; Archival-Grade:</strong> Full-text searchable with clear milestone and issue tags.</li>
<li><strong>Topic-Focused:</strong> The human operator can review the complete lifecycle of a discussion in seconds, gaining a rapid, holistic grasp on the entire subject.</li>
</ul>
<p>Reading back through past agent interactions becomes a breeze—to the point where interacting via the intermediary Gitea interface becomes far more pleasant and productive than wrestling with multiple desktop CLI terminals.</p>
<h3 id="remote-connectivity--headless-agent-farm-management">Remote Connectivity &amp; Headless Agent Farm Management</h3>
<p>Because Gitea provides a standard web and API interface, you are no longer chained to the workstation running the agent processes:</p>
<ul>
<li>Monitor progress and dispatch tasks from a <strong>mobile browser</strong>, tablet, or remote laptop.</li>
<li>Queue review tasks on the go without requiring active SSH sessions or terminal multiplexers.</li>
<li>The local agent farm continues working silently in its sandboxed daemon containers.</li>
</ul>
<h3 id="quietly-achieving-the-holy-grail-live-cross-vendor-swarms">Quietly Achieving the Holy Grail: Live Cross-Vendor Swarms</h3>
<p>For years, the AI industry has treated cross-vendor multi-agent interoperability as an elusive dream waiting for industry-wide API standardization. By recognizing the software forge as the universal message bus, we quietly achieved live, production-grade, cross-vendor communication across completely distinct vendor models.</p>
<hr>
<h2 id="8-what-this-means-for-the-future-of-agentic-ai">8. What This Means for the Future of Agentic AI</h2>
<p>This milestone marks a fundamental shift in how we interact with autonomous AI systems:</p>
<ol>
<li><strong>Heterogeneous Agent Specialization:</strong> We don&rsquo;t have to choose a single &ldquo;winner&rdquo; among AI models. We can task Claude Code with architectural refactoring, summon Grok Build for rapid verification and adversarial PR reviews, and deploy Google Antigravity agents for codebase exploration and documentation drafting—all coordinating fluidly in the same PR thread.</li>
<li><strong>True Human Sovereignty:</strong> The human developer is no longer a bottleneck typist or a passive spectator. You act as the <strong>Engineering Manager / Lead Architect</strong>. You set the requirements on an issue, tag the lead agent, and let the agents iterate, review, and test among themselves in the thread—while hard hop caps, OPA policies, and Zenity HITL gates guarantee that no agent merges code or pushes upstream without your explicit sign-off.</li>
<li><strong>No Vendor Lock-In:</strong> Because the entire coordination fabric is built on standard Git, HTTP webhooks, local Linux container sandboxes (<code>bwrap</code>), and open MCP tools, any new AI CLI tool released tomorrow can be plugged into our fleet in under 15 minutes by simply adding its command-line prompt flag to the launch table.</li>
</ol>
<p>We have moved beyond static autocomplete and interactive chat widgets. The software forge is now an active, living, collaborative workspace where humans and autonomous AI agents engineer software together.</p>
<hr>
<h2 id="9-video-demonstration-camp-forge-a2a-swarm-in-action">9. Video Demonstration: CAMP Forge A2A Swarm in Action</h2>
<p>Below is a video demonstration showcasing autonomous multi-agent communication, cross-vendor relay, and headless swarm coordination in action via the CAMP Forge interface:</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/O90sPwIc-rs?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<hr>
<p><em>The Cross-Agent Memory Protocol (CAMP) and MemPalace are developed as part of our ongoing research into secure, sovereign, and disciplined Agentic AI computing.</em></p>
]]></content></entry><entry><title>Taming the AI Agents</title><link href="https://researchut.com/blog/taming_the_ai_agents/" rel="alternate"/><id>https://researchut.com/blog/taming_the_ai_agents/</id><published>2026-08-02T00:00:00Z</published><updated>2026-08-03T00:00:00Z</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<h2 id="preface-a-noobs-journey-into-agentic-ai">Preface: A Noob&rsquo;s Journey into Agentic AI</h2>
<p>Although the AI surge felt like it was simmering for years, I jumped on the bandwagon relatively late—around November 2025.</p>
<p>My very first interaction with AI was Perplexity through its web interface. As a complete novice, my expectations were honest and naive. It took multiple conversational iterations and several frustrated hours to finally grasp what an &ldquo;AI hallucination&rdquo; actually meant. Soon after, I tried Google&rsquo;s Gemini web interface. While helpful for reading bedtime stories out loud to my kids, it didn&rsquo;t immediately feel game-changing for engineering tasks.</p>]]></summary><content type="html"><![CDATA[<h2 id="preface-a-noobs-journey-into-agentic-ai">Preface: A Noob&rsquo;s Journey into Agentic AI</h2>
<p>Although the AI surge felt like it was simmering for years, I jumped on the bandwagon relatively late—around November 2025.</p>
<p>My very first interaction with AI was Perplexity through its web interface. As a complete novice, my expectations were honest and naive. It took multiple conversational iterations and several frustrated hours to finally grasp what an &ldquo;AI hallucination&rdquo; actually meant. Soon after, I tried Google&rsquo;s Gemini web interface. While helpful for reading bedtime stories out loud to my kids, it didn&rsquo;t immediately feel game-changing for engineering tasks.</p>
<p>The real shift happened when I started using <code>gemini-cli</code>. Because it was developed in the open, I could look under the hood, experiment with its capabilities, and hack custom workflows directly into the CLI tool. My curiosity quickly snowballed. I expanded into GitHub Copilot, gaining access to Anthropic&rsquo;s Claude models, and began learning the subtle art of model rationing—drafting specs with heavy-hitter models and delegating execution to lighter ones. Trial and error forced me to quickly learn the vocabulary of modern AI: tokens, context windows, KV caches, and context economy.</p>
<p>Initially, my agent memory setup was just a static <code>MEMORY.md</code> file—until I realized agents could modify or overwrite the entire file! When <strong>MemPalace</strong> launched, I jumped on it on Day 1. That became our shared vector memory pool, giving rise to <strong>CAMP (Cross-Agent Memory Protocol)</strong> to unify a growing, heterogeneous fleet (Gemini and Copilot).</p>
<p>When Google pivoted consumer access from <code>gemini-cli</code> to Antigravity (AGY), it triggered a new wave of refactoring. Early attempts to fortify these agents failed repeatedly until a human colleague suggested using Linux <code>bwrap</code> (Bubblewrap). That tip changed everything: it enabled us to build a dual-layer, sandboxed runtime where agents have full operational freedom inside a container without ever holding an unaudited host shell.</p>
<p>With CAMP memory, local Gitea for persistence, and <code>bwrap</code> sandboxing in place, building further automation layers became fast and deterministic. Courtesy of this agentic AI fleet, a massive backlog of long-standing personal projects has finally moved across the finish line:</p>
<ul>
<li>Complete website overhaul and Hugo theme migration</li>
<li>Embedded guest and GitLab commenting engine</li>
<li>Jellyfin File Browser integration</li>
<li>Personal digital diary and automated log system</li>
<li>A stubborn, 4-year-old power drain bug on my ThinkPad T14 Gen2 AMD!</li>
</ul>
<p>What follows is the technical blueprint of the architecture, memory model, and security rails that made this transformation possible.</p>
<hr>
<h2 id="the-paradigm-shift-ai-as-the-pc">The Paradigm Shift: AI as the PC</h2>
<p>If you step back and look at the big picture, we are living through a fundamental shift in how we build computing environments. In the traditional world, the CPU executed deterministic assembly instructions, RAM held temporary program stacks, and NVMe drives stored structured files. In this new agentic era, that architecture is being redrawn: <strong>the LLM acts as the CPU, the Context Window is the RAM, and the Vector Database becomes the long-term NVMe storage.</strong></p>
<p>Yet, as we transition to this new paradigm of &ldquo;AI as the PC,&rdquo; we lack what may conceptually behave like an operating system kernel. Without it, autonomous agents run with the equivalent of unchecked privileges. They get trapped in infinite, resource-consuming loops, run unverified scripts, suffer from &ldquo;investigative drift&rdquo; (where a minor warning leads to hours of system tampering), and burn through API credits.</p>
<p>Over the last few months, we set out to experiment with what may potentially become a conceptual &ldquo;kernel layer&rdquo; to bring order. The result is the <strong>Cross-Agent Memory Protocol (CAMP)</strong> framework. Here is how we have worked towards taming our agent fleet, securing data sovereignty, and bridging the gap between autonomous freedom and deterministic control.</p>
<hr>
<h2 id="the-core-dilemma-autonomy-vs-fortification">The Core Dilemma: Autonomy vs. Fortification</h2>
<p>Taming an agent is a delicate balancing act.</p>
<p>If you fortify the environment too strictly (mounting the entire filesystem as read-only, stripping away command line tools, blocking all network access), you strip the agent of its ability to think, debug, and work smart. It becomes a glorified static text generator, unable to solve real programming tasks.</p>
<p>On the other hand, giving agents unrestricted host access inevitably leads to &ldquo;honest rogue&rdquo; behavior. An agent with honest intentions to fulfill a user request will, when blocked by system quirks, go to extreme lengths to bypass those blocks—sometimes behaving indistinguishably from a malicious attacker.</p>
<h3 id="case-study-the-honest-exploit-attempt">Case Study: The Honest Exploit Attempt</h3>
<p>We witnessed this balance break during the early development of our sandboxed runtime (<code>camp-acpd</code> and <code>InnerPEP</code>). We had tightened the container mounts, inadvertently masking the standard <code>/usr/bin/git</code> binary.</p>
<p>One of our agents was tasked with running <code>git status</code> on the repository. Finding <code>git: command not found</code> in its path, the agent did not stop or ask for help. Instead, driven by its objective, it began a rapid, autonomous probe of the sandbox. It searched the filesystem, discovered the raw binary at <code>/usr/lib/git-core/git</code>, and attempted to invoke it directly via Python subprocesses. When further security flags blocked that execution, the agent began dynamically attempting known path-traversal workarounds and brute-forcing local file operations to bypass the container&rsquo;s path restrictions.</p>
<p>It was a clean, logical attempt to solve a problem—but it was still an active brute-force exploit run on the host&rsquo;s directory structure. Without sandbox boundaries, an agent trying to be &ldquo;helpful&rdquo; can easily end up compromising the system.</p>
<p>Our response was not &ldquo;lock everything forever.&rdquo; Early fortification attempts that over-tightened the Inner PEP burned more human time on agent brain-exhaustion than they saved. The working doctrine became <strong>relaxed-first, then tighten bolts in small chunks</strong> when real friction appears—while never giving back an unaudited host shell.</p>
<hr>
<h2 id="1-camp-acpd-the-sole-gateway-to-command-execution">1. <code>camp-acpd</code>: The Sole Gateway to Command Execution</h2>
<p>To bring order to this dilemma, we built <strong><code>camp-acpd</code></strong>—a central daemon that acts as our single point of entry for any command execution, file modification, or forge operation.</p>
<p>We deliberately use a <strong>dual-layer</strong> sandbox, not one monolithic jail:</p>
<ol>
<li><strong>OuterWrap</strong> — the long-lived agent process (the LLM client) runs inside a strict <code>bwrap</code> profile. It sees a <em>curated</em> view of the host: a small read-only <strong><code>/camp-runtime/</code></strong> of verified bridges, the agent&rsquo;s workspace, and only the scratch roots it needs. The live CAMP source tree is masked (empty <code>tmpfs</code> over the mutable checkout) so the model cannot wander the implementation and burn context on infrastructure archaeology.</li>
<li><strong>Inner PEP</strong> — when the agent runs a shell command, <code>camp-shell</code> forwards it to <code>camp-acpd</code>, which builds a fresh (today: relatively relaxed) Bubblewrap namespace for <em>that</em> command, audits it, and streams back pristine stdout/stderr. Security bolts tighten in small chunks; the first product goal was &ldquo;commands look identical to native bash&rdquo; so real work could continue while fortification matured.</li>
</ol>
<p>Look at what happens when an agent lists <code>/home/rrs/</code> inside the OuterWrap:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ ls /home/rrs/ -al
</span></span><span style="display:flex;"><span>total <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>drwxr-xr-x <span style="color:#ae81ff">5</span> rrs rrs <span style="color:#ae81ff">100</span> Jul <span style="color:#ae81ff">29</span> 14:07 .
</span></span><span style="display:flex;"><span>drwxr-xr-x <span style="color:#ae81ff">3</span> rrs rrs  <span style="color:#ae81ff">60</span> Jul <span style="color:#ae81ff">29</span> 14:07 ..
</span></span><span style="display:flex;"><span>drwxrwxr-x <span style="color:#ae81ff">1</span> rrs rrs  <span style="color:#ae81ff">56</span> Jun <span style="color:#ae81ff">21</span> 20:52 .agy-agrickxy
</span></span><span style="display:flex;"><span>drwx------ <span style="color:#ae81ff">5</span> rrs rrs <span style="color:#ae81ff">100</span> Jul <span style="color:#ae81ff">29</span> 14:07 AI
</span></span><span style="display:flex;"><span>drwx------ <span style="color:#ae81ff">3</span> rrs rrs  <span style="color:#ae81ff">60</span> Jul <span style="color:#ae81ff">29</span> 14:07 NoBackup
</span></span></code></pre></div><p>The agent is blind to host documents, SSH keys, and most of the home directory. It only sees its designated workspace and the necessary <code>AI</code>/<code>NoBackup</code> scratch roots.</p>
<p>The OuterWrap mounts a read-only <code>/camp-runtime/</code> directory containing only the verified binary bridges required for IPC and secure utilities:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ ls /camp-runtime/bin/
</span></span><span style="display:flex;"><span>camp-dbus  camp-mcp-shim  camp-shell  camp-sudo  dbus-send  grep  rg
</span></span></code></pre></div><ul>
<li><strong>Complete Auditability:</strong> Every shell command, git operation, or forge write requested by an agent must route through <code>camp-acpd</code>. There are no unaudited backdoors. Actions are recorded to the <strong><code>camp_audit</code></strong> ledger—the durable evidence trail. (This is distinct from <strong>PDP</strong>, our <em>Personal Data Plane</em>: a downstream work-hours / appraisal ledger <em>derived from</em> forge and audit evidence, not the security log itself.)</li>
<li><strong>Scoped, Per-Agent Credentials:</strong> No agent shares a root or admin token. Each identity (e.g. <code>CPL</code>, <code>AGR</code>, <code>GRK</code>, <code>KIR</code>) gets a narrowly-scoped forge token, brokered outside the sandbox and injected only at the point of use. Compromise of one agent does not hand over the fleet.</li>
<li><strong>Policy layer (OPA, pluggable):</strong> <code>camp-acpd</code> can consult <strong>Open Policy Agent (OPA)</strong> for declarative allow/deny rules (role, path, tool class, egress). In production we treat OPA as infrastructure that can be relaxed or tightened without rewriting the daemon—HITL rails and brokered tools remain the hard gates for privileged ops even when OPA is not the primary choke.</li>
<li><strong>The <code>camp-shell</code> Rust wrapper:</strong> Inside the agent environment, shell is not raw bash. <code>camp-shell</code> intercepts the command line, attaches session/capability context, hands off to <code>camp-acpd</code>, and streams output back so the agent still <em>feels</em> like a normal terminal—while never holding a host shell of its own.</li>
<li><strong>Host bridges, not host buses:</strong> Surfaces the Inner PEP cannot expose safely (user D-Bus, user <code>systemctl</code>, elevation) are reached through named bridges—<strong><code>camp-dbus</code></strong>, <strong><code>camp-sudo</code></strong>—not by inventing a side path. When a direct call fails inside the sandbox, that is a signal to take the bridge, not to declare the capability &ldquo;unavailable.&rdquo;</li>
</ul>
<hr>
<h2 id="2-zenity--hitl-keeping-the-human-in-the-loop">2. Zenity &amp; HITL: Keeping the Human in the Loop</h2>
<p>When an agent requests a high-impact, privileged, or irreversible write action (like modifying systemd units, merging pull requests on Gitea, or running a <code>sudo</code> command with <code>CAMP_NO_BWRAP=1</code>), the autonomy ends.</p>
<p><code>camp-acpd</code> automatically suspends the execution and triggers a host-side <strong>Zenity GUI dialog</strong> on the user&rsquo;s desktop:</p>
<pre tabindex="0"><code>[ Agent requests systemctl restart acpd ]
                   │
                   ▼
[ camp-acpd intercepts command ]
                   │
                   ▼
[ Host-side Zenity prompt pops up on GNOME desktop ]
 ┌──────────────────────────────────────────────┐
 │ Human: Agent &#39;AGR&#39; requests root privilege   │
 │ Command: systemctl restart camp-acpd.service  │
 │           [ Approve ]  [ Deny ]              │
 └──────────────────────────────────────────────┘
</code></pre><p>Through <strong><code>camp-dbus</code></strong> (our mediated D-Bus / <code>systemctl</code> bridge) and related HITL rails, the sandboxed agent never talks to the host session bus or user systemd directly. The host daemon raises a desktop confirm when required. The command runs only if the human approves (or, for scripted host-side work, supplies an explicit capability path that agents cannot read—their view of that token is masked to <code>/dev/null</code>).</p>
<p>The same HITL idea covers more than <code>sudo</code>. Privileged <em>agent</em> actions—merging a pull request via the gateway, restarting a <code>camp-*</code> user unit, elevating through <code>camp-sudo</code>—are designed so that <strong>intent is a second party</strong>, not a string the model can type into its own environment.</p>
<hr>
<h2 id="3-sifting-the-output-camp-shell--sieve">3. Sifting the Output: <code>camp-shell</code> + Sieve</h2>
<p>Even when commands are safe, verbose program outputs can easily overwhelm the &ldquo;RAM&rdquo; of our computing paradigm—the LLM&rsquo;s context window. Running a compiler or listing a massive directory might generate thousands of lines of output, pushing the agent&rsquo;s prompt size to its limit and rendering it unable to reason effectively.</p>
<p>To prevent this context bloat, <code>camp-shell</code> integrates with the <strong>Shell Sieve</strong>. If an agent attempts to run a verbose command like listing <code>/bin/</code>, the output is automatically truncated and sieved:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>$ ls /bin/
</span></span><span style="display:flex;"><span>--- <span style="color:#f92672">[</span>CAMP SHELL SIEVE: output truncated <span style="color:#66d9ef">for</span> context economy<span style="color:#f92672">]</span> ---
</span></span><span style="display:flex;"><span><span style="color:#e6db74">&#39;[&#39;</span>
</span></span><span style="display:flex;"><span> 411toppm
</span></span><span style="display:flex;"><span> 7z
</span></span><span style="display:flex;"><span> 7za
</span></span><span style="display:flex;"><span> 7zr
</span></span><span style="display:flex;"><span> ... <span style="color:#f92672">[</span><span style="color:#ae81ff">4926</span> lines hidden — <span style="color:#ae81ff">66824</span> bytes total<span style="color:#f92672">]</span> ...
</span></span><span style="display:flex;"><span> zipsplit
</span></span><span style="display:flex;"><span> zless
</span></span><span style="display:flex;"><span> zlib-flate
</span></span><span style="display:flex;"><span> zmore
</span></span><span style="display:flex;"><span> znew
</span></span><span style="display:flex;"><span> zrun
</span></span><span style="display:flex;"><span> zstd
</span></span><span style="display:flex;"><span>--- <span style="color:#f92672">[</span>FULL OUTPUT ARCHIVED: /home/rrs/.cache/camp/shell-artifacts/camp_cmd_2443e7d6add2c9fa.log <span style="color:#f92672">(</span><span style="color:#ae81ff">5026</span> lines, <span style="color:#ae81ff">66824</span> bytes<span style="color:#f92672">)]</span>
</span></span><span style="display:flex;"><span>    To read it WITHOUT re-flooding context <span style="color:#f92672">(</span>a plain <span style="color:#e6db74">`</span>cat<span style="color:#e6db74">`</span> is re-sieved<span style="color:#f92672">)</span>:
</span></span><span style="display:flex;"><span>      - a file-read/viewer tool on that path <span style="color:#f92672">(</span>bypasses the shell<span style="color:#f92672">)</span>, or
</span></span><span style="display:flex;"><span>      - small slices: sed -n <span style="color:#e6db74">&#39;120,160p&#39;</span> &lt;path&gt; ; grep -n PATTERN &lt;path&gt; ; head -c <span style="color:#ae81ff">4000</span> &lt;path&gt; ---
</span></span></code></pre></div><ul>
<li><strong>Context Hygiene:</strong> The agent only receives a high-signal overview of the first and last few lines (capping at 150 lines or 5,000 characters). The full, untruncated log is written directly to disk.</li>
<li><strong>On-Demand Inspection:</strong> If the agent needs to inspect a specific compiler error deep inside the output, it is instructed by <code>camp-shell</code> to bypass the terminal and read the specific slice of the archived file directly, preserving context capacity and reducing API token costs.</li>
</ul>
<hr>
<h2 id="4-local-first-forge-and-egress-default-off">4. Local-First Forge and Egress Default-Off</h2>
<p>Autonomy on the host is useless if every push still phones home to someone else&rsquo;s cloud. CAMP is <strong>local-first</strong>: each agent works against a <strong>local Gitea</strong> hub (<code>localhost:8095</code>). Mirroring <em>into</em> CAMP from upstream forges is open; <strong>egress back out</strong> (<code>git push</code> to GitLab/GitHub, <code>glab</code>/<code>gh</code> that would create remote MRs, and similar) is <strong>default-OFF</strong>.</p>
<p>The chokepoint is deliberate and boring on purpose:</p>
<ul>
<li>A <code>pre-push</code> hook (and matching forge CLI wrappers) allow pushes only to the local hub without ceremony.</li>
<li>Any other remote requires human intent: either a host-side capability token the sandbox cannot read, or a Zenity &ldquo;Allow push?&rdquo; dialog on a graphical session.</li>
<li>The token path is <strong>fixed</strong>, not env-overridable—agents once nearly gained a bypass when a test knobs made the path configurable; that class of hole is treated as a security regression, not a convenience feature.</li>
</ul>
<p>The result matches the dual-layer philosophy: agents remain free to branch, commit, and open pull requests <strong>locally</strong>; publishing outside the house stays a human act.</p>
<h3 id="the-pr-rail-humans-merge-agents-deliver">The PR rail (humans merge, agents deliver)</h3>
<p>Fleet rules are equally blunt about <em>who</em> may change production: <strong>agents open pull requests under their own identity; only the human merges canonical branches and deploys.</strong> There is no shared admin token for agents to &ldquo;just fix prod.&rdquo; That sounds bureaucratic until the first time an agent would otherwise have &ldquo;helpfully&rdquo; force-pushed a mainline branch at 2 a.m. Attribution, review, and deploy stay human-sovereign.</p>
<hr>
<h2 id="5-mempalace-attributed-long-term-vector-memory">5. MemPalace: Attributed Long-Term Vector Memory</h2>
<p>Rather than leaving agents to guess or make assumptions, we integrated <strong>MemPalace</strong>—a central, shared vector repository—into the heart of CAMP. The backend itself has evolved: MemPalace began on <code>ChromaDB</code>, but the entire fleet (11,000+ drawers across every agent wing) has since been migrated to <strong><code>pgvector</code> on PostgreSQL 18</strong>, giving us transactional guarantees, better concurrency under a shared fleet, and a single canonical store instead of per-agent SQLite files.</p>
<p>On wake-up, the agent does not start with a blank slate. It calls <code>mempalace_status</code> to load the current palace map and runs semantic queries on past session summaries. This allows the agent to pull down historical references, recall user preferences, and review past debugging decisions, eliminating context silos between separate runs.</p>
<p>Memory is written in <strong>AAAK</strong> (Attributed Agentic Association Keys)—a compressed, attributed dialect that stores dates, importance ratings (★ to ★★★★★), and agent attributions. Because writes come from a fleet of heterogeneous CLIs with no shared runtime, we did not build one monolithic &ldquo;memory service&rdquo;—we built a set of small, independently-scheduled tools that each own one failure mode:</p>
<ul>
<li><strong><code>camp-mempalace-miner</code> — the ingestion layer.</strong> This tool actually exists in two generations, still running side by side. The original per-agent hook miners (one per CLI family—Gemini, Copilot, Grok, the sandboxed pilot agents) are launched directly from each agent&rsquo;s own lifecycle hooks (<code>AfterAgent</code>, <code>PreCompress</code>/<code>PreCompact</code>, <code>SessionEnd</code>) as a detached subprocess, throttled to at most once per 30 minutes or 30 user turns. On top of that we added a <strong>central, timer-driven miner</strong>—a single <code>systemd --user</code> timer firing roughly every 9 minutes—that knows the on-disk transcript layout for <em>every</em> agent code in the fleet (e.g. Copilot&rsquo;s <code>~/.copilot/session-state/*/events.jsonl</code>, Grok&rsquo;s <code>~/.grok/sessions/**/updates.jsonl</code>, each Gemini persona&rsquo;s own <code>chats/</code> directory) and mines all of them into the <em>one</em> central palace, stamping every drawer with <code>agent_id</code> and <code>added_by=camp-central-miner</code>. This mattered in practice: sandboxed pilot agents running under <code>bwrap</code> were writing into a tmpfs overlay that evaporated on exit, so their memory silently never reached the host palace until the central miner started reading their transcripts directly instead of trusting their in-sandbox writes. Both generations share the same crash-safety plumbing—per-session byte-offset tracking, content-hash dedup, advisory file locks, and a <code>CAMP_DRY_RUN</code> mode for safe testing—so neither can double-file or corrupt state if it&rsquo;s killed mid-run.</li>
<li><strong><code>camp-mempalace-compactor</code> — hierarchical aging.</strong> A periodic job that finds <code>room_general</code> drawers older than 30 days, batches 10–15 raw snippets at a time, and asks a locally-hosted LLM to compress them into one dense AAAK summary block, keeping vector search signal-dense instead of drowning in verbatim history. We learned this the hard way: running the compactor&rsquo;s small maintenance model on the same GPU as the interactive 7B model caused it to crash under Vulkan device contention, so the maintenance model now runs CPU-only, a perfectly adequate trade-off for a background summarizer.</li>
<li><strong><code>camp-mempalace-fsck</code> — the integrity and semantic auditor.</strong> This single tool absorbed what we originally scoped as two separate ideas (a syntax &ldquo;validator&rdquo; and a consistency &ldquo;fsck&rdquo;), because in practice they&rsquo;re one audit pass. In its default, unattended mode it deep-scans the palace for broken invariants—missing <code>agent_id</code> attribution, null or malformed embeddings, incomplete document text—and auto-repairs whatever is safe to fix without judgment calls. Its <code>--attended</code> mode is the interesting one: it hands ambiguous, potentially mis-tagged drawers to a local LLM for reclassification, shows you its proposed room change, and waits for an explicit <code>Approve? [y/N/q]</code> before committing—keeping a human in the loop for anything that requires judgment rather than mechanical repair.</li>
</ul>
<p>Together, this trio is why the fleet&rsquo;s memory coverage doesn&rsquo;t depend on any single agent behaving well: even if a sandboxed pilot never runs its own hook miner correctly, the central miner will still find and file its transcripts on the next timer tick, and fsck will catch and repair anything that slips through mangled. A single gateway call, <code>report_miner_brief</code>, aggregates every agent&rsquo;s mining state (sessions mined, exchanges filed, pending backlog) into one fleet-wide status line—so verifying that <em>all</em> agents are actually being remembered is a one-shot check, not a per-agent archaeology dig.</p>
<p><strong>Diary sovereignty</strong> is non-negotiable: one agent does not read another&rsquo;s private diary without an explicit tunnel and permission. The shared palace holds fleet knowledge; private journals stay private by architecture, not by &ldquo;please don&rsquo;t look.&rdquo;</p>
<p>Vector recall alone isn&rsquo;t enough, though—embeddings can retrieve a <em>stale</em> fact just as confidently as a current one. So MemPalace also maintains an explicit <strong>Knowledge Graph</strong> (<code>mempalace_kg_add</code> / <code>mempalace_kg_invalidate</code> / <code>mempalace_kg_query</code>) for hard facts that change over time (a DSN, a service version, a person&rsquo;s role). When a fact changes, the old entry is explicitly invalidated rather than left to be out-competed by a newer, similarly-worded memory. The house rule we drilled into every agent: <em>before stating anything about a person, project, or past event, query the palace first—wrong is worse than slow.</em></p>
<hr>
<h2 id="6-mcp-one-syscall-table-for-a-heterogeneous-fleet">6. MCP: One Syscall Table for a Heterogeneous Fleet</h2>
<p>None of this architecture would be practical if every agent vendor insisted on its own custom integration dialect. Our fleet is genuinely heterogeneous: GitHub Copilot, Gemini CLI, Claude, and Grok each come with different native tool-calling schemas and different ideas of what a &ldquo;tool&rdquo; should be. The <strong>Model Context Protocol (MCP)</strong> is what makes CAMP&rsquo;s foundational services vendor-agnostic: every capability the fleet needs is exposed once, as an MCP server, and every agent—regardless of who built it—talks to the exact same tool surface.</p>
<p><code>camp_acp_gateway</code> is the flagship example: a single MCP server that fronts almost the entire CAMP foundation—</p>
<ul>
<li><strong>Memory</strong> (<code>mempalace_status</code>, <code>mempalace_search</code>, <code>mempalace_kg_*</code>, <code>mempalace_checkpoint</code>) — the palace operations covered above.</li>
<li><strong>Work tracking</strong> (<code>camp_issue_create</code>/<code>camp_issue_comment</code>/<code>camp_issue_update</code>, <code>camp_pr_create</code>/<code>camp_pr_merge</code>) — the shared Issue Tracker and PR workflow.</li>
<li><strong>Agent-to-agent coordination</strong> (<code>camp_a2a_propose_task</code>, <code>camp_a2a_send_message</code>, <code>camp_a2a_fetch_inbox</code>) — the passive A2A layer.</li>
<li><strong>Evidence and provenance</strong> (<code>forge_discover</code>, <code>forge_ledger</code>, <code>forge_onboard</code>) — the ingestion side that feeds PDP&rsquo;s work ledger from real Gitea/forge activity, keeping billable-hours accounting evidence-based rather than self-reported.</li>
<li><strong>Global policy and directives</strong> (<code>camp_global_directives</code>, <code>camp_policy_map</code>, <code>camp_policy_search</code>) — the fleet-wide rulebook every agent reads on wake-up, versioned like everything else.</li>
</ul>
<p>The effect is conceptually analogous to an OS syscall table: application code doesn&rsquo;t care whether it&rsquo;s running on one CPU family or another, because the interface layer presents one stable interface underneath. Here, an agent doesn&rsquo;t care if it&rsquo;s Copilot&rsquo;s tool-call schema or Gemini&rsquo;s function-calling format—<code>camp_acp_gateway</code> presents the same tools, the same argument shapes, and the same <code>agent_id</code>-stamped audit trail no matter which vendor is asking. That attribution is not incidental: every MCP call is tagged with the calling agent&rsquo;s code (<code>CPL</code>, <code>GRK</code>, <code>KIR</code>, …), so the same accountability the sandbox enforces at the shell layer is also enforced at the memory, task-tracking, and coordination layer. A rogue or buggy agent can&rsquo;t quietly bypass its own audit trail just because it happens to be a different vendor&rsquo;s CLI.</p>
<p>Discovery is uniform too: <code>camp_mcp_catalog</code> lets any agent enumerate what&rsquo;s actually available on the gateway at runtime, rather than hard-coding tool lists per agent—useful when the tool surface grows (as it regularly does) without every agent&rsquo;s configuration needing a synchronized update.</p>
<hr>
<h2 id="7-agent-isolation-and-the-a2a-horizon">7. Agent Isolation and the A2A Horizon</h2>
<p>In the CAMP architecture, each agent is treated as a unique, independent entity. Agents operate in isolated sandboxes with distinct workspaces and credentials. An agent cannot mutate another agent&rsquo;s repository or step on its toes without explicit permission.</p>
<p>Fleet behaviour is not left to tribal knowledge. A short <strong>constitution</strong>—<code>camp-directives.md</code>—is served verbatim to every agent on wake-up and on a standing cadence via <code>camp_global_directives</code>. Identity, memory, egress, shell routing, A2A, and tooling posture live there once; per-agent instruction files are only overlays (paths, runtime quirks), not forks of the rules.</p>
<p>Currently, cooperation is achieved through a <strong>passive A2A (Agent-to-Agent)</strong> mechanism:</p>
<ul>
<li>Agents send messages, task proposals, and status updates via <code>camp_acp_gateway</code>.</li>
<li>These tasks are queued and reviewed when a session is active or when the user acts as a mediator.</li>
<li>For anything longer-lived than a single session, the fleet leans on a <strong>shared CAMP Issue Tracker</strong> (Gitea-hosted, <code>camp_issue_create</code>/<code>camp_issue_comment</code>/<code>camp_issue_update</code>). Work items carry explicit dependency links—e.g. an issue implementing a forge adapter will note &ldquo;depends on #472 (contracts)&rdquo; and an agent picking it up can develop against the dependency&rsquo;s branch before it lands. Pull requests are reviewed and commented on across agents and the human, so a fix started by one agent in one session can be picked up, critiqued, and finished by a different agent (or the same one, days later) without losing any context—the issue <em>is</em> the context.</li>
</ul>
<h3 id="the-headless-limitation">The Headless Limitation</h3>
<p>While passive A2A works beautifully for structured handoffs, the current frontier of agentic design faces a key limitation: <strong>agents are not yet fully headless-capable</strong>. They depend on the active terminal session, browser loop, or prompt loop of the user to keep executing.</p>
<p>Because agents cannot run completely detached in the background as daemon processes, we cannot yet achieve <strong>active A2A communication</strong>—where a swarm of agents autonomously wakes up on a cron schedule, coordinates complex migrations in the background, resolves merge conflicts among themselves, and presents a completed PR in the morning without any active human terminal sessions. Overcoming this headless hurdle is the next major step in our roadmap.</p>
<hr>
<h2 id="8-the-local-first-promise-data-sovereignty">8. The Local-First Promise: Data Sovereignty</h2>
<p>Utter data sovereignty means keeping your memory, code, and execution local—and making cloud models <em>optional guests</em>, not landlords.</p>
<ul>
<li><strong>Local Gitea hub:</strong> Code, issues, and pull requests live on a machine you control. Agents are first-class forge users there; external forges are mirrors you choose to push, not the default workspace.</li>
<li><strong>Ollama (and friends):</strong> CAMP integrates with local LLM runtimes. We run models such as Qwen 2.5 7B, Gemma 2B, and Phi 3.5 Mini locally, accelerated by the laptop&rsquo;s iGPU (Vulkan). Maintenance models for memory compaction can run CPU-only so they do not thrash the interactive GPU session.</li>
<li><strong>Model-agnostic sovereignty:</strong> Because vector memory, local Gitea, and execution sandboxes are decoupled from any one vendor CLI, a new open-weights model or a new agent frontend is a plug-in—not a migration. Historical memory, access policies, and coding workflows stay put.</li>
</ul>
<hr>
<h2 id="conclusion-bridging-the-paradigm">Conclusion: Bridging the Paradigm</h2>
<p>By combining <strong>local LLM execution (Ollama)</strong>, <strong>dual-layer sandboxing (OuterWrap + Inner PEP via camp-shell / camp-acpd)</strong>, <strong>HITL rails (Zenity, fixed-path capability tokens, human-only merge/deploy)</strong>, <strong>egress default-off to a local Gitea hub</strong>, <strong>a vendor-agnostic MCP tool surface (<code>camp_acp_gateway</code>)</strong>, and <strong>automated memory maintenance (MemPalace suite)</strong>, we&rsquo;ve tried to experiment with what may potentially become the conceptual equivalent of an operating system kernel for the AI era.</p>
<p>The work is unfinished by design. Headless swarm coordination, runtime-directory default-deny (so the next secret is invisible without a deliberate allow-list), and further tightening of relaxed Inner PEP mounts remain open. The point of such a conceptual kernel is not to pretend agents are tame—it is to make every ambitious shortcut <em>auditable</em>, <em>attributable</em>, and <em>interruptible by a human</em>.</p>
<p>We no longer treat autonomous agents as unpredictable, untrusted black boxes. They are disciplined pair-programmers: free enough to do real engineering, bound enough that &ldquo;helpful&rdquo; does not become &ldquo;hostile,&rdquo; and sovereign enough that the house—not the cloud vendor—owns the ledger of what they did.</p>
<h3 id="video-demonstrations-camp-mempalace-memory-in-action">Video Demonstrations: CAMP MemPalace Memory in Action</h3>
<p>Below are three video demonstrations showing CAMP MemPalace memory integration in action across three different AI agent clients:</p>
<h4 id="antigravity-agent-client">Antigravity Agent Client</h4>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Wedde3W27Bk?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<h4 id="claude-agent-client">Claude Agent Client</h4>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/YwhgtVy9Wlw?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<h4 id="grok-build-agent-client">Grok-Build Agent Client</h4>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/bFebTwrCvRY?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

]]></content></entry><entry><title>Debian COSMIC: A Fast-Track System Extension &amp; Monorepo Packaging Journey</title><link href="https://researchut.com/blog/debian_cosmic_fast_track/" rel="alternate"/><id>https://researchut.com/blog/debian_cosmic_fast_track/</id><published>2026-07-29T00:00:00Z</published><updated>2026-07-29T00:00:00Z</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<p>System76’s <strong>COSMIC Desktop Environment</strong>—written from the ground up in Rust—is one of the most exciting developments in the Linux desktop ecosystem. Built for modern Wayland composition, modularity, and high-performance UX, it has captured the attention of desktop enthusiasts across distributions.</p>
<p>However, for users running <strong>Debian Testing</strong> or <strong>Debian Unstable</strong>, getting COSMIC onto their machines traditionally presents a steep hill to climb. The official upstream codebase consists of dozens of independent repositories (<code>cosmic-comp</code>, <code>cosmic-panel</code>, <code>cosmic-applets</code>, <code>cosmic-settings</code>, <code>cosmic-files</code>, and more) along with hundreds of Rust crate dependencies. Packaging each component individually according to strict Debian policy involves filing dozens of ITPs, waiting through NEW queue processing, and managing endless dependency updates.</p>]]></summary><content type="html"><![CDATA[<p>System76’s <strong>COSMIC Desktop Environment</strong>—written from the ground up in Rust—is one of the most exciting developments in the Linux desktop ecosystem. Built for modern Wayland composition, modularity, and high-performance UX, it has captured the attention of desktop enthusiasts across distributions.</p>
<p>However, for users running <strong>Debian Testing</strong> or <strong>Debian Unstable</strong>, getting COSMIC onto their machines traditionally presents a steep hill to climb. The official upstream codebase consists of dozens of independent repositories (<code>cosmic-comp</code>, <code>cosmic-panel</code>, <code>cosmic-applets</code>, <code>cosmic-settings</code>, <code>cosmic-files</code>, and more) along with hundreds of Rust crate dependencies. Packaging each component individually according to strict Debian policy involves filing dozens of ITPs, waiting through NEW queue processing, and managing endless dependency updates.</p>
<p>For someone who simply wants to explore, test, and run COSMIC on Debian <em>today</em>, waiting for full distribution packaging is impractical.</p>
<p>To bridge this gap, we created <strong>Debian COSMIC</strong> (<code>debian-cosmic</code>)—a pragmatic, fast-track delivery pipeline designed to build, package, and run COSMIC Epoch on Debian Testing and Sid right now.</p>
<hr>
<h2 id="the-fast-track-pivot-the-monorepo-strategy">The Fast-Track Pivot: The Monorepo Strategy</h2>
<p>Rather than fighting distribution policy or attempting to maintain fifty separate Debian source packages, we leveraged System76&rsquo;s official <strong><code>cosmic-epoch</code> monorepo</strong> releases (e.g. <code>epoch-1.4.0</code>).</p>
<p>By compiling the monorepo in an isolated, sanitized Debian Testing container/chroot, we build the entire COSMIC stack—compositor, panel, settings, launcher, applets, and session helpers—in a single, automated pass.</p>
<p>This approach gives us two primary delivery outcomes:</p>
<h3 id="1-the-monorepo-deb-cosmic-epoch-monorepodeb">1. The Monorepo <code>.deb</code> (<code>cosmic-epoch-monorepo.deb</code>)</h3>
<p>For users who prefer standard Debian package management:</p>
<ul>
<li>A single, unified <code>.deb</code> package containing the entire compiled <code>/usr</code> hierarchy of the COSMIC desktop environment.</li>
<li>Automatically versioned against upstream release tags (e.g. <code>1.4.0-1</code>) and published to our APT repository and GitHub Releases.</li>
<li>Easily installed via standard <code>apt install</code>:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo apt update
</span></span><span style="display:flex;"><span>sudo apt install cosmic-epoch-monorepo
</span></span></code></pre></div></li>
</ul>
<h3 id="2-the-system-extension-systemd-sysext-overlay">2. The System Extension (<code>systemd-sysext</code>) Overlay</h3>
<p>For users who embrace an immutable host philosophy or don&rsquo;t want external packages mutating their pristine host <code>/usr</code> filesystem:</p>
<ul>
<li>We package the compiled COSMIC stack into an OCI container image delivered via the GitHub Container Registry (<code>ghcr.io</code>).</li>
<li>Using <code>systemd-sysext</code>, the image is mounted at runtime as a read-only overlay on top of <code>/usr</code>.</li>
<li>When you log into COSMIC, the desktop environment is dynamically merged into your host. When you switch back to GNOME or KDE, a simple helper script (<code>cosmic-toggle</code>) unmerges the overlay, leaving your host filesystem 100% clean and untouched.</li>
</ul>
<hr>
<h2 id="-preventing-abi-drift-the-cosmic-canary-package">🛡️ Preventing ABI Drift: The <code>cosmic-canary</code> Package</h2>
<p>Running a <code>systemd-sysext</code> overlay on a rolling distribution like Debian Testing or Sid introduces a subtle technical challenge: <strong>host library ABI drift</strong>.</p>
<p>Because the sysext binaries link dynamically against shared C libraries on your host (such as Mesa graphics drivers, DRM, Vulkan, or Pipewire), a routine <code>apt upgrade</code> on your host might update <code>libgbm1</code> or <code>libdrm2</code> to a newer version. If the new host library introduces an ABI change, launching COSMIC from an older sysext overlay can cause black screens, broken rendering, or segfaults.</p>
<p>To solve this without cluttering standard Debian packaging, we created an &ldquo;Early Warning System&rdquo;: the <strong>JIT Canary (<code>cosmic-canary</code>) package</strong>.</p>
<h3 id="the-tiered-dependency-model">The Tiered Dependency Model</h3>
<p>Generated dynamically at build time using <code>equivs-build</code> (via our <code>generate-cosmic-canary.sh</code> tool), the <code>cosmic-canary</code> package pins your host&rsquo;s libraries into two distinct zones:</p>
<ul>
<li>🔴 <strong>The Strict Zone (<code>=</code> dependency):</strong> Pinned to the exact version used at build time for volatile graphics and hardware stack components (<code>libmesa</code>, <code>libgbm</code>, <code>libdrm</code>, <code>libvulkan</code>, <code>libdisplay-info</code>, <code>libpixman</code>, <code>libxkbcommon</code>, <code>libinput</code>, <code>libpipewire</code>). If a host <code>apt upgrade</code> attempts to bump Mesa or DRM versions, <code>cosmic-canary</code> blocks the upgrade, alerting you that a sysext rebuild is required before upgrading your host drivers.</li>
<li>🟢 <strong>The Relaxed Zone (<code>&gt;=</code> dependency):</strong> Pinned with minimum version bounds for stable system layers and protocol libraries (<code>libc6</code>, <code>libgcc</code>, <code>libstdc++</code>, <code>libwayland</code>, <code>libdbus</code>, <code>libpam</code>, <code>libglib</code>, <code>libssl</code>, <code>libx11</code>). Security updates and minor patches to these libraries are allowed through without triggering false alarms.</li>
</ul>
<hr>
<h2 id="quickstart-how-to-try-debian-cosmic">Quickstart: How to Try Debian COSMIC</h2>
<p>Whether you want the unified <code>.deb</code> or the <code>sysext</code> overlay, setting up Debian COSMIC takes only a few minutes.</p>
<h3 id="method-a-apt-repository-deb">Method A: APT Repository (.deb)</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># 1. Add the GPG key</span>
</span></span><span style="display:flex;"><span>sudo mkdir -p /etc/apt/keyrings
</span></span><span style="display:flex;"><span>curl -fsSL https://rickysarraf.github.io/debian-cosmic/debian-cosmic.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/debian-cosmic.gpg
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 2. Add the repository</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;deb [signed-by=/etc/apt/keyrings/debian-cosmic.gpg] https://rickysarraf.github.io/debian-cosmic/ unstable main&#34;</span> | sudo tee /etc/apt/sources.list.d/debian-cosmic.list
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># 3. Install COSMIC Monorepo</span>
</span></span><span style="display:flex;"><span>sudo apt update
</span></span><span style="display:flex;"><span>sudo apt install cosmic-epoch-monorepo
</span></span></code></pre></div><h3 id="method-b-system-extension-sysext">Method B: System Extension (<code>sysext</code>)</h3>
<p>If you have <code>systemd</code> &gt;= 248 and Docker installed:</p>
<ol>
<li>Clone the <code>debian-cosmic</code> repository:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git clone https://github.com/rickysarraf/debian-cosmic.git
</span></span><span style="display:flex;"><span>cd debian-cosmic
</span></span></code></pre></div></li>
<li>Pull and stage the latest sysext overlay:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>./bin/cosmic-update
</span></span></code></pre></div></li>
<li>Toggle the COSMIC environment on/off whenever you want:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>./bin/cosmic-toggle
</span></span></code></pre></div></li>
</ol>
<hr>
<h2 id="conclusion">Conclusion</h2>
<p><code>debian-cosmic</code> is not intended to replace official, long-term Debian packaging efforts. Instead, it is a <strong>fast-track, hacker-friendly playground</strong> for early adopters, developers, and testers who want to experience System76’s COSMIC Epoch on Debian Testing and Sid right now.</p>
<p>By combining monorepo container builds, <code>systemd-sysext</code> overlays, and <code>cosmic-canary</code> ABI safety checks, we have achieved a fast, clean, and reliable way to run cutting-edge desktop software on Debian without sacrificing system stability.</p>
<p><em>Check out the <a href="https://github.com/rickysarraf/debian-cosmic">debian-cosmic repository on GitHub</a> to contribute, report issues, or try out the latest build!</em></p>
]]></content></entry><entry><title>Immutable Debian</title><link href="https://researchut.com/blog/Immutable_Atomic_Debian/" rel="alternate"/><id>https://researchut.com/blog/Immutable_Atomic_Debian/</id><published>2025-12-20T00:00:00Z</published><updated>2025-12-20T00:00:00Z</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<h2 id="immutable-atomic-linux-distirbutions">Immutable Atomic Linux Distirbutions</h2>
<p>Of late, I&rsquo;ve been hearing a lot of (good) things about Immutable Linux
Distributions, from friends, colleagues and mentors. It has been
something on my plate for some time, to explore. But given the nature of
the subject, it has been delayed for a while. Reasons are simple; I can
only really judge this product if I use it for some time; and it has to
be on my primary daily driver machine.</p>]]></summary><content type="html"><![CDATA[<h2 id="immutable-atomic-linux-distirbutions">Immutable Atomic Linux Distirbutions</h2>
<p>Of late, I&rsquo;ve been hearing a lot of (good) things about Immutable Linux
Distributions, from friends, colleagues and mentors. It has been
something on my plate for some time, to explore. But given the nature of
the subject, it has been delayed for a while. Reasons are simple; I can
only really judge this product if I use it for some time; and it has to
be on my primary daily driver machine.</p>
<p>Personal life, this year, has been quite challenging as well. Thus it got pushed to until now.</p>
<h3 id="chrome-os">Chrome OS</h3>
<p>I&rsquo;ve realized that I&rsquo;ve been quite late to a lot of Linux parties.
Containers, Docker, Kubernetes, Golang, Rust, Immutable Linux and many
many more.</p>
<p>Late to the extent that I&rsquo;ve had a Chrome Book lying at home for many
months but never got to tinker with it at all.</p>
<p>Having used it for just around 2 weeks now, I can see what a great
product Google built with it. In short, this is exactly how a Linux
desktop integration should be. The GUI integration is just top notch.
There&rsquo;s consistency across all applications rendered on the Chrome OS</p>
<p>The integration of [X]Wayland and friends is equally good. Maybe Google
should consider opensourcing all those components. IIRC, exo,
sommelier, xwayland, ash and many more.</p>
<p>I was equally happy to see their <code>Linux Development Environment</code>
offering on supported hardware. While tightly integrated, it still
allows power users to tinker things around. I was quite impressed to see
nested containers in <code>crostini</code>. Job well done.</p>
<p>All of this explains why there&rsquo;s much buzz about <code>Immutable Atomic Linux Distributions</code> these days.</p>
<p>Then, there&rsquo;s the Android integration, which is just awesome in case you
care of it. Both <code>libndk</code> and <code>libhoudini</code> are well integrated and
nicely usable.</p>
<h3 id="immutable-linux-distributions">Immutable Linux Distributions</h3>
<p>This holiday season I wanted to find and spend some time catching up on
stuff I had been prolonging.</p>
<p>I chose to explore this subject while trying to remain in familiar
Debian land. So my first look was to see if there was any product
derived out of the Debian base.</p>
<p>That brought me to <code>Vanilla OS Orchid</code>. This is a fresh out of oven
project, recently switched to being based on Debian Sid. Previous
iteration used Ubuntu as the base.</p>
<p>Vanilla OS turned out to be quite good an experience. The stock
offering is created well enough to serve the general audience. And the
framework is such wonderfully structured that seasoned users can tinker
around with it, without much fuss.</p>
<p>Vanilla OS uses an A/B Partition model for how system updates are
rolled. At any point, when a new OTA update is pushed, it gets applied
to the inactive A/B partition. And it gets activated at next boot. If things
break, user has the option to switch to the previous state. Just the
usual set of expectations one would have with an immutable distribution.</p>
<p>What they&rsquo;ve done beautifully is:</p>
<ul>
<li>Integration Device Mapper LVM for A/B Partition</li>
<li>Linux Container OCI images to provison/flash A/B Paritions</li>
<li>Developed <code>abroot</code> utility for A/B Partition management</li>
<li>APX (Distrobox) integration for container workflows, with multiple Linux flavors</li>
<li>No <code>sudo</code>. Everything done via <code>pkexec</code></li>
</ul>
<p>But the most awesome thing I liked in Vanilla OS is <a href="https://github.com/rickysarraf/custom-image">custom images</a>. This allows power users to easily tinker with the developer workflow and generate new images, tailored for their specific use cases. All of this done levraging the GitHub/GitLab CI/CD workflows, which I think is just plain awesome. Given that payload is of the OCI format, the CICD workflow just generates new OCI images and publishes to a registry. And then the same is pulled to the client as an OTA.</p>
<p>Hats off to this small team/community for doing such nice integration
work, ultimately producing a superb Immutable Atomic Linux Distribution
based on the Debian base.</p>
<h3 id="immutable-linux">Immutable Linux</h3>
<p>My primary work machine has grown over the years, being on the rolling
Debian Testing/Unstable channel. And I don&rsquo;t much feel the itch ever to
format my (primary) machine so quick, no matter how great the counter
offer is.</p>
<p>So that got me wondering how to have some of bling of the immutable
world that I&rsquo;ve tasted (Thanks Chrome OS and Vanilla OS). With a fair
idea of what they offer in features, I drew a line to what I&rsquo;d want on
my primary machine.</p>
<ul>
<li>read-only rootfs</li>
<li>read-only /etc/</li>
</ul>
<p>This also kinda hardens my systems to an extent that I can&rsquo;t
accidentally cause catastrophic damage to it.</p>
<p>The feature I&rsquo;m letting go of is the A/B Partition (rpm-ostree for Fedora
land). While a good feature, having to integrate it into my current
machine is going to be very very challenging.</p>
<p>I actually feel that, the core assumption the Immutable Distros make,
that all hardware is going to <code>Just Work</code>, is flawed. While Linux has
substantially improved over the past years, there&rsquo;s still a hit/miss
when introducing very recent hardware.</p>
<p>Immutable Linux is targeted for the novice user, who won&rsquo;t accidentally
mess with the system. But what would the novice user do in case they
have issues with their recently purchased hardware, that they are
attempting to run (Immutable) Linux on.</p>
<h3 id="riteshs-immutable-debian">Ritesh&rsquo;s Immutable Debian</h3>
<p>With the premise set, on to sailing in immutable land.</p>
<p>There&rsquo;s another ground breaking innovation that has been happening;
which I think everyone is aware of. And may be using it as well, direct
or indirect.</p>
<p><em>Artificial Intelligence</em></p>
<p>While I&rsquo;ve only been a user for a couple of months as I draft this post,
I&rsquo;m now very much impressed with all this innovation. Being at the
consumer end has me appreciating it for what it has offered thus far.
And I haven&rsquo;t even scratched the surface. I&rsquo;m making attempts at
developing understanding of <em>Machine Learning</em> and <em>Artificial
Intelligence</em> but there&rsquo;s a looonnngg way to go still.</p>
<p>What I&rsquo;m appreciating the most is the availability of the AI Technology.
It has helped me be more efficient. And thus I get to use the gain
(time) with family.</p>
<p>To wrap, what I tailored my primary OS to, wouldn&rsquo;t have been possible
without assistance from AI.</p>
<p>With that, I disclaim that the rest of this article is primarily drafted
by my AI Companion. This is going to serve me as a reference for future,
when I forget about how all of this was structured.</p>
<h1 id="-system-architecture-immutable-debian-btrfs--mergerfs">🏗️ System Architecture: Immutable Debian (Btrfs + MergerFS)</h1>
<p>This system is a custom-hardened <strong>Immutable Workstation</strong> based on Debian Testing/Unstable. It utilizes native Btrfs properties and surgical VFS mounting to isolate the Operating System from persistent data.</p>
<h2 id="1-storage-strategy-subvolume-isolation">1. Storage Strategy: Subvolume Isolation</h2>
<p>The system resides on a LUKS-encrypted NVMe partition, using a flattened subvolume layout to separate the &ldquo;Gold Master&rdquo; OS from volatile and persistent data.</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Mount Point</th>
					<th style="text-align: left">Subvolume Path</th>
					<th style="text-align: left">State</th>
					<th style="text-align: left">Purpose</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><code>/</code></td>
					<td style="text-align: left"><code>/ROOTVOL</code></td>
					<td style="text-align: left"><strong>RO</strong></td>
					<td style="text-align: left">The core OS image.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>/etc</code></td>
					<td style="text-align: left"><code>/ROOTVOL/etc</code></td>
					<td style="text-align: left"><strong>RO</strong></td>
					<td style="text-align: left">System configuration (Snapshot-capable).</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>/home/rrs</code></td>
					<td style="text-align: left"><code>/ROOTVOL/home/rrs</code></td>
					<td style="text-align: left"><strong>RW</strong></td>
					<td style="text-align: left">User data and Kitty terminal configs.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>/var/lib</code></td>
					<td style="text-align: left"><code>/ROOTVOL/var/lib</code></td>
					<td style="text-align: left"><strong>RW</strong></td>
					<td style="text-align: left">Docker, Apt state, and system DBs.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>/var/spool</code></td>
					<td style="text-align: left"><code>/ROOTVOL/var/spool</code></td>
					<td style="text-align: left"><strong>RW</strong></td>
					<td style="text-align: left">Mail queues and service state.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>/swap</code></td>
					<td style="text-align: left"><code>/ROOTVOL/swap</code></td>
					<td style="text-align: left"><strong>RW</strong></td>
					<td style="text-align: left">Isolated path for No_COW Swapfile.</td>
			</tr>
			<tr>
					<td style="text-align: left"><code>/disk-tmp</code></td>
					<td style="text-align: left"><code>/ROOTVOL/disk-tmp</code></td>
					<td style="text-align: left"><strong>RW</strong></td>
					<td style="text-align: left">MergerFS overflow tier.</td>
			</tr>
	</tbody>
</table>
<h3 id="11-etcfstab">1.1 /etc/fstab</h3>
<pre tabindex="0"><code>❯ cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use &#39;blkid&#39; to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# &lt;file system&gt; &lt;mount point&gt;   &lt;type&gt;  &lt;options&gt;       &lt;dump&gt;  &lt;pass&gt;

# --- ROOT &amp; BOOT ---
/dev/mapper/nvme0n1p3_crypt  /  btrfs  autodefrag,compress=zstd,discard=async,noatime,defaults,ro  0  0
/dev/nvme0n1p2               /boot      ext4    defaults        0  2
/dev/nvme0n1p1               /boot/efi  vfat    umask=0077      0  1

# --- SWAP ---
# Mount the &#34;Portal&#34; to the swap subvolume using UUID (Robust)
UUID=4473b40b-bb46-43d6-b69c-ef17bfcac41c  /swap  btrfs  subvol=/ROOTVOL/swap,defaults,noatime  0  0

# Activate the swap file by path (Correct for files)
/swap/swapfile  none  swap  defaults  0  0

# --- DATA / MEDIA ---
UUID=439e297a-96a5-4f81-8b3a-24559839539d  /media/rrs/TOSHIBA  btrfs  noauto,compress=zstd,space_cache=v2,subvolid=5,subvol=/,user

# --- MERGERFS ---
# --- DISK-TMP (MergerFS Overflow Tier) ---
# Ensure this ID matches your actual disk-tmp subvolume
UUID=4473b40b-bb46-43d6-b69c-ef17bfcac41c  /disk-tmp  btrfs  subvolid=417,discard=async,defaults,noatime,compress=zstd  0  0
tmpfs               /ram-tmp   tmpfs          defaults  0  0
/ram-tmp:/disk-tmp  /tmp       fuse.mergerfs  x-systemd.requires=/ram-tmp,x-systemd.requires=/disk-tmp,defaults,allow_other,use_ino,nonempty,minfreespace=1G,category.create=all,moveonenospc=true  0  0

# --- IMMUTABILITY PERSISTENCE LAYERS ---
# We explicitly mount these subvolumes so they remain Writable later.
# UUID is the same as your /var/lib entry (your main Btrfs volume).

# 1. /var/lib (Docker, Apt state) - ID 50659
UUID=4473b40b-bb46-43d6-b69c-ef17bfcac41c  /var/lib    btrfs   subvolid=50659,discard=async,defaults,noatime,compress=zstd  0  0

# 2. /home/rrs (User Data) - ID 13032
UUID=4473b40b-bb46-43d6-b69c-ef17bfcac41c  /home/rrs   btrfs   subvolid=13032,discard=async,defaults,noatime,compress=zstd  0  0

# 3. /etc (System Config) - ID 13030
UUID=4473b40b-bb46-43d6-b69c-ef17bfcac41c  /etc        btrfs   subvolid=13030,discard=async,defaults,noatime,compress=zstd,ro  0  0

# 4. /var/log (Logs) - ID 406
UUID=4473b40b-bb46-43d6-b69c-ef17bfcac41c  /var/log    btrfs   subvolid=406,discard=async,defaults,noatime,compress=zstd    0  0

# 5. /var/cache (Apt Cache) - ID 409
UUID=4473b40b-bb46-43d6-b69c-ef17bfcac41c  /var/cache  btrfs   subvolid=409,discard=async,defaults,noatime,compress=zstd    0  0

# 6. /var/tmp (Temp files) - ID 401
UUID=4473b40b-bb46-43d6-b69c-ef17bfcac41c  /var/tmp    btrfs   subvolid=401,discard=async,defaults,noatime,compress=zstd    0  0

# /var/spool
UUID=4473b40b-bb46-43d6-b69c-ef17bfcac41c  /var/spool  btrfs  subvolid=50689,discard=async,defaults,noatime,compress=zstd  0  0
</code></pre><h2 id="2-tiered-memory-model-tmp">2. Tiered Memory Model (/tmp)</h2>
<p>To balance performance and capacity, <code>/tmp</code> is managed via <strong>MergerFS</strong>:</p>
<ul>
<li><strong>Tier 1 (RAM):</strong> <code>tmpfs</code> mounted at <code>/ram-tmp</code>.</li>
<li><strong>Tier 2 (Disk):</strong> Btrfs subvolume mounted at <code>/disk-tmp</code>.</li>
<li><strong>Logic:</strong> Files are written to RAM first. If RAM falls below 1GB available, files spill over to the Btrfs disk tier.</li>
</ul>
<h2 id="3-hibernation--swap-logic">3. Hibernation &amp; Swap Logic</h2>
<ul>
<li><strong>Size:</strong> 33 GiB (Configured for Suspend-to-Disk with 24GB RAM).</li>
<li><strong>Attribute:</strong> The <code>/swap</code> subvolume is marked <strong>No_COW (+C)</strong>.</li>
<li><strong>Kernel Integration:</strong>
<ul>
<li><code>resume=UUID=...</code> (Points to the unlocked LUKS container).</li>
<li><code>resume_offset=...</code> (Physical extent mapping for Btrfs).</li>
</ul>
</li>
</ul>
<h3 id="31-systemd-sleephibernation">3.1 systemd sleep/Hibernation</h3>
<pre tabindex="0"><code>❯ cat /etc/systemd/sleep.conf.d/sleep.conf
[Sleep]
HibernateDelaySec=12min
</code></pre><p>and</p>
<pre tabindex="0"><code>❯ cat /etc/systemd/logind.conf.d/logind.conf
[Login]
HandleLidSwitch=suspend-then-hibernate
HandlePowerKey=suspend-then-hibernate
HandleSuspendKey=suspend-then-hibernate
SleepOperation==suspend-then-hibernate
</code></pre><h2 id="4-immutability--safety-mechanisms">4. Immutability &amp; Safety Mechanisms</h2>
<p>The system state is governed by two key components:</p>
<h3 id="a-the-control-script-immutectl">A. The Control Script (<code>immutectl</code>)</h3>
<p>Handles the state transition by flipping Btrfs properties and VFS mount flags in the correct order.</p>
<ul>
<li><code>sudo immutectl unlock</code>: Sets <code>ro=false</code> and remounts <code>rw</code>.</li>
<li><code>sudo immutectl lock</code>: Sets <code>ro=true</code> and remounts <code>ro</code>.</li>
</ul>
<pre tabindex="0"><code>❯ cat /usr/local/bin/immutectl
#!/bin/bash

# Ensure script is run as root
if [[ $EUID -ne 0 ]]; then
   echo &#34;This script must be run as root (sudo).&#34;
   exit 1
fi

ACTION=$1

case $ACTION in
    unlock)
        echo &#34;🔓 Unlocking / and /etc for maintenance...&#34;

        # 1. First, tell the Kernel to allow writes to the mount point
        mount -o remount,rw /
        mount -o remount,rw /etc
        
        # 2. Now that the VFS is RW, Btrfs will allow you to change the property
        btrfs property set / ro false
        btrfs property set /etc ro false

        echo &#34;Status: System is now READ-WRITE.&#34;
        ;;
    lock)
        echo &#34;🔒 Locking / and /etc (Immutable Mode)...&#34;
        sync

        btrfs property set / ro true
        btrfs property set /etc ro true

        # We still attempt remount, but we ignore failure since Property is the Hard Lock
        mount -o remount,ro / 2&gt;/dev/null
        mount -o remount,ro /etc 2&gt;/dev/null

        echo &#34;Status: System is now READ-ONLY (Btrfs Property Set).&#34;
        ;;
    status)
        echo &#34;--- System Immutability Status ---&#34;
        
        for dir in &#34;/&#34; &#34;/etc&#34;; do
            # Get VFS state
            VFS_STATE=$(grep &#34; $dir &#34; /proc/mounts | awk &#39;{print $4}&#39; | cut -d, -f1)
            
            # Get Btrfs Property state
            BTRFS_PROP=$(btrfs property get &#34;$dir&#34; ro | cut -d= -f2)
            
            # Determine overall health
            if [[ &#34;$BTRFS_PROP&#34; == &#34;true&#34; ]]; then
                FINAL_STATUS=&#34;LOCKED (RO)&#34;
            else
                FINAL_STATUS=&#34;UNLOCKED (RW)&#34;
            fi

            echo &#34;Path: $dir&#34;
            echo &#34;  - VFS Layer (Mount): $VFS_STATE&#34;
            echo &#34;  - Btrfs Property:    ro=$BTRFS_PROP&#34;
            echo &#34;  - Effective State:   $FINAL_STATUS&#34;
            
            # Check for mismatch (The &#34;Busy&#34; scenario)
            if [[ &#34;$VFS_STATE&#34; == &#34;rw&#34; &amp;&amp; &#34;$BTRFS_PROP&#34; == &#34;true&#34; ]]; then
                echo &#34;  ⚠️  NOTICE: VFS is RW but Btrfs is RO. System is effectively Immutable.&#34;
            fi
            echo &#34;&#34;
        done
        ;;
    *)
        echo &#34;Usage: $0 {lock|unlock|status}&#34;
        exit 1
        ;;
esac
</code></pre><h3 id="b-the-smart-seal-immutability-sealservice">B. The Smart Seal (<code>immutability-seal.service</code>)</h3>
<p>A systemd one-shot service that ensures the system is locked on boot.</p>
<ul>
<li><strong>Fail-safe:</strong> The service checks <code>/proc/cmdline</code> for the standalone word <code>rw</code>. If found (via GRUB manual override), the seal is aborted to allow emergency maintenance.</li>
</ul>
<pre tabindex="0"><code>❯ cat /etc/systemd/system/immutability-seal.service 
[Unit]
Description=Ensure Btrfs Immutable Properties are set on Boot (unless rw requested)
DefaultDependencies=no
After=systemd-remount-fs.service
Before=local-fs.target
# Don&#39;t run in emergency/rescue modes
#ConditionPathExists=!/run/systemd/seats/seat0

[Service]
Type=oneshot
# The robust check: exit if &#39;rw&#39; exists as a standalone word
ExecStartPre=/bin/sh -c &#39;! grep -qE &#34;\brw\b&#34; /proc/cmdline&#39;
ExecStartPre=mount -o remount,rw /
ExecStart=/usr/bin/btrfs property set / ro true
ExecStart=/usr/bin/btrfs property set /etc ro true
ExecStartPost=mount -o remount,ro /
RemainAfterExit=yes

[Install]
WantedBy=local-fs.target
</code></pre><h2 id="5-monitoring--maintenance">5. Monitoring &amp; Maintenance</h2>
<ul>
<li><strong>Nagging:</strong> A systemd user-timer runs <code>immutability-nag</code> every 15 minutes to notify the desktop session if the system is currently in an &ldquo;Unlocked&rdquo; state.</li>
<li><strong>Verification:</strong> Use <code>sudo immutectl status</code> to verify that both the VFS Layer and Btrfs Properties are in sync.</li>
</ul>
<h3 id="51-nagging">5.1 Nagging</h3>
<pre tabindex="0"><code>❯ cat ~/bin/immutability-nag 
#!/bin/bash
# Check Btrfs property
BTRFS_STATUS=$(btrfs property get / ro | cut -d= -f2)

if [[ &#34;$BTRFS_STATUS&#34; == &#34;false&#34; ]]; then
    # Use notify-send (Standard, fast, non-intrusive)
    notify-send -u critical -i security-low \
    &#34;🔓 System Unlocked&#34; \
    &#34;Root is currently WRITABLE. Run &#39;immutectl lock&#39; when finished.&#34;
fi
</code></pre><p>and</p>
<pre tabindex="0"><code>❯ usystemctl cat immutability-nag.service 
# /home/rrs/.config/systemd/user/immutability-nag.service
[Unit]
Description=Check Btrfs immutability and notify user
# Ensure it doesn&#39;t run before the graphical session is ready
After=graphical-session.target

[Service]
Type=oneshot
ExecStart=%h/bin/immutability-nag
# Standard environment for notify-send to find the DBus session
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%U/bus

[Install]
WantedBy=default.target

    ~                                                                                                                                                                   20:35:15 
❯ usystemctl cat immutability-nag.timer 
# /home/rrs/.config/systemd/user/immutability-nag.timer
[Unit]
Description=Check immutability every 15 mins

[Timer]
OnStartupSec=5min
OnUnitActiveSec=15min

[Install]
WantedBy=timers.target
</code></pre><p>And the resultant nag in action.


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/immutable-seal.jpeg');" >
      <img itemprop="thumbnail" src="/images/immutable-seal.jpeg" alt="Immutable Debian Nag"/>
    </div>
    <a href="/images/immutable-seal.jpeg" itemprop="contentUrl"></a>
      <figcaption><h4>Immutable Debian Nag</h4>
      </figcaption>
  </figure>
</div>
</p>
<h3 id="52-verification">5.2 Verification</h3>
<pre tabindex="0"><code>❯ sudo immutectl status
[sudo] password for rrs: 
--- System Immutability Status ---
Path: /
  - VFS Layer (Mount): rw
  - Btrfs Property:    ro=false
  - Effective State:   UNLOCKED (RW)

Path: /etc
  - VFS Layer (Mount): rw
  - Btrfs Property:    ro=false
  - Effective State:   UNLOCKED (RW)



    ~                                                                                                                                                                   21:14:08 
❯ sudo immutectl lock
🔒 Locking / and /etc (Immutable Mode)...
Status: System is now READ-ONLY (Btrfs Property Set).


    ~                                                                                                                                                                   21:14:15 
❯ sudo immutectl status
--- System Immutability Status ---
Path: /
  - VFS Layer (Mount): rw
  - Btrfs Property:    ro=true
  - Effective State:   LOCKED (RO)
  ⚠️  NOTICE: VFS is RW but Btrfs is RO. System is effectively Immutable.

Path: /etc
  - VFS Layer (Mount): rw
  - Btrfs Property:    ro=true
  - Effective State:   LOCKED (RO)
  ⚠️  NOTICE: VFS is RW but Btrfs is RO. System is effectively Immutable.
</code></pre><hr>
<p><strong>Date Configured:</strong> December 2025<br>
<strong>Philosophy:</strong> The OS is a diagnostic tool. If an application fails to write to a locked path, the application is the variable, not the system.</p>
<h2 id="wrap">Wrap</h2>
<p>Overall, I&rsquo;m very very happy with, the result of a day of working
together with AI. I wouldn&rsquo;t have gotten things done so quick in such
time if it wasn&rsquo;t around. Such great is this age of AI.</p>
]]></content></entry><entry><title>KDE PowerDevil Systemd Inhibit</title><link href="https://researchut.com/blog/KDE_PowerDevil_systemd_inhibitors/" rel="alternate"/><id>https://researchut.com/blog/KDE_PowerDevil_systemd_inhibitors/</id><published>2025-10-28T00:00:00Z</published><updated>2025-10-28T00:00:00Z</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<p>With KDE 6.5.0, PowerDevil has <del>broken</del> forced its own set of
suspend/hibernate inhibitors onto logind. And to my knowledge, there&rsquo;s no way to disable them.</p>
<link rel="stylesheet" href="/css/hugo-easy-gallery.css" />

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/powerdevil-logind-inhibitors.jpeg');" >
      <img itemprop="thumbnail" src="/images/powerdevil-logind-inhibitors.jpeg" alt="KDE PowerDevil Settings Window"/>
    </div>
    <a href="/images/powerdevil-logind-inhibitors.jpeg" itemprop="contentUrl"></a>
  </figure>
</div>

<p>As a user, I&rsquo;d prefer to set lid action as <code>Do nothing</code> and really
expect KDE/PowerDevil to do nothing in that regard.
But with KDE 6.5.0 PowerDevil forces those inhibitors whatsoever.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>❯ systemd-inhibit  --list
</span></span><span style="display:flex;"><span>WHO            UID  USER PID   COMM            WHAT                                                                       WHY                                                        &gt;
</span></span><span style="display:flex;"><span>ModemManager   <span style="color:#ae81ff">0</span>    root <span style="color:#ae81ff">3541</span>  ModemManager    sleep                                                                      ModemManager needs to reset devices                        &gt;
</span></span><span style="display:flex;"><span>NetworkManager <span style="color:#ae81ff">0</span>    root <span style="color:#ae81ff">3453</span>  NetworkManager  sleep                                                                      NetworkManager needs to turn off networks                  &gt;
</span></span><span style="display:flex;"><span>UPower         <span style="color:#ae81ff">0</span>    root <span style="color:#ae81ff">4342</span>  upowerd         sleep                                                                      Pause device polling                                       &gt;
</span></span><span style="display:flex;"><span>PowerDevil     <span style="color:#ae81ff">1000</span> rrs  <span style="color:#ae81ff">82735</span> org_kde_powerde handle-power-key:handle-suspend-key:handle-hibernate-key:handle-lid-switch KDE handles power events                                   &gt;
</span></span><span style="display:flex;"><span>Screen Locker  <span style="color:#ae81ff">1000</span> rrs  <span style="color:#ae81ff">4844</span>  kwin_wayland    sleep                                                                      Ensuring that the screen gets locked before going to sleep &gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span> inhibitors listed.
</span></span></code></pre></div><p>This essentially prohibits logind to act on the lid actions. And instead forces the user to depend on nothing else and other than PowerDevil. This assumes the wishful thought that PowerDevil is Solid.</p>]]></summary><content type="html"><![CDATA[<p>With KDE 6.5.0, PowerDevil has <del>broken</del> forced its own set of
suspend/hibernate inhibitors onto logind. And to my knowledge, there&rsquo;s no way to disable them.</p>
<link rel="stylesheet" href="/css/hugo-easy-gallery.css" />

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/powerdevil-logind-inhibitors.jpeg');" >
      <img itemprop="thumbnail" src="/images/powerdevil-logind-inhibitors.jpeg" alt="KDE PowerDevil Settings Window"/>
    </div>
    <a href="/images/powerdevil-logind-inhibitors.jpeg" itemprop="contentUrl"></a>
  </figure>
</div>

<p>As a user, I&rsquo;d prefer to set lid action as <code>Do nothing</code> and really
expect KDE/PowerDevil to do nothing in that regard.
But with KDE 6.5.0 PowerDevil forces those inhibitors whatsoever.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>❯ systemd-inhibit  --list
</span></span><span style="display:flex;"><span>WHO            UID  USER PID   COMM            WHAT                                                                       WHY                                                        &gt;
</span></span><span style="display:flex;"><span>ModemManager   <span style="color:#ae81ff">0</span>    root <span style="color:#ae81ff">3541</span>  ModemManager    sleep                                                                      ModemManager needs to reset devices                        &gt;
</span></span><span style="display:flex;"><span>NetworkManager <span style="color:#ae81ff">0</span>    root <span style="color:#ae81ff">3453</span>  NetworkManager  sleep                                                                      NetworkManager needs to turn off networks                  &gt;
</span></span><span style="display:flex;"><span>UPower         <span style="color:#ae81ff">0</span>    root <span style="color:#ae81ff">4342</span>  upowerd         sleep                                                                      Pause device polling                                       &gt;
</span></span><span style="display:flex;"><span>PowerDevil     <span style="color:#ae81ff">1000</span> rrs  <span style="color:#ae81ff">82735</span> org_kde_powerde handle-power-key:handle-suspend-key:handle-hibernate-key:handle-lid-switch KDE handles power events                                   &gt;
</span></span><span style="display:flex;"><span>Screen Locker  <span style="color:#ae81ff">1000</span> rrs  <span style="color:#ae81ff">4844</span>  kwin_wayland    sleep                                                                      Ensuring that the screen gets locked before going to sleep &gt;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span> inhibitors listed.
</span></span></code></pre></div><p>This essentially prohibits logind to act on the lid actions. And instead forces the user to depend on nothing else and other than PowerDevil. This assumes the wishful thought that PowerDevil is Solid.</p>
<p>I&rsquo;d love to continue using my suspend workflow via systemd&rsquo;s
<code>suspend-then-hibernate</code> target as it has been working reliably for years. And
it also allows me to customize the behavior as I see fit.</p>
<p>Of course, I do have the option to trigger <code>systemd suspend-then-hibernate</code> manually, every time, before closing the lid. But
computers and automation has spoilt things.</p>
<p>The quick workaround/fix is to delegate it to ACPI, on platforms that
support it. Thankfully all of x86 to my knowledge.</p>
<p>So, in ACPI actions I&rsquo;ve a new config set to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>❯ cat /etc/acpi/actions/lm_lid.sh
</span></span><span style="display:flex;"><span><span style="color:#75715e">#! /bin/sh</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>grep close /proc/acpi/button/lid/LID/state <span style="color:#f92672">&amp;&amp;</span> systemctl suspend-then-hibernate
</span></span></code></pre></div><p>And with that I can be back to reliably (and carelessly)
<code>suspend-then-hibernate</code> my laptop.</p>
]]></content></entry><entry><title>apt-offline 1.8.6</title><link href="https://researchut.com/blog/apt_offline_186/" rel="alternate"/><id>https://researchut.com/blog/apt_offline_186/</id><published>2025-02-26T18:56:04+05:30</published><updated>2025-02-26T18:56:04+05:30</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<h2 id="apt-offline-186">apt-offline 1.8.6</h2>
<p><em><strong>apt-offline</strong></em> version 1.8.6 was released almost 3 weeks ago on 08/February/2025</p>
<p>This release includes many bug fixes from community users.</p>
<ul>
<li>Error out if we cannot initialize the APT lock.
Thanks to Matthew Maslak</li>
<li>check for checksum and handle appropriately (#217)
Thanks to Dan Whitman (Github:kyp44)</li>
<li>Honor the &ndash;allow-unauthenticated option.
Thanks to João A (Github: Jonybat)</li>
<li>Retry when server reports 429 Too Many Requests occurs.
Thanks to Zoltan Kelemen (Github: misterzed88)</li>
<li>Also support file:/// url types.
Thanks to c4bhuf@github</li>
<li>Honor user specified extra gpg keyrings</li>
</ul>
<h3 id="changelog">Changelog</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>apt-offline (1.8.6-1) unstable; urgency=medium
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  * Error out if we cannot initialize the APT lock.
</span></span><span style="display:flex;"><span>    Thanks to Matthew Maslak
</span></span><span style="display:flex;"><span>  * check for checksum and handle appropriately (#217)
</span></span><span style="display:flex;"><span>    Thanks to Dan Whitman (Github:kyp44)
</span></span><span style="display:flex;"><span>  * Honor the --allow-unauthenticated option.
</span></span><span style="display:flex;"><span>    Thanks to João A (Github: Jonybat)
</span></span><span style="display:flex;"><span>  * Retry when server reports 429 Too Many Requests occurs.
</span></span><span style="display:flex;"><span>    Thanks to Zoltan Kelemen (Github: misterzed88)
</span></span><span style="display:flex;"><span>  * Also support file:/// url types.
</span></span><span style="display:flex;"><span>    Thanks to c4bhuf@github
</span></span><span style="display:flex;"><span>  * Honor user specified extra gpg keyrings
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> -- Ritesh Raj Sarraf &lt;rrs@debian.org&gt;  Sat, 08 Feb 2025 20:46:24 +0530
</span></span></code></pre></div><h3 id="resources">Resources</h3>
<ul>
<li>Tarball and Zip archive for <em><strong>apt-offline</strong></em> are available <a href="https://github.com/rickysarraf/apt-offline/releases/tag/v1.8.6">here</a></li>
<li>Packages should be <a href="https://packages.debian.org/apt-offline">available</a> in Debian.</li>
<li>Development for <em><strong>apt-offline</strong></em> is currently hosted <a href="https://github.com/rickysarraf/apt-offline">here</a></li>
</ul>]]></summary><content type="html"><![CDATA[<h2 id="apt-offline-186">apt-offline 1.8.6</h2>
<p><em><strong>apt-offline</strong></em> version 1.8.6 was released almost 3 weeks ago on 08/February/2025</p>
<p>This release includes many bug fixes from community users.</p>
<ul>
<li>Error out if we cannot initialize the APT lock.
Thanks to Matthew Maslak</li>
<li>check for checksum and handle appropriately (#217)
Thanks to Dan Whitman (Github:kyp44)</li>
<li>Honor the &ndash;allow-unauthenticated option.
Thanks to João A (Github: Jonybat)</li>
<li>Retry when server reports 429 Too Many Requests occurs.
Thanks to Zoltan Kelemen (Github: misterzed88)</li>
<li>Also support file:/// url types.
Thanks to c4bhuf@github</li>
<li>Honor user specified extra gpg keyrings</li>
</ul>
<h3 id="changelog">Changelog</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>apt-offline (1.8.6-1) unstable; urgency=medium
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  * Error out if we cannot initialize the APT lock.
</span></span><span style="display:flex;"><span>    Thanks to Matthew Maslak
</span></span><span style="display:flex;"><span>  * check for checksum and handle appropriately (#217)
</span></span><span style="display:flex;"><span>    Thanks to Dan Whitman (Github:kyp44)
</span></span><span style="display:flex;"><span>  * Honor the --allow-unauthenticated option.
</span></span><span style="display:flex;"><span>    Thanks to João A (Github: Jonybat)
</span></span><span style="display:flex;"><span>  * Retry when server reports 429 Too Many Requests occurs.
</span></span><span style="display:flex;"><span>    Thanks to Zoltan Kelemen (Github: misterzed88)
</span></span><span style="display:flex;"><span>  * Also support file:/// url types.
</span></span><span style="display:flex;"><span>    Thanks to c4bhuf@github
</span></span><span style="display:flex;"><span>  * Honor user specified extra gpg keyrings
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> -- Ritesh Raj Sarraf &lt;rrs@debian.org&gt;  Sat, 08 Feb 2025 20:46:24 +0530
</span></span></code></pre></div><h3 id="resources">Resources</h3>
<ul>
<li>Tarball and Zip archive for <em><strong>apt-offline</strong></em> are available <a href="https://github.com/rickysarraf/apt-offline/releases/tag/v1.8.6">here</a></li>
<li>Packages should be <a href="https://packages.debian.org/apt-offline">available</a> in Debian.</li>
<li>Development for <em><strong>apt-offline</strong></em> is currently hosted <a href="https://github.com/rickysarraf/apt-offline">here</a></li>
</ul>
]]></content></entry><entry><title>Nepenthes</title><link href="https://researchut.com/blog/Nepenthes/" rel="alternate"/><id>https://researchut.com/blog/Nepenthes/</id><published>2022-07-21T08:46:56+05:30</published><updated>2022-07-21T08:46:56+05:30</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<p>Of the many things we care for in our garden, having some <em>Carnivorous plants</em> was also one to have.</p>
<p>Plants are tricky. A lot of information they pass. And depending on where you are and what plants you are with, the results can vary. The <strong>Nepenthes</strong> family isn&rsquo;t native to where I live but I still wanted to have them. While not impossible, though a difficult task to bring up such species.</p>]]></summary><content type="html"><![CDATA[<p>Of the many things we care for in our garden, having some <em>Carnivorous plants</em> was also one to have.</p>
<p>Plants are tricky. A lot of information they pass. And depending on where you are and what plants you are with, the results can vary. The <strong>Nepenthes</strong> family isn&rsquo;t native to where I live but I still wanted to have them. While not impossible, though a difficult task to bring up such species.</p>
<p>So plants are tricky; tricky because they are saying things all the time; but all you need to decode those signals is <em>time and patience</em>, to closely observe to what they exhibit and then try to relate.</p>
<p>Thankfully the Nepenthes have pitchered well.</p>
<link rel="stylesheet" href="/css/hugo-easy-gallery.css" />

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/Nepenthes/IMG_2022-01-08-12-39-36-109-thumb.jpg');" >
      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_2022-01-08-12-39-36-109-thumb.jpg" alt="/images/Nepenthes/IMG_2022-01-08-12-39-36-109-thumb.jpg"/>
    </div>
    <a href="/images/Nepenthes/IMG_2022-01-08-12-39-36-109.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>First Nepenthes</h4>
      </figcaption>
  </figure>
</div>

<p>My very first attempt resulted in a failure. Now that I&rsquo;ve been able to grow a young plant to have it fruit many pitchers, I conclude that the first plant I got was an unhealthy one. The same does reflect in the picture that I took.</p>


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/Nepenthes/IMG_2022-01-22-11-06-55-479-thumb.jpg');" >
      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_2022-01-22-11-06-55-479-thumb.jpg" alt="/images/Nepenthes/IMG_2022-01-22-11-06-55-479-thumb.jpg"/>
    </div>
    <a href="/images/Nepenthes/IMG_2022-01-22-11-06-55-479.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Second Nepenthes</h4>
      </figcaption>
  </figure>
</div>

<p>This was the second attempt with a different one. Thankfully, this one has prospered. The pitchers that follow are all from this plant.</p>
<h2 id="nepenthes">Nepenthes</h2>
<p>It is a tropical pitcher plant found in the rain forests. Caring for them can be very very tricky.</p>
<p>The below pictures/videos are in order, as and when they developed.</p>

<div class="gallery caption-position-bottom caption-effect-slide hover-effect-zoom hover-transition" itemscope itemtype="http://schema.org/ImageGallery">
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/IMG_2022-01-08-12-39-36-109-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_2022-01-08-12-39-36-109-thumb.jpg" alt="Img 2022 01 08 12 39 36 109" />
				    </div>
			      <figcaption>
		          <p>Img 2022 01 08 12 39 36 109</p>
			      </figcaption>
				    <a href="/images/Nepenthes/IMG_2022-01-08-12-39-36-109.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/IMG_2022-01-22-11-06-55-479-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_2022-01-22-11-06-55-479-thumb.jpg" alt="Img 2022 01 22 11 06 55 479" />
				    </div>
			      <figcaption>
		          <p>Img 2022 01 22 11 06 55 479</p>
			      </figcaption>
				    <a href="/images/Nepenthes/IMG_2022-01-22-11-06-55-479.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/IMG_20220301_163415-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_20220301_163415-thumb.jpg" alt="Img 20220301 163415" />
				    </div>
			      <figcaption>
		          <p>Img 20220301 163415</p>
			      </figcaption>
				    <a href="/images/Nepenthes/IMG_20220301_163415.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/IMG_20220331_141742-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_20220331_141742-thumb.jpg" alt="Img 20220331 141742" />
				    </div>
			      <figcaption>
		          <p>Img 20220331 141742</p>
			      </figcaption>
				    <a href="/images/Nepenthes/IMG_20220331_141742.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/IMG_20220331_141756-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_20220331_141756-thumb.jpg" alt="Img 20220331 141756" />
				    </div>
			      <figcaption>
		          <p>Img 20220331 141756</p>
			      </figcaption>
				    <a href="/images/Nepenthes/IMG_20220331_141756.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/IMG_20220506_130907-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_20220506_130907-thumb.jpg" alt="Img 20220506 130907" />
				    </div>
			      <figcaption>
		          <p>Img 20220506 130907</p>
			      </figcaption>
				    <a href="/images/Nepenthes/IMG_20220506_130907.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/IMG_20220508_095237-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_20220508_095237-thumb.jpg" alt="Img 20220508 095237" />
				    </div>
			      <figcaption>
		          <p>Img 20220508 095237</p>
			      </figcaption>
				    <a href="/images/Nepenthes/IMG_20220508_095237.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/IMG_20220514_101246-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_20220514_101246-thumb.jpg" alt="Img 20220514 101246" />
				    </div>
			      <figcaption>
		          <p>Img 20220514 101246</p>
			      </figcaption>
				    <a href="/images/Nepenthes/IMG_20220514_101246.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/IMG_20220517_105302-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/IMG_20220517_105302-thumb.jpg" alt="Img 20220517 105302" />
				    </div>
			      <figcaption>
		          <p>Img 20220517 105302</p>
			      </figcaption>
				    <a href="/images/Nepenthes/IMG_20220517_105302.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220523_112608-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220523_112608-thumb.jpg" alt="Mvimg 20220523 112608" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220523 112608</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220523_112608.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220529_102407-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220529_102407-thumb.jpg" alt="Mvimg 20220529 102407" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220529 102407</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220529_102407.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220530_095758-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220530_095758-thumb.jpg" alt="Mvimg 20220530 095758" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220530 095758</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220530_095758.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220531_100202-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220531_100202-thumb.jpg" alt="Mvimg 20220531 100202" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220531 100202</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220531_100202.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220603_114627-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220603_114627-thumb.jpg" alt="Mvimg 20220603 114627" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220603 114627</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220603_114627.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220607_123033-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220607_123033-thumb.jpg" alt="Mvimg 20220607 123033" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220607 123033</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220607_123033.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220611_090629-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220611_090629-thumb.jpg" alt="Mvimg 20220611 090629" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220611 090629</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220611_090629.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220614_101959-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220614_101959-thumb.jpg" alt="Mvimg 20220614 101959" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220614 101959</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220614_101959.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220701_095004-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220701_095004-thumb.jpg" alt="Mvimg 20220701 095004" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220701 095004</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220701_095004.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220701_095023-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220701_095023-thumb.jpg" alt="Mvimg 20220701 095023" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220701 095023</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220701_095023.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/MVIMG_20220717_093153-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/MVIMG_20220717_093153-thumb.jpg" alt="Mvimg 20220717 093153" />
				    </div>
			      <figcaption>
		          <p>Mvimg 20220717 093153</p>
			      </figcaption>
				    <a href="/images/Nepenthes/MVIMG_20220717_093153.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220302_133509734-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220302_133509734-thumb.jpg" alt="Pxl 20220302 133509734" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220302 133509734</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220302_133509734.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220313_094230263-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220313_094230263-thumb.jpg" alt="Pxl 20220313 094230263" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220313 094230263</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220313_094230263.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220320_092722961-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220320_092722961-thumb.jpg" alt="Pxl 20220320 092722961" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220320 092722961</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220320_092722961.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220320_102332731.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220320_102332731.MP.jpg" alt="Pxl 20220320 102332731" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220320 102332731</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220320_102332731.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220321_111144250.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220321_111144250.MP.jpg" alt="Pxl 20220321 111144250" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220321 111144250</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220321_111144250.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220326_101006318-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220326_101006318-thumb.jpg" alt="Pxl 20220326 101006318" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220326 101006318</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220326_101006318.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220326_101017255-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220326_101017255-thumb.jpg" alt="Pxl 20220326 101017255" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220326 101017255</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220326_101017255.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220405_131648280-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220405_131648280-thumb.jpg" alt="Pxl 20220405 131648280" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220405 131648280</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220405_131648280.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220407_110213685-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220407_110213685-thumb.jpg" alt="Pxl 20220407 110213685" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220407 110213685</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220407_110213685.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220410_100455858.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220410_100455858.MP.jpg" alt="Pxl 20220410 100455858" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220410 100455858</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220410_100455858.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220411_130518098-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220411_130518098-thumb.jpg" alt="Pxl 20220411 130518098" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220411 130518098</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220411_130518098.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220412_101435088.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220412_101435088.MP.jpg" alt="Pxl 20220412 101435088" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220412 101435088</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220412_101435088.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220415_100546316-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220415_100546316-thumb.jpg" alt="Pxl 20220415 100546316" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220415 100546316</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220415_100546316.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220416_104426132-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220416_104426132-thumb.jpg" alt="Pxl 20220416 104426132" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220416 104426132</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220416_104426132.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220416_104539152-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220416_104539152-thumb.jpg" alt="Pxl 20220416 104539152" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220416 104539152</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220416_104539152.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220419_095927933-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220419_095927933-thumb.jpg" alt="Pxl 20220419 095927933" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220419 095927933</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220419_095927933.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220519_110740604.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220519_110740604.MP.jpg" alt="Pxl 20220519 110740604" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220519 110740604</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220519_110740604.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220520_112411873.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220520_112411873.MP.jpg" alt="Pxl 20220520 112411873" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220520 112411873</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220520_112411873.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220527_174948354-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220527_174948354-thumb.jpg" alt="Pxl 20220527 174948354" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220527 174948354</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220527_174948354.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220528_114902977-thumb.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220528_114902977-thumb.jpg" alt="Pxl 20220528 114902977" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220528 114902977</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220528_114902977.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220615_095929327.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220615_095929327.MP.jpg" alt="Pxl 20220615 095929327" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220615 095929327</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220615_095929327.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220615_095936325.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220615_095936325.MP.jpg" alt="Pxl 20220615 095936325" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220615 095936325</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220615_095936325.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220622_110204818.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220622_110204818.MP.jpg" alt="Pxl 20220622 110204818" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220622 110204818</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220622_110204818.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220704_100826627.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220704_100826627.MP.jpg" alt="Pxl 20220704 100826627" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220704 100826627</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220704_100826627.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220711_115044138.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220711_115044138.MP.jpg" alt="Pxl 20220711 115044138" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220711 115044138</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220711_115044138.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
				<div class="box">
				  <figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
				    <div class="img" style="background-image: url('/images/Nepenthes/PXL_20220711_115055352.MP.jpg');" >
				      <img itemprop="thumbnail" src="/images/Nepenthes/PXL_20220711_115055352.MP.jpg" alt="Pxl 20220711 115055352" />
				    </div>
			      <figcaption>
		          <p>Pxl 20220711 115055352</p>
			      </figcaption>
				    <a href="/images/Nepenthes/PXL_20220711_115055352.MP.jpg" itemprop="contentUrl"></a>
				  </figure>
				</div>
</div>

<h2 id="march-2022">March 2022</h2>
<p>The very first pitcher blooms</p>


<video width=50% height=auto controls> //autoplay off
<!-- <video width=100% controls autoplay> //autoplay on -->
    <source src="/images/Nepenthes/PXL_20220320_092726895.mp4_stripped.mp4" type="video/mp4">
    Your browser does not support the video tag.  
</video>


<h2 id="april-2022">April 2022</h2>
<p>The second pitcher</p>


<video width=50% height=auto controls> //autoplay off
<!-- <video width=100% controls autoplay> //autoplay on -->
    <source src="/images/Nepenthes/PXL_20220410_100505919.LS.mp4_stripped.mp4" type="video/mp4">
    Your browser does not support the video tag.  
</video>
<video width=50% height=auto controls> //autoplay off
<!-- <video width=100% controls autoplay> //autoplay on -->
    <source src="/images/Nepenthes/PXL_20220423_104419042.mp4_stripped.mp4" type="video/mp4">
    Your browser does not support the video tag.  
</video>


<h2 id="may-2022">May 2022</h2>
<p>Moar pitchers</p>


<video width=50% height=auto controls> //autoplay off
<!-- <video width=100% controls autoplay> //autoplay on -->
    <source src="/images/Nepenthes/VID_20220521_131917.mp4_stripped.mp4" type="video/mp4">
    Your browser does not support the video tag.  
</video>


<h2 id="june-2022">June 2022</h2>
<p>Pitchers, Pitchers&hellip;.</p>


<video width=50% height=auto controls> //autoplay off
<!-- <video width=100% controls autoplay> //autoplay on -->
    <source src="/images/Nepenthes/VID_20220611_090647.mp4_stripped.mp4" type="video/mp4">
    Your browser does not support the video tag.  
</video>


<h2 id="july-2022">July 2022</h2>
<p>Many more to follow&hellip;.</p>
<p>More on YouTube Playlist: <a href="https://youtube.com/playlist?list=PLWWn3IBEvP7GSMfseh5_jyUzoO9vAjELK">Nepenthes</a></p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/ExEdwC53K60?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<h2 id="pests">Pests</h2>
<p>Thankfully, so far, no pest problems have occurred. Possibly, because the usual pests are part of the diet.</p>
<h2 id="care-tips">Care Tips</h2>
<p>Bottom line is that you need to ensure your Nepenthes has the <em>Tropical Rain Forest</em> type habitat. Whatever it takes, build that.</p>
]]></content></entry><entry><title>Systemd Service Hang</title><link href="https://researchut.com/blog/Systemd_Service_Hang/" rel="alternate"/><id>https://researchut.com/blog/Systemd_Service_Hang/</id><published>2022-04-22T00:00:00Z</published><updated>2024-08-15T00:00:00Z</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<p>Finally, TIL, what can all be the reason for systemd services to hang indefinitely. The internet is flooded with numerous reports on this topic but no clear answers. So no more uselessly marked workarounds like: <code>systemctl daemon-reload</code> and <code>systemctl-daemon-reexec</code> for this scenario.</p>
<p>The scene would be something along the lines of:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>rrs         <span style="color:#ae81ff">6467</span>  0.0  0.0  <span style="color:#ae81ff">23088</span> <span style="color:#ae81ff">15852</span> pts/1    Ss   12:53   0:00  |   |   <span style="color:#ae81ff">\_</span> /bin/bash
</span></span><span style="display:flex;"><span>rrs        <span style="color:#ae81ff">11512</span>  0.0  0.0  <span style="color:#ae81ff">14876</span>  <span style="color:#ae81ff">4608</span> pts/1    S+   13:18   0:00  |   |   |   <span style="color:#ae81ff">\_</span> systemctl restart snapper-timeline.timer
</span></span><span style="display:flex;"><span>rrs        <span style="color:#ae81ff">11513</span>  0.0  0.0  <span style="color:#ae81ff">14984</span>  <span style="color:#ae81ff">3076</span> pts/1    S+   13:18   0:00  |   |   |       <span style="color:#ae81ff">\_</span> /bin/systemd-tty-ask-password-agent --watch
</span></span><span style="display:flex;"><span>rrs        <span style="color:#ae81ff">11514</span>  0.0  0.0 <span style="color:#ae81ff">234756</span>  <span style="color:#ae81ff">6752</span> pts/1    Sl+  13:18   0:00  |   |   |       <span style="color:#ae81ff">\_</span> /usr/bin/pkttyagent --notify-fd <span style="color:#ae81ff">5</span> --fallback
</span></span></code></pre></div><p>The <code>snapper-timeline</code> service is important to me and it not running for months is a complete failure. Disappointingly, commands like <code>systemctl --failed</code> do not report of this oddity. The overall system status is reported to be fine, which is completely incorrect.</p>]]></summary><content type="html"><![CDATA[<p>Finally, TIL, what can all be the reason for systemd services to hang indefinitely. The internet is flooded with numerous reports on this topic but no clear answers. So no more uselessly marked workarounds like: <code>systemctl daemon-reload</code> and <code>systemctl-daemon-reexec</code> for this scenario.</p>
<p>The scene would be something along the lines of:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>rrs         <span style="color:#ae81ff">6467</span>  0.0  0.0  <span style="color:#ae81ff">23088</span> <span style="color:#ae81ff">15852</span> pts/1    Ss   12:53   0:00  |   |   <span style="color:#ae81ff">\_</span> /bin/bash
</span></span><span style="display:flex;"><span>rrs        <span style="color:#ae81ff">11512</span>  0.0  0.0  <span style="color:#ae81ff">14876</span>  <span style="color:#ae81ff">4608</span> pts/1    S+   13:18   0:00  |   |   |   <span style="color:#ae81ff">\_</span> systemctl restart snapper-timeline.timer
</span></span><span style="display:flex;"><span>rrs        <span style="color:#ae81ff">11513</span>  0.0  0.0  <span style="color:#ae81ff">14984</span>  <span style="color:#ae81ff">3076</span> pts/1    S+   13:18   0:00  |   |   |       <span style="color:#ae81ff">\_</span> /bin/systemd-tty-ask-password-agent --watch
</span></span><span style="display:flex;"><span>rrs        <span style="color:#ae81ff">11514</span>  0.0  0.0 <span style="color:#ae81ff">234756</span>  <span style="color:#ae81ff">6752</span> pts/1    Sl+  13:18   0:00  |   |   |       <span style="color:#ae81ff">\_</span> /usr/bin/pkttyagent --notify-fd <span style="color:#ae81ff">5</span> --fallback
</span></span></code></pre></div><p>The <code>snapper-timeline</code> service is important to me and it not running for months is a complete failure. Disappointingly, commands like <code>systemctl --failed</code> do not report of this oddity. The overall system status is reported to be fine, which is completely incorrect.</p>
<p>Thankfully, a kind soul&rsquo;s <a href="https://github.com/NixOS/nixpkgs/issues/2584#issuecomment-42616675">comment</a> gave the hint. The problem is that you could be having certain services in <code>Activating</code> status, which thus blocks all other services; quietly. So much for the unnecessary fun.</p>
<p>Looking further, in my case, it was:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>rrs@priyasi:~$ systemctl list-jobs 
</span></span><span style="display:flex;"><span>JOB  UNIT                           TYPE  STATE  
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">81</span>   timers.target                  start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">85</span>   man-db.timer                   start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">88</span>   fstrim.timer                   start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">3832</span> snapper-timeline.service       start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">83</span>   snapper-timeline.timer         start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">39</span>   systemd-time-wait-sync.service start running
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">87</span>   logrotate.timer                start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">84</span>   debspawn-clear-caches.timer    start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">89</span>   plocate-updatedb.timer         start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">91</span>   dpkg-db-backup.timer           start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">93</span>   e2scrub_all.timer              start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">40</span>   time-sync.target               start waiting
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">86</span>   apt-listbugs.timer             start waiting
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">13</span> jobs listed.
</span></span><span style="display:flex;"><span>13:12 ♒ ॐ ♅ ♄ ⛢     ☺ 😄    
</span></span></code></pre></div><p>That was it. I knew the <code>systemd-timesyncd</code> service, in the past, had given me enough headaches. And so was it this time, just quietly doing it all again.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>rrs@priyasi:~$ systemctl status systemd-time-wait-sync.service
</span></span><span style="display:flex;"><span>● systemd-time-wait-sync.service - Wait Until Kernel Time Synchronized
</span></span><span style="display:flex;"><span>     Loaded: loaded <span style="color:#f92672">(</span>/lib/systemd/system/systemd-time-wait-sync.service; enabled; vendor preset&gt;
</span></span><span style="display:flex;"><span>     Active: activating <span style="color:#f92672">(</span>start<span style="color:#f92672">)</span> since Fri 2022-04-22 13:14:25 IST; 1min 38s ago
</span></span><span style="display:flex;"><span>       Docs: man:systemd-time-wait-sync.service<span style="color:#f92672">(</span>8<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>   Main PID: <span style="color:#ae81ff">11090</span> <span style="color:#f92672">(</span>systemd-time-wa<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>      Tasks: <span style="color:#ae81ff">1</span> <span style="color:#f92672">(</span>limit: 37051<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>     Memory: 836.0K
</span></span><span style="display:flex;"><span>        CPU: 7ms
</span></span><span style="display:flex;"><span>     CGroup: /system.slice/systemd-time-wait-sync.service
</span></span><span style="display:flex;"><span>             └─11090 /lib/systemd/systemd-time-wait-sync
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Apr <span style="color:#ae81ff">22</span> 13:14:25 priyasi systemd<span style="color:#f92672">[</span>1<span style="color:#f92672">]</span>: Starting Wait Until Kernel Time Synchronized...
</span></span><span style="display:flex;"><span>Apr <span style="color:#ae81ff">22</span> 13:14:25 priyasi systemd-time-wait-sync<span style="color:#f92672">[</span>11090<span style="color:#f92672">]</span>: adjtime state <span style="color:#ae81ff">5</span> status <span style="color:#ae81ff">40</span> time Fri 2022-&gt;
</span></span><span style="display:flex;"><span>13:16 ♒ ॐ ♅ ♄ ⛢      ☹ 😟<span style="color:#f92672">=</span>&gt; <span style="color:#ae81ff">3</span>  
</span></span></code></pre></div><p>Dear LazyWeb, anybody knows of why the <code>systemd-time-wait-sync</code> service would hang indefinitely? I&rsquo;ve had identical setups on many machines, in the same network, where others don&rsquo;t exhibit this problem.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>rrs@priyasi:~$ systemctl cat systemd-time-wait-sync.service
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>...snipped...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>Service<span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>Type<span style="color:#f92672">=</span>oneshot
</span></span><span style="display:flex;"><span>ExecStart<span style="color:#f92672">=</span>/lib/systemd/systemd-time-wait-sync
</span></span><span style="display:flex;"><span>TimeoutStartSec<span style="color:#f92672">=</span>infinity
</span></span><span style="display:flex;"><span>RemainAfterExit<span style="color:#f92672">=</span>yes
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">[</span>Install<span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>WantedBy<span style="color:#f92672">=</span>sysinit.target
</span></span></code></pre></div><p>The <code>TimeoutStartSec=infinity</code> is definitely an attribute that shouldn&rsquo;t be shipped in any system services. There are use cases for it but that should be left for local admins to explicitly decide. Hanging for <code>infinity</code> is not a desired behavior for a system service.</p>
<p>In figuring all this out, today I learnt the handy <code>systemctl list-jobs</code> command, which will give the list of active <code>running/blocked/waiting</code> jobs.</p>
<h2 id="update-2024-08-15">Update: 2024-08-15</h2>
<p>This week I finally found the cause of the issue. I have a bunch of bridge interfaces defined on my machine. And all of them, most of their time, would be <code>DOWN</code></p>
<pre tabindex="0"><code>
@ ip a
1: lo: &lt;LOOPBACK,UP,LOWER_UP&gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
2: withnet: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether XXXXXXXXXXXXXXXXX brd ff:ff:ff:ff:ff:ff
3: nonet: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether XXXXXXXXXXXXXXXXX brd ff:ff:ff:ff:ff:ff
4: tap0: &lt;NO-CARRIER,BROADCAST,MULTICAST,UP&gt; mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether XXXXXXXXXXXXXXXXX brd ff:ff:ff:ff:ff:ff
6: wlan0: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether XXXXXXXXXXXXXXXXX brd ff:ff:ff:ff:ff:ff
    inet 10.42.1.66/24 brd 10.42.1.255 scope global dynamic noprefixroute wlan0
       valid_lft 5325sec preferred_lft 5325sec
    inet6 fe80::9bc0:e362:7c9d:be7c/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
7: email-laptop: &lt;POINTOPOINT,NOARP,UP,LOWER_UP&gt; mtu 1280 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet XXXXXXXXXXXXXXXXX scope global noprefixroute email-laptop
       valid_lft forever preferred_lft forever
    inet6 XXXXXXXXXXXXXXXXX scope global noprefixroute 
       valid_lft forever preferred_lft forever
    inet6 XXXXXXXXXXXXXXXXXXXXXXXX/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
⛢ 13:55:21 rrs@priyasi ~/pu/researchut-hugo   researchut|+1…2
</code></pre><p>And as it stands, that is the cause of the problem.</p>
<p><code>systemd-timesyncd</code> would invoke an attempt to sync time for all the interfaces defined under <code>systemd-networkd</code>. And given the setup, that is bound to <del>fail</del> timeout; which is why I had added the  override against:</p>
<pre tabindex="0"><code>TimeoutStartSec=infinity
</code></pre><p>So, apparently, for every interface in <code>networkd</code>, it&rsquo;d attempt the ntp sync. It reports along the lines of:</p>
<pre tabindex="0"><code>Aug 15 13:24:06 priyasi systemd-timesyncd[1987]: Network configuration changed, trying to establish connection.
</code></pre><p>So I learnt this week, of the attribute to handle this:</p>
<pre tabindex="0"><code>@ cat sysbr0.network
[Match]
Name=withnet

[Network]
DHCPServer=yes
IPv4Forwarding=yes
IPv6Forwarding=yes
IPMasquerade=both
Address=192.168.1.1/24
LLMNR=yes

[Link]
RequiredForOnline=no

#[DHCPServer]
#DNS=192.168.1.1
</code></pre><p>With that, NTP time synchronization is back to what it should be. Precision synchronization of the system time.</p>
<pre tabindex="0"><code>ॐ 14:11:35 rrs@priyasi /etc/systemd/network  
@ timedatectl show
LocalRTC=no
CanNTP=yes
NTP=yes
NTPSynchronized=yes
TimeUSec=Thu 2024-08-15 14:12:45 IST
RTCTimeUSec=Thu 2024-08-15 14:12:45 IST
</code></pre>]]></content></entry><entry><title>Btrfs Subvol Fix</title><link href="https://researchut.com/blog/BTRFS_Subvol_Fix/" rel="alternate"/><id>https://researchut.com/blog/BTRFS_Subvol_Fix/</id><published>2022-04-20T22:41:53+05:30</published><updated>2022-04-20T22:41:53+05:30</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<p>There surely is need for better tooling on the BTRFS File System side.</p>
<p>While <a href="/blog/Thinkpad_AMD_Debian/">migrating</a> my setup from one machine to another, this is one issue I came to be aware of, only today, when my backup tool (<code>btrbk</code>) complained about it. Following the pointers, I see the below snippet in <code>btrfs-subvolume</code> manual page.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>       A snapshot that was created by send/receive will be read-only, with different last change generation, read-only and with set received_uuid which identifies the subvolume on the
</span></span><span style="display:flex;"><span>       filesystem that produced the stream. The usecase relies on matching data on both sides. Changing the subvolume to read-write after it has been received requires to reset the
</span></span><span style="display:flex;"><span>       received_uuid. As this is a notable change and could potentially break the incremental send use <span style="color:#66d9ef">case</span>, performing it by btrfs property set requires force <span style="color:#66d9ef">if</span> that is really desired by
</span></span><span style="display:flex;"><span>       user.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>           Note
</span></span><span style="display:flex;"><span>           The safety checks have been implemented in 5.14.2, any subvolumes previously received <span style="color:#f92672">(</span>with a valid received_uuid<span style="color:#f92672">)</span> and read-write status may exist and could still lead to
</span></span><span style="display:flex;"><span>           problems with send/receive. You can use btrfs subvolume show to identify them. Flipping the flags to read-only and back to read-write will reset the received_uuid manually. There
</span></span><span style="display:flex;"><span>           may exist a convenience tool in the future.
</span></span></code></pre></div><p>Fixing the <code>Received UUID: </code> flag meant running the below:</p>]]></summary><content type="html"><![CDATA[<p>There surely is need for better tooling on the BTRFS File System side.</p>
<p>While <a href="/blog/Thinkpad_AMD_Debian/">migrating</a> my setup from one machine to another, this is one issue I came to be aware of, only today, when my backup tool (<code>btrbk</code>) complained about it. Following the pointers, I see the below snippet in <code>btrfs-subvolume</code> manual page.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>       A snapshot that was created by send/receive will be read-only, with different last change generation, read-only and with set received_uuid which identifies the subvolume on the
</span></span><span style="display:flex;"><span>       filesystem that produced the stream. The usecase relies on matching data on both sides. Changing the subvolume to read-write after it has been received requires to reset the
</span></span><span style="display:flex;"><span>       received_uuid. As this is a notable change and could potentially break the incremental send use <span style="color:#66d9ef">case</span>, performing it by btrfs property set requires force <span style="color:#66d9ef">if</span> that is really desired by
</span></span><span style="display:flex;"><span>       user.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>           Note
</span></span><span style="display:flex;"><span>           The safety checks have been implemented in 5.14.2, any subvolumes previously received <span style="color:#f92672">(</span>with a valid received_uuid<span style="color:#f92672">)</span> and read-write status may exist and could still lead to
</span></span><span style="display:flex;"><span>           problems with send/receive. You can use btrfs subvolume show to identify them. Flipping the flags to read-only and back to read-write will reset the received_uuid manually. There
</span></span><span style="display:flex;"><span>           may exist a convenience tool in the future.
</span></span></code></pre></div><p>Fixing the <code>Received UUID: </code> flag meant running the below:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>rrs@priyasi:.../spool$ sudo btrfs sub show /
</span></span><span style="display:flex;"><span>WARNING: the subvolume is read-write and has received_uuid set,
</span></span><span style="display:flex;"><span>         don&#39;t use it for incremental send. Please see section
</span></span><span style="display:flex;"><span>         &#39;SUBVOLUME FLAGS&#39; in manual page btrfs-subvolume for
</span></span><span style="display:flex;"><span>         further information.
</span></span><span style="display:flex;"><span>ROOTVOL
</span></span><span style="display:flex;"><span>        Name:                   ROOTVOL
</span></span><span style="display:flex;"><span>        UUID:                   122b0de1-e6f2-6845-aba0-6bf766c16526
</span></span><span style="display:flex;"><span>        Parent UUID:            -
</span></span><span style="display:flex;"><span>        Received UUID:          34772967-c709-5146-bf20-898f7dbc2c1f
</span></span><span style="display:flex;"><span>        Creation time:          2021-12-02 19:59:29 +0530
</span></span><span style="display:flex;"><span>        Subvolume ID:           256
</span></span><span style="display:flex;"><span>        Generation:             138473
</span></span><span style="display:flex;"><span>        Gen at creation:        7
</span></span><span style="display:flex;"><span>        Parent ID:              5
</span></span><span style="display:flex;"><span>        Top level ID:           5
</span></span><span style="display:flex;"><span>        Flags:                  -
</span></span><span style="display:flex;"><span>        Send transid:           35245
</span></span><span style="display:flex;"><span>        Send time:              2021-12-02 19:59:29 +0530
</span></span><span style="display:flex;"><span>        Receive transid:        34
</span></span><span style="display:flex;"><span>        Receive time:           2021-12-02 20:13:11 +0530
</span></span><span style="display:flex;"><span>        Snapshot(s):
</span></span><span style="display:flex;"><span>                                ROOTVOL/.snapshots/1/snapshot
</span></span><span style="display:flex;"><span>                                ROOTVOL/.snapshots/2/snapshot
</span></span><span style="display:flex;"><span>22:40 ♒ ॐ ♅ ♄ ⛢     ☺ 😄    
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>rrs@priyasi:.../spool$ sudo btrfs property set / ro true
</span></span><span style="display:flex;"><span>WARNING: read-write subvolume with received_uuid, this is bad
</span></span><span style="display:flex;"><span>22:40 ♒ ॐ ♅ ♄ ⛢     ☺ 😄    
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>rrs@priyasi:.../spool$ sudo btrfs property set -f / ro false
</span></span><span style="display:flex;"><span>22:40 ♒ ॐ ♅ ♄ ⛢     ☺ 😄    
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>rrs@priyasi:.../spool$ sudo btrfs sub show /
</span></span><span style="display:flex;"><span>ROOTVOL
</span></span><span style="display:flex;"><span>        Name:                   ROOTVOL
</span></span><span style="display:flex;"><span>        UUID:                   122b0de1-e6f2-6845-aba0-6bf766c16526
</span></span><span style="display:flex;"><span>        Parent UUID:            -
</span></span><span style="display:flex;"><span>        Received UUID:          -
</span></span><span style="display:flex;"><span>        Creation time:          2021-12-02 19:59:29 +0530
</span></span><span style="display:flex;"><span>        Subvolume ID:           256
</span></span><span style="display:flex;"><span>        Generation:             138473
</span></span><span style="display:flex;"><span>        Gen at creation:        7
</span></span><span style="display:flex;"><span>        Parent ID:              5
</span></span><span style="display:flex;"><span>        Top level ID:           5
</span></span><span style="display:flex;"><span>        Flags:                  -
</span></span><span style="display:flex;"><span>        Send transid:           0
</span></span><span style="display:flex;"><span>        Send time:              2021-12-02 19:59:29 +0530
</span></span><span style="display:flex;"><span>        Receive transid:        138480
</span></span><span style="display:flex;"><span>        Receive time:           2022-04-20 22:40:43 +0530
</span></span><span style="display:flex;"><span>        Snapshot(s):
</span></span><span style="display:flex;"><span>                                ROOTVOL/.snapshots/1/snapshot
</span></span><span style="display:flex;"><span>                                ROOTVOL/.snapshots/2/snapshot
</span></span><span style="display:flex;"><span>22:40 ♒ ॐ ♅ ♄ ⛢     ☺ 😄    
</span></span></code></pre></div><p>Hoping there won&rsquo;t be surprises in the coming months. 🤞</p>
]]></content></entry><entry><title>apt-offline 1.8.4</title><link href="https://researchut.com/blog/apt_offline_184/" rel="alternate"/><id>https://researchut.com/blog/apt_offline_184/</id><published>2022-02-12T20:47:04+05:30</published><updated>2022-02-12T20:47:04+05:30</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<h2 id="apt-offline-184">apt-offline 1.8.4</h2>
<p><em><strong>apt-offline</strong></em> version 1.8.4 has been released.</p>
<p>This release includes many bug fixes but the important ones are:</p>
<ul>
<li>Better GPG signature handling</li>
<li>Support for verifying InRelease files</li>
</ul>
<h3 id="changelog">Changelog</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>apt-offline (1.8.4-1) unstable; urgency=medium
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [ Debian Janitor ]
</span></span><span style="display:flex;"><span>  * Update standards version to 4.5.0, no changes needed.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [ Paul Wise ]
</span></span><span style="display:flex;"><span>  * Clarify file type in unknown file message
</span></span><span style="display:flex;"><span>  * Fix typos
</span></span><span style="display:flex;"><span>  * Remove trailing whitespace
</span></span><span style="display:flex;"><span>  * Update LICENSE file to match official GNU version
</span></span><span style="display:flex;"><span>  * Complain when there are no valid keyrings instead of missing keyrings
</span></span><span style="display:flex;"><span>  * Make all syncrhronised files world readable
</span></span><span style="display:flex;"><span>  * Fix usage of indefinite articles
</span></span><span style="display:flex;"><span>  * Only show the APT Offline GUI once in the menu
</span></span><span style="display:flex;"><span>  * Update out of date URLs
</span></span><span style="display:flex;"><span>  * Fix date and whitespace issues in the manual page
</span></span><span style="display:flex;"><span>  * Replace stereotyping with an appropriate word
</span></span><span style="display:flex;"><span>  * Switch more Python shebangs to Python 3
</span></span><span style="display:flex;"><span>  * Correct usage of the /tmp/ directory
</span></span><span style="display:flex;"><span>  * Fix YAML files
</span></span><span style="display:flex;"><span>  * Fix usage of the log API
</span></span><span style="display:flex;"><span>  * Make the copying of changelog lines less brittle
</span></span><span style="display:flex;"><span>  * Do not split keyring paths on whitespace
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [ Ritesh Raj Sarraf ]
</span></span><span style="display:flex;"><span>  * Drop the redundant import of the apt module.
</span></span><span style="display:flex;"><span>    Thanks to github/dandelionred
</span></span><span style="display:flex;"><span>  * Fix deprecation of get_bugs() in debianbts
</span></span><span style="display:flex;"><span>  * Drop the unused IgnoredBugTypes
</span></span><span style="display:flex;"><span>  * Set encoding for files when opening
</span></span><span style="display:flex;"><span>  * Better error logging when apt fails
</span></span><span style="display:flex;"><span>  * Don&#39;t mandate a default option
</span></span><span style="display:flex;"><span>  * Demote metadata errors to verbose
</span></span><span style="display:flex;"><span>  * Also log an error message for every failed .deb url
</span></span><span style="display:flex;"><span>  * Check hard for the url type
</span></span><span style="display:flex;"><span>  * Check for ascii armored signature files.
</span></span><span style="display:flex;"><span>    Thanks to David Klnischkies
</span></span><span style="display:flex;"><span>  * Add MIME type for InRelease files
</span></span><span style="display:flex;"><span>  * Drop patch 0001-Drop-the-redundant-import-of-the-apt-module.patch.
</span></span><span style="display:flex;"><span>    Now part of the 1.8.4 release
</span></span><span style="display:flex;"><span>  * Prepare release 1.8.3
</span></span><span style="display:flex;"><span>  * Prepare release 1.8.4
</span></span><span style="display:flex;"><span>  * debian packaging
</span></span><span style="display:flex;"><span>    + Bump debhelper compatibility to 13
</span></span><span style="display:flex;"><span>    + Update install files
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [ Dean Anderson ]
</span></span><span style="display:flex;"><span>  * [#143] Added support for verifying InRelease files
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> -- Ritesh Raj Sarraf &lt;rrs@debian.org&gt;  Sat, 12 Feb 2022 18:52:58 +0530
</span></span></code></pre></div><h3 id="resources">Resources</h3>
<ul>
<li>Tarball and Zip archive for <em><strong>apt-offline</strong></em> are available <a href="https://github.com/rickysarraf/apt-offline/releases/tag/v1.8.4">here</a></li>
<li>Packages should be <a href="https://packages.debian.org/apt-offline">available</a> in Debian.</li>
<li>Development for <em><strong>apt-offline</strong></em> is currently hosted <a href="https://github.com/rickysarraf/apt-offline">here</a></li>
</ul>]]></summary><content type="html"><![CDATA[<h2 id="apt-offline-184">apt-offline 1.8.4</h2>
<p><em><strong>apt-offline</strong></em> version 1.8.4 has been released.</p>
<p>This release includes many bug fixes but the important ones are:</p>
<ul>
<li>Better GPG signature handling</li>
<li>Support for verifying InRelease files</li>
</ul>
<h3 id="changelog">Changelog</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>apt-offline (1.8.4-1) unstable; urgency=medium
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [ Debian Janitor ]
</span></span><span style="display:flex;"><span>  * Update standards version to 4.5.0, no changes needed.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [ Paul Wise ]
</span></span><span style="display:flex;"><span>  * Clarify file type in unknown file message
</span></span><span style="display:flex;"><span>  * Fix typos
</span></span><span style="display:flex;"><span>  * Remove trailing whitespace
</span></span><span style="display:flex;"><span>  * Update LICENSE file to match official GNU version
</span></span><span style="display:flex;"><span>  * Complain when there are no valid keyrings instead of missing keyrings
</span></span><span style="display:flex;"><span>  * Make all syncrhronised files world readable
</span></span><span style="display:flex;"><span>  * Fix usage of indefinite articles
</span></span><span style="display:flex;"><span>  * Only show the APT Offline GUI once in the menu
</span></span><span style="display:flex;"><span>  * Update out of date URLs
</span></span><span style="display:flex;"><span>  * Fix date and whitespace issues in the manual page
</span></span><span style="display:flex;"><span>  * Replace stereotyping with an appropriate word
</span></span><span style="display:flex;"><span>  * Switch more Python shebangs to Python 3
</span></span><span style="display:flex;"><span>  * Correct usage of the /tmp/ directory
</span></span><span style="display:flex;"><span>  * Fix YAML files
</span></span><span style="display:flex;"><span>  * Fix usage of the log API
</span></span><span style="display:flex;"><span>  * Make the copying of changelog lines less brittle
</span></span><span style="display:flex;"><span>  * Do not split keyring paths on whitespace
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [ Ritesh Raj Sarraf ]
</span></span><span style="display:flex;"><span>  * Drop the redundant import of the apt module.
</span></span><span style="display:flex;"><span>    Thanks to github/dandelionred
</span></span><span style="display:flex;"><span>  * Fix deprecation of get_bugs() in debianbts
</span></span><span style="display:flex;"><span>  * Drop the unused IgnoredBugTypes
</span></span><span style="display:flex;"><span>  * Set encoding for files when opening
</span></span><span style="display:flex;"><span>  * Better error logging when apt fails
</span></span><span style="display:flex;"><span>  * Don&#39;t mandate a default option
</span></span><span style="display:flex;"><span>  * Demote metadata errors to verbose
</span></span><span style="display:flex;"><span>  * Also log an error message for every failed .deb url
</span></span><span style="display:flex;"><span>  * Check hard for the url type
</span></span><span style="display:flex;"><span>  * Check for ascii armored signature files.
</span></span><span style="display:flex;"><span>    Thanks to David Klnischkies
</span></span><span style="display:flex;"><span>  * Add MIME type for InRelease files
</span></span><span style="display:flex;"><span>  * Drop patch 0001-Drop-the-redundant-import-of-the-apt-module.patch.
</span></span><span style="display:flex;"><span>    Now part of the 1.8.4 release
</span></span><span style="display:flex;"><span>  * Prepare release 1.8.3
</span></span><span style="display:flex;"><span>  * Prepare release 1.8.4
</span></span><span style="display:flex;"><span>  * debian packaging
</span></span><span style="display:flex;"><span>    + Bump debhelper compatibility to 13
</span></span><span style="display:flex;"><span>    + Update install files
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [ Dean Anderson ]
</span></span><span style="display:flex;"><span>  * [#143] Added support for verifying InRelease files
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> -- Ritesh Raj Sarraf &lt;rrs@debian.org&gt;  Sat, 12 Feb 2022 18:52:58 +0530
</span></span></code></pre></div><h3 id="resources">Resources</h3>
<ul>
<li>Tarball and Zip archive for <em><strong>apt-offline</strong></em> are available <a href="https://github.com/rickysarraf/apt-offline/releases/tag/v1.8.4">here</a></li>
<li>Packages should be <a href="https://packages.debian.org/apt-offline">available</a> in Debian.</li>
<li>Development for <em><strong>apt-offline</strong></em> is currently hosted <a href="https://github.com/rickysarraf/apt-offline">here</a></li>
</ul>
]]></content></entry><entry><title>ThinkPad AMD Debian</title><link href="https://researchut.com/blog/Thinkpad_AMD_Debian/" rel="alternate"/><id>https://researchut.com/blog/Thinkpad_AMD_Debian/</id><published>2022-01-11T19:37:24+05:30</published><updated>2022-01-11T19:37:24+05:30</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<p>After a hiatus of 6 years, it was nice to be back with the ThinkPad. This blog post briefly touches upon my impressions with the current generation ThinkPad T14 Gen2 AMD variant.</p>


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/ThinkPad_T14_Gen2_AMD.jpg');" >
      <img itemprop="thumbnail" src="/images/ThinkPad_T14_Gen2_AMD.jpg" alt="ThinkPad T14 Gen2 AMD"/>
    </div>
    <a href="/images/ThinkPad_T14_Gen2_AMD.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>ThinkPad T14 Gen2 AMD</h4>
      </figcaption>
  </figure>
</div>

<h3 id="lenovo">Lenovo</h3>
<p>It took 8 weeks to get my hands on the machine. Given the pandemic, restrictions and uncertainities, not sure if I should call it an ontime delivery. This was a CTO - Customise-to-order; so was nice to get rid of things I really didn&rsquo;t care/use much. On the other side, it also meant I could save on some power. It also came comparatively cheaper overall.</p>]]></summary><content type="html"><![CDATA[<p>After a hiatus of 6 years, it was nice to be back with the ThinkPad. This blog post briefly touches upon my impressions with the current generation ThinkPad T14 Gen2 AMD variant.</p>


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/ThinkPad_T14_Gen2_AMD.jpg');" >
      <img itemprop="thumbnail" src="/images/ThinkPad_T14_Gen2_AMD.jpg" alt="ThinkPad T14 Gen2 AMD"/>
    </div>
    <a href="/images/ThinkPad_T14_Gen2_AMD.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>ThinkPad T14 Gen2 AMD</h4>
      </figcaption>
  </figure>
</div>

<h3 id="lenovo">Lenovo</h3>
<p>It took 8 weeks to get my hands on the machine. Given the pandemic, restrictions and uncertainities, not sure if I should call it an ontime delivery. This was a CTO - Customise-to-order; so was nice to get rid of things I really didn&rsquo;t care/use much. On the other side, it also meant I could save on some power. It also came comparatively cheaper overall.</p>
<ul>
<li>No fingerprint reader</li>
<li>No Touch screen</li>
</ul>
<p>There&rsquo;s still parts where Lenovo could improve. Or less frustate a customer. I don&rsquo;t understand why a company would provide a full customization option on their portal, while at the same time, not provide an explicit option to choose the make/model of the hardware one wants. Lenovo deliberately chooses to not show/specify which WiFi adapter one could choose. So, as I suspected, I ended up with a <code>MEDIATEK Corp. Device 7961</code> wifi adapter.</p>
<h3 id="amd">AMD</h3>
<p>For the first time in my computing life, I&rsquo;m now using AMD at the core. I was pretty frustrated with annoying Intel Graphics bugs, so decided to take the plunge and give AMD/ATI a shot, knowing that the <code>radeon</code> driver does have decent support. So far, on the graphics side of things, I&rsquo;m glad that things look bright. The stock in-kernel radeon driver has been working perfect for my needs and I haven&rsquo;t had to tinker even once so far, in my 30 days of use.</p>
<p>On the overall system performance, I have not done any benchmarks nor do I want to do. But wholly, the system performance is smooth.</p>
<h3 id="powerthermal">Power/Thermal</h3>
<p>This is where things need more improvement on the AMD side. This AMD laptop terribly draws a lot of power in suspend mode. And it isn&rsquo;t just this machine, but also the previous T14 Gen1 which has similar problems. I&rsquo;m not sure if this is a generic ThinkPad problem, or an AMD specific problem. But coming from the Dell XPS 13 9370 Intel, this does draw a lot lot more power. So much, that I chose to use hibernation instead.</p>
<p>Similarly, on the thermal side, this machine doesn&rsquo;t cool down well as compared the the Dell XPS Intel one. On an idle machine, its temperature are comparatively higher. Looking at <code>powertop</code> reports, it does show to consume an average of 10 watts power even while idle.</p>
<p>I&rsquo;m hoping these are Linux ingeration issues and that Lenovo/AMD will improve things in the coming months. But given the user feedback on the ThinkPad T14 Gen1 thread, it may just be wishful thinking.</p>
<h3 id="linux">Linux</h3>
<p>The overall hardware support has been surprisingly decent. The MediaTek WiFi driver had some glitches but with Linux 5.15+, things have considerably improved. And I hope the trend will continue with forthcoming Linux releases. My previous device driver experience with MediaTek wasn&rsquo;t good but I took the plunge, considering that in the worst scenario I&rsquo;d have the option to swap the card.</p>
<p>There&rsquo;s a lot of marketing about Linux + Intel. But I took a jibe with Linux + AMD. There are glitches but nothing so far that has been a dealbreaker. If anything, I wish Lenovo/AMD would seriously work on the power/thermal issues.</p>
<h3 id="migration">Migration</h3>
<p>Other than what&rsquo;s mentioned above, I haven&rsquo;t had any serious issues. I may have had some rare occassional hangs but they&rsquo;ve been so infrequent that I haven&rsquo;t spent time to investigate those.</p>
<p>Upon receiving the machine, my biggest requirement was how to switch my current workstation from Dell XPS to Lenovo ThinkPad. I&rsquo;ve been using btrfs for some time now. And over the years, built my own practise on how to structure it. Things like, provisioning [sub]volumes, based on use cases is one thing I see. Like keeping separate subvols for: cache/temporary data, copy-on-write data , swap etc. I wish these things could be simplified; either on the btrfs tooling side or some different tool on top of it.</p>
<p>Below is filtered list of subvols created over years, that were worthy of moving to the new machine.</p>
<pre tabindex="0"><code>rrs@priyasi:~$ cat btrfs-volume-layout 
ID 550 gen 19166 top level 5 path home/foo/.cache
ID 552 gen 1522688 top level 5 path home/rrs
ID 553 gen 1522688 top level 552 path home/rrs/.cache
ID 555 gen 1426323 top level 552 path home/rrs/rrs-home/Libvirt-Images
ID 618 gen 1522672 top level 5 path var/spool/news
ID 634 gen 1522670 top level 5 path var/tmp
ID 635 gen 1522688 top level 5 path var/log
ID 639 gen 1522226 top level 5 path var/cache
ID 992 gen 1522670 top level 5 path disk-tmp
ID 1018 gen 1522688 top level 552 path home/rrs/NoBackup
ID 1196 gen 1522671 top level 5 path etc
ID 23721 gen 775692 top level 5 path swap
18:54 ♒ ॐ ♅ ♄ ⛢     ☺ 😄    
</code></pre><h4 id="btrfs-sendreceive">btrfs send/receive</h4>
<p>This did come in handy but I sorely missed some feature. Maybe they aren&rsquo;t there, or are there and I didn&rsquo;t look close enough. Over the years, different attributes were set to different subvols. Over time I forget what feature was added where. But from a migration point of view, it&rsquo;d be nice to say, &ldquo;Take this volume and take it with all its attributes&rdquo;. I didn&rsquo;t find that functionality in <code>send/receive</code>.</p>
<p>There&rsquo;s <code>get/set-property</code> which I noticed later but by then it was late. So some sort of tooling, ideally something like <code>btrfs migrate</code> or somesuch would be nicer.</p>
<p>In the file system world, we already have nice tools to take care of similar scenarios. Like with <code>rsync</code>, I can request it to carry all file attributes.</p>
<p>Also, iirc, <code>send/receive</code> works only on <code>ro</code> volumes. So there&rsquo;s more work one needs to do in:</p>
<ol>
<li>create ro vol</li>
<li>send</li>
<li>receive</li>
<li>don&rsquo;t forget to set rw property</li>
<li>And then somehow find out other properties set on each individual subvols and [re]apply the same on the destination</li>
</ol>
<p>I wish this all be condensed into a sub-command.</p>
<p>For my own sake, for this migration, the steps used were:</p>
<pre tabindex="0"><code>user@debian:~$ for volume in `sudo btrfs sub list /media/user/TOSHIBA/Migrate/ | cut -d &#39; &#39; -f9 | grep -v ROOTVOL | grep -v etc | grep -v btrbk`; do echo $volume; sud
o btrfs send /media/user/TOSHIBA/$volume | sudo btrfs receive /media/user/BTRFSROOT/ ; done            
Migrate/snapshot_disk-tmp
At subvol /media/user/TOSHIBA/Migrate/snapshot_disk-tmp
At subvol snapshot_disk-tmp
Migrate/snapshot-home_foo_.cache
At subvol /media/user/TOSHIBA/Migrate/snapshot-home_foo_.cache
At subvol snapshot-home_foo_.cache
Migrate/snapshot-home_rrs
At subvol /media/user/TOSHIBA/Migrate/snapshot-home_rrs
At subvol snapshot-home_rrs
Migrate/snapshot-home_rrs_.cache
At subvol /media/user/TOSHIBA/Migrate/snapshot-home_rrs_.cache
At subvol snapshot-home_rrs_.cache
ERROR: crc32 mismatch in command
Migrate/snapshot-home_rrs_rrs-home_Libvirt-Images
At subvol /media/user/TOSHIBA/Migrate/snapshot-home_rrs_rrs-home_Libvirt-Images
At subvol snapshot-home_rrs_rrs-home_Libvirt-Images
ERROR: crc32 mismatch in command
Migrate/snapshot-var_spool_news
At subvol /media/user/TOSHIBA/Migrate/snapshot-var_spool_news
At subvol snapshot-var_spool_news
Migrate/snapshot-var_lib_machines
At subvol /media/user/TOSHIBA/Migrate/snapshot-var_lib_machines
At subvol snapshot-var_lib_machines
Migrate/snapshot-var_lib_machines_DebianSidTemplate
..... snipped .....
</code></pre><p>And then, follow-up with:</p>
<pre tabindex="0"><code>user@debian:~$ for volume in `sudo btrfs sub list /media/user/BTRFSROOT/ | cut -d &#39; &#39; -f9`; do echo $volume; sudo btrfs property set -ts /media/user/BTRFSROOT/$volume ro false; done
ROOTVOL
ERROR: Could not open: No such file or directory
etc
snapshot_disk-tmp
snapshot-home_foo_.cache
snapshot-home_rrs
snapshot-var_spool_news
snapshot-var_lib_machines
snapshot-var_lib_machines_DebianSidTemplate
snapshot-var_lib_machines_DebSidArmhf
snapshot-var_lib_machines_DebianJessieTemplate
snapshot-var_tmp
snapshot-var_log
snapshot-var_cache
snapshot-disk-tmp
</code></pre><p>And then finally, renaming everything to match proper:</p>
<pre tabindex="0"><code>user@debian:/media/user/BTRFSROOT$ for x in snapshot*; do vol=$(echo $x | cut -d &#39;-&#39; -f2 | sed -e &#34;s|_|/|g&#34;); echo $x $vol; sudo mv $x $vol; done
snapshot-var_lib_machines var/lib/machines
snapshot-var_lib_machines_Apertisv2020ospackTargetARMHF var/lib/machines/Apertisv2020ospackTargetARMHF
snapshot-var_lib_machines_Apertisv2021ospackTargetARM64 var/lib/machines/Apertisv2021ospackTargetARM64
snapshot-var_lib_machines_Apertisv2022dev3ospackTargetARMHF var/lib/machines/Apertisv2022dev3ospackTargetARMHF
snapshot-var_lib_machines_BusterArm64 var/lib/machines/BusterArm64
snapshot-var_lib_machines_DebianBusterTemplate var/lib/machines/DebianBusterTemplate
snapshot-var_lib_machines_DebianJessieTemplate var/lib/machines/DebianJessieTemplate
snapshot-var_lib_machines_DebianSidTemplate var/lib/machines/DebianSidTemplate
snapshot-var_lib_machines_DebianSidTemplate_var_lib_portables var/lib/machines/DebianSidTemplate/var/lib/portables
snapshot-var_lib_machines_DebSidArm64 var/lib/machines/DebSidArm64
snapshot-var_lib_machines_DebSidArmhf var/lib/machines/DebSidArmhf
snapshot-var_lib_machines_DebSidMips var/lib/machines/DebSidMips
snapshot-var_lib_machines_JenkinsApertis var/lib/machines/JenkinsApertis
snapshot-var_lib_machines_v2019 var/lib/machines/v2019
snapshot-var_lib_machines_v2019LinuxSupport var/lib/machines/v2019LinuxSupport
snapshot-var_lib_machines_v2020 var/lib/machines/v2020
snapshot-var_lib_machines_v2021dev3Slim var/lib/machines/v2021dev3Slim
snapshot-var_lib_machines_v2021dev3SlimTarget var/lib/machines/v2021dev3SlimTarget
snapshot-var_lib_machines_v2022dev2OspackMinimal var/lib/machines/v2022dev2OspackMinimal
snapshot-var_lib_portables var/lib/portables
snapshot-var_log var/log
snapshot-var_spool_news var/spool/news
snapshot-var_tmp var/tmp
</code></pre><h4 id="snapper">snapper</h4>
<p>Entirely independent of this, but indirectly related. I use <code>snapper</code> as my snapshotting tool. It worked perfect on my previous machine. While everything got migrated, the only thing that fell apart was <code>snapper</code>. It just wouldn&rsquo;t start/run proper. Funny thing is that I just removed the snapper configs and reinitialized with the exact same config again, and voila snapper was happy.</p>
<h3 id="conclusion">Conclusion</h3>
<p>That was pretty much it. With the above and then also migrating <code>/boot</code> and then just chroot to install the boot loader. At some time, I&rsquo;d like to explore other boot options but given that that is such a non-essential task, it is low on the list.</p>
<p>The good part was that I booted into my new machine with my exact workstation setup as it was. All the way to the user cache and the desktop session. So it was nice on that part.</p>
<p>But I surely think there&rsquo;s room for a better migration experience here. If not directly as <code>btrfs migrate</code>, then maybe as an independent tool. The problem is that such a tool is going to be used once in years, so I didn&rsquo;t find the motivation to write one. But this surely would be a good use case for the distribution vendors.</p>
]]></content></entry><entry><title>Lotus to Lily</title><link href="https://researchut.com/blog/Lotus_To_Lily/" rel="alternate"/><id>https://researchut.com/blog/Lotus_To_Lily/</id><published>2021-10-09T21:52:30+05:30</published><updated>2021-10-16T22:46:30+05:30</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<h2 id="the-lotus-story-so-far">The Lotus story so far</h2>
<p>My <a href="/blog/Setting-Lotus-Pot/">very first experience</a> with <em>water flowering plants</em> was pretty good. I learnt a good deal of things; <em>from setting up the pond, germinating the lotus seeds, setting up the right soil, witnessing the growth of the lotus plant, fish eco-system to take care of the pond</em>. Overall, a lot of things learnt.</p>
<p>But I couldn&rsquo;t succeed in getting the Lotus flower. A lot many reasons. The granite container developed some leakage, which I had to fix by emptying it, which might have caused some shock to the lotus. But more than that, in my understanding, the reason for not being able to flower the lotus, was the amount of sunlight. From what I have learned, these plants need a minimum of 6-8 hrs of sunlight to really give you with the flowering result, whereas the setup of my pond was on the ground with hardly 3-4 hrs of sun. And that too, with all the plants growing, resulted in indirect sunlight.</p>]]></summary><content type="html"><![CDATA[<h2 id="the-lotus-story-so-far">The Lotus story so far</h2>
<p>My <a href="/blog/Setting-Lotus-Pot/">very first experience</a> with <em>water flowering plants</em> was pretty good. I learnt a good deal of things; <em>from setting up the pond, germinating the lotus seeds, setting up the right soil, witnessing the growth of the lotus plant, fish eco-system to take care of the pond</em>. Overall, a lot of things learnt.</p>
<p>But I couldn&rsquo;t succeed in getting the Lotus flower. A lot many reasons. The granite container developed some leakage, which I had to fix by emptying it, which might have caused some shock to the lotus. But more than that, in my understanding, the reason for not being able to flower the lotus, was the amount of sunlight. From what I have learned, these plants need a minimum of 6-8 hrs of sunlight to really give you with the flowering result, whereas the setup of my pond was on the ground with hardly 3-4 hrs of sun. And that too, with all the plants growing, resulted in indirect sunlight.</p>
<h3 id="lotus-to-lily">Lotus to Lily</h3>
<p>For my new setup, I chose a large oval container. And this one, I placed on my terrace, carefully choosing a spot where it&rsquo;d get 6-8 hrs of very bright sun on usual days. Other than that, the rest of the setup is pretty similar to my previous setup in the garden. Guppies, Solar Water Fountain etc.</p>
<link rel="stylesheet" href="/css/hugo-easy-gallery.css" />

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20211002_112805.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20211002_112805.jpg" alt="Initial lily pond setup"/>
    </div>
    <a href="/images/IMG_20211002_112805.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Initial lily pond setup</h4>
      </figcaption>
  </figure>
</div>

<p>The good thing about the terrace is that the setup gets ample amount of sun. You can see that in the picture above, with the amount of algae that has been formed. Something that is vital for the plant&rsquo;s ecosystem.</p>
<p>I must thank my wonderful neighbor who kindly shared a sapling from their lily plant. They already had had success with flowering the lily. So I had high hopes to see the day come when I&rsquo;d be happy to write down my experience in this blog post. Though, a lot of patience is needed. I got the lily some time in January this year. And it blossomed now, in October.</p>
<p>So, here&rsquo;s me sharing my happiness here, in particular order of how I documented the process.</p>


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20211004_091446.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20211004_091446.jpg" alt="Monday morning greeted with a blossomed lily"/>
    </div>
    <a href="/images/IMG_20211004_091446.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Monday morning greeted with a blossomed lily</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20211004_091633824.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20211004_091633824.jpg" alt="Lily Blossom Closeup"/>
    </div>
    <a href="/images/PXL_20211004_091633824.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Lily Blossom Closeup</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20211004_104702148.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20211004_104702148.jpg" alt="Beautiful water reflection"/>
    </div>
    <a href="/images/PXL_20211004_104702148.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Beautiful water reflection</h4>
      </figcaption>
  </figure>
</div>



<video width=100% controls> //autoplay off
<!-- <video width=100% controls autoplay> //autoplay on -->
    <source src="/images/PXL_20211004_091051622.mp4_stripped.mp4" type="video/mp4">
    Your browser does not support the video tag.  
</video>


<h3 id="dawn-to-dusk">Dawn to Dusk</h3>
<p>The other thing that I learned in this whole lily episode is that the flower goes back to sleeping at dusk. And back to flowering again at dawn. There&rsquo;s so much to learn in the surrounding, only if you spare some time to the little things with mother nature.</p>
<p>

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20211004_151712791.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20211004_151712791.jpg" alt="Lily status at dusk"/>
    </div>
    <a href="/images/PXL_20211004_151712791.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Lily status at dusk</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20211005_100011914.MP.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20211005_100011914.MP.jpg" alt="Lily the next day"/>
    </div>
    <a href="/images/PXL_20211005_100011914.MP.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Lily the next day</h4>
      </figcaption>
  </figure>
</div>
</p>
<p>Not sure how long this phenomenon is to last, but overall witnessing this whole process has been mesmerizing.</p>
<p>This past week has been great. 🙏🏼</p>
]]></content></entry><entry><title>Human Society</title><link href="https://researchut.com/blog/Human_Society/" rel="alternate"/><id>https://researchut.com/blog/Human_Society/</id><published>2021-10-03T16:24:21+05:30</published><updated>2021-10-03T16:24:21+05:30</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<p>In my past, I&rsquo;ve had experiences that have had me thinking. My experiences have been mostly in the South Asian Indian Sub-Continent, so may not be fair to generalize it.</p>
<ul>
<li>
<p>Help with finding a job: I&rsquo;ve learnt many times, that when people reach out asking for help, say, for helping them with finding a job; it isn&rsquo;t about you making a recommendation/referral for them. It, instead, implies that you are indirectly being asked to find and arrange them a job.</p>]]></summary><content type="html"><![CDATA[<p>In my past, I&rsquo;ve had experiences that have had me thinking. My experiences have been mostly in the South Asian Indian Sub-Continent, so may not be fair to generalize it.</p>
<ul>
<li>
<p>Help with finding a job: I&rsquo;ve learnt many times, that when people reach out asking for help, say, for helping them with finding a job; it isn&rsquo;t about you making a recommendation/referral for them. It, instead, implies that you are indirectly being asked to find and arrange them a job.</p>
</li>
<li>
<p>Gifts for people: My impression of offering a gift to someone is usually presenting them with something I&rsquo;ve found useful and dear to me. This is irrespective of whether the gift is a brand new unpacked item or a used (immaculate) one. On the contrary, many people define a gift as an item which is unpacked and one that comes with its sealed original packaging.</p>
</li>
</ul>
]]></content></entry><entry><title>Insect Camouflage Plant</title><link href="https://researchut.com/blog/Insect_Camouflage_Plant/" rel="alternate"/><id>https://researchut.com/blog/Insect_Camouflage_Plant/</id><published>2021-07-07T19:57:12+05:30</published><updated>2021-07-07T19:57:12+05:30</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html"><![CDATA[<p>I was quite impressed by the ability of this insect; yet to be. The way it has camouflaged itself is mesmerizing. I&rsquo;ll let the video do the talking as this one is going to be difficult to express in words.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/1YE_gYggKPA?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>]]></summary><content type="html"><![CDATA[<p>I was quite impressed by the ability of this insect; yet to be. The way it has camouflaged itself is mesmerizing. I&rsquo;ll let the video do the talking as this one is going to be difficult to express in words.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/1YE_gYggKPA?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

]]></content></entry><entry><title>Plant Territorial Behavior</title><link href="https://researchut.com/blog/Plant_Territorial_Behavior/" rel="alternate"/><id>https://researchut.com/blog/Plant_Territorial_Behavior/</id><published>2021-06-29T22:35:19+05:30</published><updated>2021-06-29T22:35:19+05:30</updated><author><name>Ritesh Raj Sarraf</name><email>rrs@researchut.com</email></author><summary type="html">&lt;p>This blog post is about my observations of some of the plants in my home garden.&lt;/p>
&lt;p>While still a n00b on the subject, these notes are my observations and experiences over days, weeks and months. Thankfully, with the capability to take frequent pictures, it has been easy to do an assessment and generate a report of some of these amazing behaviors of plants, in an easy timeline order; all thanks to the EXIF data embedded.
This has very helpfully allowed me to record my, otherwise minor observations, into great detail; and make some sense out of it by correlating the data over time.&lt;/p></summary><content type="html"><![CDATA[<p>This blog post is about my observations of some of the plants in my home garden.</p>
<p>While still a n00b on the subject, these notes are my observations and experiences over days, weeks and months. Thankfully, with the capability to take frequent pictures, it has been easy to do an assessment and generate a report of some of these amazing behaviors of plants, in an easy timeline order; all thanks to the EXIF data embedded.
This has very helpfully allowed me to record my, otherwise minor observations, into great detail; and make some sense out of it by correlating the data over time.</p>
<p>It is an emotional experience. You see, plants are amazing. When I sow a sapling, water it, feed it, watch it grow, prune it, medicate it, and what not; I build up affection towards it.</p>
<p>Though, at the same time, to me it is a strict relationship, not too attached; as in it doesn&rsquo;t hurt to uproot a plant if there is a good reason. But still, I find some sort of association to it.</p>
<p>With plants around, it feels I have a lot of lives around me. All prospering, communicating, sharing. And communicate they do. What is needed is just the right language to observe and absorb their signals and decipher what they are trying to say.</p>
<h2 id="devastation">Devastation</h2>
<p>How in this world, when you are caring for your plants, can it transform:</p>
<h3 id="from-this">From This</h3>
<p><link rel="stylesheet" href="/css/hugo-easy-gallery.css" />

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20200719_113627_tigr.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20200719_113627_tigr.jpg" alt="Healthy Mulberry Plant"/>
    </div>
    <a href="/images/IMG_20200719_113627_tigr.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Healthy Mulberry Plant</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20201105_142219_tigr.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20201105_142219_tigr.jpg" alt="Healthy Mulberry Plant"/>
    </div>
    <a href="/images/IMG_20201105_142219_tigr.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Healthy Mulberry Plant</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/MVIMG_20200621_080239.jpg');" >
      <img itemprop="thumbnail" src="/images/MVIMG_20200621_080239.jpg" alt="Healthy Bael Plant"/>
    </div>
    <a href="/images/MVIMG_20200621_080239.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Healthy Bael Plant</h4>
      </figcaption>
  </figure>
</div>
</p>
<h3 id="to-this">To This</h3>
<p>

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/MVIMG_20201205_140903.jpg');" >
      <img itemprop="thumbnail" src="/images/MVIMG_20201205_140903.jpg" alt="Dead Mulberry Plant"/>
    </div>
    <a href="/images/MVIMG_20201205_140903.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Dead Mulberry Plant</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20210329_103803361.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20210329_103803361.jpg" alt="Very Sick Bael Plant"/>
    </div>
    <a href="/images/PXL_20210329_103803361.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Very Sick Bael Plant</h4>
      </figcaption>
  </figure>
</div>
</p>
<p>With emotions involved, this can be an unpleasant experience.</p>
<p>Bael is a dear plant to me. The plant as a whole has religious values (Shiva). As well, its fruits have lots of health benefits, especially for the intestines. Its leaves have a lot of medicinal properties.</p>
<p>When I planted the Bael, there were a lot of emotions that went along.</p>
<p>On the other hand, the Mulberry is something I put in with a lot of enthusiasm. Mulberries are now rare to find, especially in urban locations. For one, they have a very short shelf life; But more than that, the way lifestyles are heading towards, I was always worried if my children would ever have a day to see and taste these fruits.</p>
<p>The mulberry that I planted, yielded twice; once very soon when I had planted and second, before it died. Infact, it died while during its second yield phase.</p>
<p>It was quite saddening to see that happen. It made me wonder why it happened. I had been caring for the plants fairly well. Watering them timely, feeding them the right amount of nutrients. They were getting a good amount of sun.</p>
<p>But still their health was deteriorating. And then the demise of the Mulberry. Many thoughts hit my mind.</p>
<p>I consulted the claimed experts in the domain, the <em>maali</em>, the gardener. I got a very vague answer; there must be termites in the soil. It didn&rsquo;t make much sense to me. I mean if there are termites they&rsquo;d hit day one. They won&rsquo;t sleep for months and just wake up one fine day and start attacking the roots of particular plants; not all.</p>
<p>I wasn&rsquo;t convinced with the termite theory; But still, give the <em>expert</em> the blind hand, I went with his word.</p>
<p>When my mulberry was dead, I dug its roots. Looking for proof, to see if there were any termites, I uprooted it. But I couldn&rsquo;t find any trace of termites. And the plant next to it was perfectly healthy and blossoming. So I was convinced that it wasn&rsquo;t the termite but something else.</p>
<p>But else what ? I still didn&rsquo;t have an answer to that.</p>
<h2 id="thinking">Thinking</h2>
<p>The Corona pandemic had embraced and there was a lot to worry, and worry not any, if you change the perspective. With plants around in my home, and our close engagement with them, and the helplessness that I felt after seeking help from the experts, it was time again; to build up some knowledge on the subject.</p>
<p>But how ? How do you go about a subject you have not much clue about ? A subject which has always been around in the surrounding but very seldom have I dedicated <em>focused thought</em> to it. To be honest, the initial thought of diving on the subject made me clueless. I had no idea where to begin with. But, so, as has been my past history, I chose to take it as a <em>curiosity</em>.</p>
<p>I gathered some books, skimmed through a couple of pages. Majority of the books I got hold of were about <em><strong>DIYs and How to do Home Gardening</strong></em> types. It was a decent introduction to a novice but my topic of curiosity was different.</p>
<p>Thankfully, with the Internet, and YouTube®️ in particular, a lot of good stuff is available as documentary videos. While going through some, I came across a video which mentioned about <strong>carnivore plants</strong>. Like, for example, this one. 

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/carnivore_plant.jpeg');" >
      <img itemprop="thumbnail" src="/images/carnivore_plant.jpeg" alt="Carnivore Plant"/>
    </div>
    <a href="/images/carnivore_plant.jpeg" itemprop="contentUrl"></a>
      <figcaption><h4>Carnivore Plant</h4>
      </figcaption>
  </figure>
</div>
 <div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
 			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/Z08FhT3-cJc?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
 		</div>
</p>
<p>This got me thinking that there could be a possibility of something similar, that did the fate to my Mulberry plant. But who did it ? And how to dive further on this suspicion ? And most of all, if that <em>thought of possibility</em> was actually the <em>reality</em>. Or was I just hitting in the dark ?</p>
<h2 id="beginning">Beginning</h2>
<p>To put some perspective, here&rsquo;s how it started. When we moved into our home, the gardener put in a couple of plants stock, as part of the property handover. Now, I don&rsquo;t exactly recollect the name of the plants that came in stock, neither English nor Hindi; But at my neighbor&rsquo;s place, the plant is still there.</p>
<p>Here are some of the pictures of this beauty. But don&rsquo;t just go by the looks as looks can be deceiving


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20210427_095928.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20210427_095928.jpg" alt="Dominating Plant"/>
    </div>
    <a href="/images/IMG_20210427_095928.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Dominating Plant</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20210427_095959.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20210427_095959.jpg" alt="Dominating Plant"/>
    </div>
    <a href="/images/IMG_20210427_095959.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Dominating Plant</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20210427_100016.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20210427_100016.jpg" alt="Dominating Plant"/>
    </div>
    <a href="/images/IMG_20210427_100016.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Dominating Plant</h4>
      </figcaption>
  </figure>
</div>
</p>
<p>We hadn&rsquo;t put any serious thought about the plants we were offered by the gardener. After all, we never had ever thought of any mishap either.</p>
<h2 id="plants-we-planted">Plants we planted</h2>
<p>Apart from what was offered by the builder/gardener as part of the property handover, in over the next 6 months of we moving in, I planted 3 tree type plants.</p>
<ol>
<li>Mulberry</li>
<li>Bael</li>
<li>Rudraksha</li>
</ol>
<p>The Mulberry, as I have described so far, died a tragic death.</p>
<p>Bael, on the other hand, fought hard. But very little did we know that the plant was struggling the fight. Our impression was that we must have been given a bad breed of the plant. Or maybe the termite theory had some truth.</p>
<p>For the Rudraksha plant, the growth was slow. This was the very first time I had seen a Rudraksha plant, so I had no clue of what its growth rate could be, and what to expect out of it. I wasn&rsquo;t sure if the local climate suited the plant. A quick search showed no objections to the plant in the local climate, but that was it. So my theory has been to put in the plant, and observe.</p>
<p>Here&rsquo;s what my Rudraksha plant looked like during the initial days/weeks of its settlement</p>


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20200621_080227.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20200621_080227.jpg" alt="Rudraksha Plant"/>
    </div>
    <a href="/images/IMG_20200621_080227.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Rudraksha Plant</h4>
      </figcaption>
  </figure>
</div>

<h2 id="the-hint">The Hint</h2>
<p>Days passed and so on. Not much had progressed in gathering information. The plant&rsquo;s health was usual; deteriorating at a slow pace.</p>
<p>On day, thinking of the documentaries I had been watching, it hit my mind about the plant behavior.</p>
<ul>
<li>Plants can be <strong>Carnivores</strong>.</li>
<li>Plants can be <strong>Aggressive</strong>.</li>
<li>Plants can be <strong>Invaders</strong>.</li>
<li>Plants can be <strong>Territorial</strong>.</li>
</ul>
<p>There are many plants where their aggression can be witnessed with bare human eyes. Like creepers. Some of them are good at spreading tentacles, grabbing onto other plants&rsquo; stems and branches and spread above it. This was my hint from the documentaries. That&rsquo;s one of the many ways plants set their dominance. That is what hit my mind that if plants are aggressive on the out, underneath the soil, they should be having similar behavior.</p>
<p>I mean, what we see as humans is just a part of the actual plant. More than half of the actual plant is usually underneath the soil, in most plants.</p>
<p>So there&rsquo;s a high chance to get more information out, if you dig the soil and look the roots.</p>
<h2 id="the-digging">The Digging</h2>
<p>As I mentioned earlier, I do establish <em>bindings, emotions and attachments</em>. But not much usually comes in the way to <em>curiosity</em>.</p>
<p>To dig further on the theory that the problem was elsewhere, with within the plants ecosystem, we needed to pick on another subject - <em>the plant</em>.</p>
<p>And the plant we chose was the plant which was planted in the initial offering to us, when we moved into our home. It was the same plant breed which was neighboring all our newly planted trees: <strong>Rudraksha, Mulberry and Bael</strong>.</p>
<p>If you look closely into the pictures above of these plants, you&rsquo;ll notice the stem of another plant, the Territorial Dominator, is close-by to these 3 plants. That&rsquo;s because the gardener put in a good number of them to get his action item complete.</p>
<p>So we chose to dig and uproot one of <em>those plant</em> to start with. Now, while they may look gentle on the outside, with nice red colored tiny flowers, these plants were giants underneath. Their roots were huge. It took some sweat shredding to single-handedly remove them.</p>
<p>

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20210212_110858.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20210212_110858.jpg" alt="Dominating Plant Uprooted"/>
    </div>
    <a href="/images/IMG_20210212_110858.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Dominating Plant Uprooted</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20210212_110902.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20210212_110902.jpg" alt="Dominating Plant Uprooted"/>
    </div>
    <a href="/images/IMG_20210212_110902.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Dominating Plant Uprooted</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20210212_110958.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20210212_110958.jpg" alt="Dominating Plant Uprooted"/>
    </div>
    <a href="/images/IMG_20210212_110958.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Dominating Plant Uprooted</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20210212_111002.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20210212_111002.jpg" alt="Dominating Plant Uprooted"/>
    </div>
    <a href="/images/IMG_20210212_111002.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Dominating Plant Uprooted</h4>
      </figcaption>
  </figure>
</div>
</p>
<h2 id="today-is-brighter">Today is brighter</h2>
<h3 id="bael">Bael</h3>
<p>I&rsquo;ll let the pictures do the initial talking today.</p>
<p>

<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20210423_102119635.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20210423_102119635.jpg" alt="Healthy Bael"/>
    </div>
    <a href="/images/PXL_20210423_102119635.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Healthy Bael</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20210606_101730160.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20210606_101730160.jpg" alt="Healthy Bael"/>
    </div>
    <a href="/images/PXL_20210606_101730160.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Healthy Bael</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/vlcsnap-2021-06-27-21h34m28s092.png');" >
      <img itemprop="thumbnail" src="/images/vlcsnap-2021-06-27-21h34m28s092.png" alt="Healthy Bael"/>
    </div>
    <a href="/images/vlcsnap-2021-06-27-21h34m28s092.png" itemprop="contentUrl"></a>
      <figcaption><h4>Healthy Bael</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/vlcsnap-2021-06-27-21h34m42s221.png');" >
      <img itemprop="thumbnail" src="/images/vlcsnap-2021-06-27-21h34m42s221.png" alt="Healthy Bael"/>
    </div>
    <a href="/images/vlcsnap-2021-06-27-21h34m42s221.png" itemprop="contentUrl"></a>
      <figcaption><h4>Healthy Bael</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/vlcsnap-2021-06-27-21h35m03s004.png');" >
      <img itemprop="thumbnail" src="/images/vlcsnap-2021-06-27-21h35m03s004.png" alt="Healthy Bael"/>
    </div>
    <a href="/images/vlcsnap-2021-06-27-21h35m03s004.png" itemprop="contentUrl"></a>
      <figcaption><h4>Healthy Bael</h4>
      </figcaption>
  </figure>
</div>
</p>
<p>The above ones are pictures of the same Bael plant, which had struggled to live, for almost 14 months. Back then, this plant was starved of its resources. It was dying a slow death out of starvation. After we uprooted the other dominant species, the Bael has recovered and has regained its charm.</p>
<p>In the pictures above of the Bael plant, you can clearly mark out the difference in its stem. The dark colored one is from its months of struggle, while the bright green is from now where it is well nourished and regained its health.</p>
<h3 id="mulberry">Mulberry</h3>
<p>As for the Mulberry, I couldn&rsquo;t save it. But I later managed to get another one. But it turns out I didn&rsquo;t take good, full length pictures of the new mulberry when I planted. The only picture I have is this:


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/MVIMG_20210303_120806.jpg');" >
      <img itemprop="thumbnail" src="/images/MVIMG_20210303_120806.jpg" alt="Second Mulberry Plant"/>
    </div>
    <a href="/images/MVIMG_20210303_120806.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Second Mulberry Plant</h4>
      </figcaption>
  </figure>
</div>
 I recollect when I brought it home, it was around 1 - 1.5 feet in length.</p>
<p>This is where I have it today: <em>Majestically standing, 12 feet and counting</em>


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/vlcsnap-2021-06-27-21h35m41s529.png');" >
      <img itemprop="thumbnail" src="/images/vlcsnap-2021-06-27-21h35m41s529.png" alt="Second Mulberry Plant 7 feet tall"/>
    </div>
    <a href="/images/vlcsnap-2021-06-27-21h35m41s529.png" itemprop="contentUrl"></a>
      <figcaption><h4>Second Mulberry Plant 7 feet tall</h4>
      </figcaption>
  </figure>
</div>
</p>
<h3 id="rudraksha">Rudraksha</h3>
<p>Then:


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/IMG_20200621_080227.jpg');" >
      <img itemprop="thumbnail" src="/images/IMG_20200621_080227.jpg" alt="Rudraksha Plant"/>
    </div>
    <a href="/images/IMG_20200621_080227.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Rudraksha Plant</h4>
      </figcaption>
  </figure>
</div>
</p>
<p>And now:</p>
<p>I feel quite happy about


<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20210407_124113300.MP.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20210407_124113300.MP.jpg" alt="Rudraksha Plant"/>
    </div>
    <a href="/images/PXL_20210407_124113300.MP.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Rudraksha Plant</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20210605_101755879.MP.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20210605_101755879.MP.jpg" alt="Rudraksha Plant"/>
    </div>
    <a href="/images/PXL_20210605_101755879.MP.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Rudraksha Plant</h4>
      </figcaption>
  </figure>
</div>



<div class="box" >
  <figure  itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
    <div class="img" style="background-image: url('/images/PXL_20210606_101648641.MP.jpg');" >
      <img itemprop="thumbnail" src="/images/PXL_20210606_101648641.MP.jpg" alt="Rudraksha Plant"/>
    </div>
    <a href="/images/PXL_20210606_101648641.MP.jpg" itemprop="contentUrl"></a>
      <figcaption><h4>Rudraksha Plant</h4>
      </figcaption>
  </figure>
</div>
</p>


<video width=100% controls> //autoplay off
<!-- <video width=100% controls autoplay> //autoplay on -->
    <source src="/images/VID_20210629_085641.mp4.mp4" type="video/mp4">
    Your browser does not support the video tag.  
</video>
<video width=100% controls> //autoplay off
    <source src="/images/VID_20210629_085704.mp4.mp4" type="video/mp4">
    Your browser does not support the video tag.  
</video>
<video width=100% controls> //autoplay off
    <source src="/images/VID_20210629_085803.mp4.mp4" type="video/mp4">
    Your browser does not support the video tag.  
</video>


<p>All these plants are on the very same soil with the very same care taker. What has changed is my experience and learning.</p>
<h2 id="plant-co-existence">Plant Co-Existence</h2>
<p>Plant co-existence is a difficult topic. My knowledge on plants is very limited in general, and co-existence is something tricky, unexplored, at times invisible (when underneath the soil). So it is a difficult topic. So far, what I&rsquo;ve learnt is purely observations, experiences and hints from the documentaries.</p>
<p>There surely are many many plants that co-exist very well. A good example is my Bael plant itself, which is healthily co-sharing its space with 2 other Croton plants. Same goes for the Rudraksha, which has a close-by neighbor in an Adenium and an Allamanda.</p>
<p>The plant world is mesmerizing. How they <em>behave, communicate and many many more signs</em>. There&rsquo;s so much to observe, learn, explore and document. I hope to have more such observations and experiences to share 🙏</p>
]]></content></entry></feed>