<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nenad Mićić</title>
    <description>The latest articles on DEV Community by Nenad Mićić (@nmicic).</description>
    <link>https://dev.to/nmicic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3503066%2F1a4b00a3-069c-44a5-80bb-6415b4588f32.jpg</url>
      <title>DEV Community: Nenad Mićić</title>
      <link>https://dev.to/nmicic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nmicic"/>
    <language>en</language>
    <item>
      <title>The same tiny GPT in SQL, PostScript and Brainfuck, byte for byte</title>
      <dc:creator>Nenad Mićić</dc:creator>
      <pubDate>Fri, 02 Oct 2026 09:54:22 +0000</pubDate>
      <link>https://dev.to/nmicic/the-same-gpt-in-sql-postscript-and-brainfuck-byte-for-byte-59lc</link>
      <guid>https://dev.to/nmicic/the-same-gpt-in-sql-postscript-and-brainfuck-byte-for-byte-59lc</guid>
      <description>&lt;p&gt;This post continues the int-llm hobby experiments from &lt;a href="https://www.linkedin.com/posts/nenadmicic_a-few-llm-experiments-ive-been-doing-as-ugcPost-7492010128074944512-oL52/" rel="noopener noreferrer"&gt;my earlier post&lt;/a&gt;. The earlier repositories are &lt;a href="https://github.com/nmicic/int-llm" rel="noopener noreferrer"&gt;int-llm&lt;/a&gt; (Q16.48 fixed-point training and TinyLlama inference), &lt;a href="https://github.com/nmicic/int-llm-precision-ladder" rel="noopener noreferrer"&gt;int-llm-precision-ladder&lt;/a&gt; (reduced stored weight precision checked against the Q16.48 reference), &lt;a href="https://github.com/nmicic/int-llm-coordinate-permutation" rel="noopener noreferrer"&gt;int-llm-coordinate-permutation&lt;/a&gt; (reversible coordinate permutations of Llama checkpoints), and &lt;a href="https://github.com/nmicic/int-llm-viz" rel="noopener noreferrer"&gt;int-llm-viz&lt;/a&gt; (visualization of the integer GPT weights and inference path).&lt;/p&gt;

&lt;p&gt;Those projects produced a C program whose output is deterministic down to the last byte. This post describes three new repositories that reproduce that output in SQL, PostScript, and Brainfuck.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reference and the gate
&lt;/h2&gt;

&lt;p&gt;The model is Andrej Karpathy's microgpt: a character-level transformer with 1 layer, 32 embedding dimensions, 4 attention heads of 8 dimensions each, an MLP width of 128, a context length of 8, and a vocabulary of 26 lowercase letters plus one BOS token. It has 14,272 parameters and was trained on a list of names.&lt;/p&gt;

&lt;p&gt;The int-llm C implementation performs every operation in Q16.48 fixed point: a signed 64-bit integer with 48 fractional bits. RMSNorm, the attention projections, softmax, exp, inverse square root, and the xorshift64 sampler are all integer code. Because no floating-point operation participates, the output depends only on the weights and the RNG seed. In this post, "the oracle" means that C program, and "the gate" means the comparison of a port's output against it.&lt;/p&gt;

&lt;p&gt;The oracle loads a 115,576-byte MGW checkpoint, runs 122 forward passes, and prints 20 sampled names (kayla, daia, lee, …, karin). Each port must print the same bytes. Each port also computes two FNV-1a checksums inside its own code, one over every raw logit word and one over every sampled byte, and both must equal the pinned values. The checksums detect regressions; they are not cryptographic integrity checks.&lt;/p&gt;

&lt;p&gt;A deliberately corrupted checkpoint serves as a negative control. The corrupted model prints the same 20 names but a different logit checksum (&lt;code&gt;b10c3a08150e95c6&lt;/code&gt; instead of &lt;code&gt;0610f72f01c199cb&lt;/code&gt;). A port that passes the gate with the canonical model and fails it with the corrupted model is comparing arithmetic, not only text.&lt;/p&gt;

&lt;h2&gt;
  
  
  int-llm-sql
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;microgpt.sql&lt;/code&gt; is a 1,410-line SQLite script. It runs with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sqlite3 :memory: &amp;lt; microgpt.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script calls &lt;code&gt;readfile()&lt;/code&gt; once to load the committed model, decodes the little-endian weights into tables, runs the forward pass and the sampling loop, prints 20 names, and compares its own checksums and step count against the pinned values before it prints &lt;code&gt;SQL_GATE=PASS&lt;/code&gt;. No stored procedure, user-defined function, loadable extension, or floating-point value participates. The repository tests the script with SQLite 3.51.0; the shell must support recursive CTEs, generated columns, window functions, ordered aggregate arguments, and &lt;code&gt;readfile()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;SQL lacks four things the forward pass needs, and the script supplies each:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sequencing.&lt;/strong&gt; SQL has no loop. An insert trigger fires the next forward pass. The script delivers 160 ticks; 122 of them reach a forward pass before BOS tokens end the samples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;128-bit integers.&lt;/strong&gt; SQLite integers are signed 64-bit. The script splits each Q16.48 multiplication into limbs and implements division, exp, and inverse square root as recursive CTEs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XOR.&lt;/strong&gt; SQLite has no XOR operator. The script computes &lt;code&gt;XOR(x, y)&lt;/code&gt; as &lt;code&gt;(x | y) - (x &amp;amp; y)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overflow detection.&lt;/strong&gt; SQLite silently promotes an overflowing &lt;code&gt;+&lt;/code&gt; or &lt;code&gt;*&lt;/code&gt; to REAL. The limb arithmetic keeps every intermediate in range, and &lt;code&gt;SUM()&lt;/code&gt; serves as the accumulator so that an overflow fails loudly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Matrix multiplication needs no workaround: it is a join followed by an integer &lt;code&gt;SUM()&lt;/code&gt;. During development, the SQL implementation was checked against the oracle at all 69,748 recorded activation, logit, and probability rows and at all 122 sampling records.&lt;/p&gt;

&lt;h2&gt;
  
  
  int-llm-postscript
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;microgpt_infer.ps&lt;/code&gt; is a 512-line PostScript program. Ghostscript runs it in about 2 seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gs &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-dBATCH&lt;/span&gt; &lt;span class="nt"&gt;-dNODISPLAY&lt;/span&gt; &lt;span class="nt"&gt;-dNOSAFER&lt;/span&gt; microgpt_infer.ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PostScript provides floating-point &lt;code&gt;exp&lt;/code&gt;, &lt;code&gt;ln&lt;/code&gt;, and &lt;code&gt;sqrt&lt;/code&gt;. The program uses none of them; every operation is integer &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;mul&lt;/code&gt;, &lt;code&gt;idiv&lt;/code&gt;, &lt;code&gt;bitshift&lt;/code&gt;, &lt;code&gt;xor&lt;/code&gt;, or &lt;code&gt;and&lt;/code&gt;. The program parses &lt;code&gt;model.mgw&lt;/code&gt; directly (header, config, tensor index, little-endian two's-complement payloads), runs the 122 forward passes, and prints the same 485 bytes as the oracle: the Machin-series Pi banner (&lt;code&gt;Pi = 3.141592653589782&lt;/code&gt;, including the oracle's integer-truncation error in the last digits) and the 20 names.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;microgpt_train.ps&lt;/code&gt; is a 1,090-line trainer. It initializes the model, runs the whole-sequence forward and backward pass, applies Adam with gradient clipping and bias correction under a CORDIC cosine learning-rate schedule, writes an MGW v1 checkpoint, and samples 20 names. All model and optimizer state is Q16.48. On Ghostscript 10.04.0, 5,000 steps took 3,712 seconds (about 62 minutes). The 5,000 loss lines, the 20 samples, and the 115,576-byte checkpoint matched a fresh C run byte for byte, and the checkpoint matched the committed &lt;code&gt;model.mgw&lt;/code&gt; at the same SHA-256.&lt;/p&gt;

&lt;p&gt;The PostScript-specific hazard: Ghostscript's &lt;code&gt;mul&lt;/code&gt; returns a real when the product overflows 64 bits, instead of raising an error. The program therefore splits each wide product into 24-bit limbs with a carry chain, and splits division remainders into two 31-bit limbs, so that no intermediate exceeds 2^63 − 1. If any limb were wrong, the gate would fail on the first affected sample.&lt;/p&gt;

&lt;h2&gt;
  
  
  int-llm-brainfuck
&lt;/h2&gt;

&lt;p&gt;This is the one I run once and never again, so you don't have to.&lt;/p&gt;

&lt;p&gt;Brainfuck has eight commands: &lt;code&gt;&amp;gt; &amp;lt; + - . , [ ]&lt;/code&gt;. A cell holds one byte. The language has no multiplication, no comparison, and no conditional other than &lt;code&gt;[ ]&lt;/code&gt;, which repeats its body while the current cell is nonzero.&lt;/p&gt;

&lt;p&gt;The repository pins its own machine profile, because Brainfuck implementations disagree on cell width, EOF, and tape size: 4,194,304 zero-initialized cells, 8-bit wrapping arithmetic, binary stdin and stdout, pointer underflow and overflow as errors, and &lt;code&gt;,&lt;/code&gt; writing zero at EOF. Each Q16.48 value occupies eight little-endian cells.&lt;/p&gt;

&lt;p&gt;Python generators emit the program. A generator may expand macros and allocate static tape regions; it may not precompute logits, samples, checksums, losses, or checkpoints. The interpreter executes commands, enforces tape limits, and counts executed commands; it does not parse the model or recognize tensors. All model work happens in the eight commands.&lt;/p&gt;

&lt;p&gt;The generated programs are not committed, because they are too large for an ordinary Git repository. The repository holds the generators, the tape map, the oracle corpus, the fixtures, and the verification logs. &lt;code&gt;make regen&lt;/code&gt; and &lt;code&gt;make training-full-program&lt;/code&gt; regenerate the programs.&lt;/p&gt;

&lt;p&gt;Phase 1, inference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;microgpt.bf&lt;/code&gt;: 16,395,194,474 bytes (16.4 GB)&lt;/li&gt;
&lt;li&gt;46,883,492,331,121,926 source commands executed (about 47 quadrillion)&lt;/li&gt;
&lt;li&gt;70,843 seconds (about 19.7 hours) for 20 names&lt;/li&gt;
&lt;li&gt;sample and logit checksums equal the pinned values; the corrupted checkpoint produces the expected distinct logit checksum&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Phase 2, training, 5,000 steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;microgpt_train.bf&lt;/code&gt;: 210,300,828,662 bytes (210 GB)&lt;/li&gt;
&lt;li&gt;484,906,588,575,174,327,064 source commands executed (about 485 quintillion)&lt;/li&gt;
&lt;li&gt;409 hours 29 minutes wall time on the Linux x86-64 runner, including cold AOT compilation&lt;/li&gt;
&lt;li&gt;all 5,000 loss lines, the 20 samples, the wide checkpoint, and the F12 checkpoint equal the oracle's output byte for byte&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trainer also computes Pi inside Brainfuck with the oracle's integer Machin series and passes the value into the CORDIC cosine schedule, because the oracle does the same and the gate accepts nothing else.&lt;/p&gt;

&lt;p&gt;A full run is not required to check the repository. &lt;code&gt;make bootstrap&lt;/code&gt; verifies the pinned artifacts and runs 39 unit tests in about one second. &lt;code&gt;make test-model-validation&lt;/code&gt; generates a 2 MB program that loads and validates the model image; it passes in about 13 seconds. &lt;code&gt;make TRACE_STAGE=logits test-model-trace&lt;/code&gt; generates a 3.2 GB program that runs one position through the complete transformer and compares its 27 logits against the oracle; with the optimized interpreter it executed 166,850,840,789,467 source commands in 18 seconds and passed. One detail: the model image is 29,944 bytes, and the generated program contains exactly 29,944 &lt;code&gt;,&lt;/code&gt; commands to read it.&lt;/p&gt;

&lt;p&gt;The verification log keeps failures. The first exact stop-after-20 training run stopped with a pointer underflow on both runners. The cause was uncleared Adam serial state overlapping the next forward pass's row-copy controls. The fix clears that workspace and has a regression test. The log records the failed run as FAIL next to the fixed rerun; it does not relabel it.&lt;/p&gt;

&lt;p&gt;The full Brainfuck training run took 409 hours. I ran it so that “it should work” could become “it did work.”&lt;/p&gt;

&lt;p&gt;Human code review is welcome. The generated Brainfuck program is 210 GB, so reviewers wishing to avoid AI assistance should probably clear their calendars for the next few centuries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;These are hobby projects, done for fun. The question behind them is how far a transformer can go, not whether it should.&lt;/p&gt;

&lt;p&gt;Integer-only arithmetic is what makes the question answerable. A floating-point port of the same model would produce slightly different rounding in each host, and "close enough" has no gate. With Q16.48, every host either reproduces the oracle's bytes or fails on the first divergent sample. That strictness turns an unusual host into a precise test of what the computation needs: 64-bit integers, a logical right shift, a loop, and nothing else. SQL supplied the loop with a trigger. PostScript supplied the wide multiply with 24-bit limbs. Brainfuck supplied everything from eight commands and a tape of bytes.&lt;/p&gt;

&lt;p&gt;The original int-llm project asked whether fixed-point integer arithmetic can replace floating point in training and inference, and int-llm-precision-ladder asked how little precision the stored weights can keep before the output changes. These three repositories ask how little the host language can offer. The answer so far is that the floor is low, and the gate is the reason the answer is exact.&lt;/p&gt;

&lt;p&gt;Every result is reproducible from the repositories with a compiler, the pinned tool versions, and time.&lt;/p&gt;

&lt;p&gt;These projects were developed and tested with AI assistance. The correctness claims do not rest on that; they rest on the byte-for-byte comparisons recorded in each repository.&lt;/p&gt;

&lt;p&gt;Lesson learned: trust AI-assisted work through validation, not through the assumption that a human reviewed every generated line.&lt;/p&gt;

&lt;p&gt;Repositories: &lt;a href="https://github.com/nmicic/int-llm-sql" rel="noopener noreferrer"&gt;int-llm-sql&lt;/a&gt;, &lt;a href="https://github.com/nmicic/int-llm-postscript" rel="noopener noreferrer"&gt;int-llm-postscript&lt;/a&gt;, &lt;a href="https://github.com/nmicic/int-llm-brainfuck" rel="noopener noreferrer"&gt;int-llm-brainfuck&lt;/a&gt;. Everything else is at &lt;a href="https://github.com/nmicic" rel="noopener noreferrer"&gt;github.com/nmicic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The next one will be something different.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>showdev</category>
      <category>sql</category>
      <category>brainfuck</category>
    </item>
    <item>
      <title>Unmoor: another take on a roaming remote terminal</title>
      <dc:creator>Nenad Mićić</dc:creator>
      <pubDate>Tue, 15 Sep 2026 09:30:44 +0000</pubDate>
      <link>https://dev.to/nmicic/unmoor-another-take-on-a-roaming-remote-terminal-3oi4</link>
      <guid>https://dev.to/nmicic/unmoor-another-take-on-a-roaming-remote-terminal-3oi4</guid>
      <description>&lt;p&gt;I published &lt;strong&gt;Unmoor&lt;/strong&gt;, an experimental encrypted, authenticated UDP terminal and file transport for Linux and macOS.&lt;/p&gt;

&lt;p&gt;The basic idea is not new. &lt;a href="https://mosh.org/" rel="noopener noreferrer"&gt;Mosh&lt;/a&gt; solved the roaming terminal first. Unmoor explores a different set of trade-offs around the same general problem.&lt;/p&gt;

&lt;p&gt;The session is identified by a cryptographic identity rather than an address tuple, so an address or NAT change doesn't end it; the session can resume once a usable UDP path exists again.&lt;/p&gt;

&lt;h3&gt;
  
  
  The main trade-off
&lt;/h3&gt;

&lt;p&gt;Mosh and Unmoor differ in what they treat as the terminal.&lt;/p&gt;

&lt;p&gt;Mosh synchronizes screen state. It can skip older output when newer state supersedes it, and its speculative local echo makes typing feel responsive before the server confirms each keystroke.&lt;/p&gt;

&lt;p&gt;Unmoor sends the stream.&lt;/p&gt;

&lt;p&gt;Once a terminal byte has been admitted by Unmoor, it is delivered or kept for repair. The client reports &lt;code&gt;SYNC&lt;/code&gt;, &lt;code&gt;OUT-OF-SYNC&lt;/code&gt; or &lt;code&gt;STALLED&lt;/code&gt;, so a gap isn't silently treated as delivered.&lt;/p&gt;

&lt;p&gt;That has a couple of useful consequences: normal terminal scrollback, search and copy work because the bytes really arrive, and someone who disrupts the path can stop output reaching you but cannot leave the client claiming that it received the complete stream.&lt;/p&gt;

&lt;p&gt;There is a real price for that choice. When retained history fills, the sender applies backpressure, which can block the command producing output until the receiver catches up. Mosh can instead skip ahead.&lt;/p&gt;

&lt;p&gt;If responsiveness on a bad link matters more than receiving the full terminal stream, use Mosh.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some other differences
&lt;/h3&gt;

&lt;p&gt;SSH authenticates Unmoor's initial exchange, but it carries public records rather than an Unmoor traffic key. Each endpoint derives fresh session keys locally using hybrid X25519 + ML-KEM-1024 key agreement.&lt;/p&gt;

&lt;p&gt;Post-quantum key agreement is required by default. &lt;code&gt;--pq=prefer&lt;/code&gt; and &lt;code&gt;--pq=off&lt;/code&gt; are explicit downgrades, and rekeys use the same hybrid exchange.&lt;/p&gt;

&lt;p&gt;After bootstrap, terminal and file traffic runs over encrypted, authenticated UDP.&lt;/p&gt;

&lt;p&gt;A few other properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a listener adopts a new return address only after a fresh authenticated packet advances the replay window, so a replayed packet can't redirect the session&lt;/li&gt;
&lt;li&gt;multiple authenticated UDP legs can belong to one session&lt;/li&gt;
&lt;li&gt;single-file push and pull verify the whole file before installing it atomically; a partial destination is never reported as success&lt;/li&gt;
&lt;li&gt;on Linux, the client confines itself by default using &lt;code&gt;no_new_privs&lt;/code&gt;, Landlock and seccomp&lt;/li&gt;
&lt;li&gt;no root, capabilities or kernel module are required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"Multiple legs" does not necessarily mean multiple physical network paths. Different UDP source ports can exercise different RSS/ECMP choices, but that alone does not prove path diversity.&lt;/p&gt;

&lt;p&gt;Unmoor is not a VPN, relay or NAT hole-puncher. The client still needs to be able to reach the listener's UDP port.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where this came from
&lt;/h3&gt;

&lt;p&gt;I actually wrote the lossy version first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nmicic/URTB" rel="noopener noreferrer"&gt;URTB&lt;/a&gt; drops output under pressure because a LoRa link gives you very little bandwidth and sometimes there is no better choice. That trade-off makes sense there.&lt;/p&gt;

&lt;p&gt;A normal network path doesn't have the same constraint, so with Unmoor I wanted to see what happens if admitted terminal output is never silently discarded.&lt;/p&gt;

&lt;p&gt;This is version 0.2.0 / protocol v2. It is experimental and has not had an external security audit.&lt;/p&gt;

&lt;p&gt;It is not intended to be exposed as a public service endpoint, and protocol v2 may change without a compatibility promise.&lt;/p&gt;

&lt;p&gt;The project was developed end-to-end with AI assistance across implementation, specification, tests, reviews and documentation. The material design decisions and responsibility for what was accepted remain mine. That provenance should be part of how the code is evaluated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/nmicic/unmoor
&lt;span class="nb"&gt;cd &lt;/span&gt;unmoor

make &lt;span class="nt"&gt;-j2&lt;/span&gt;
make check
make smoke
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;make smoke performs a real post-quantum bootstrap over loopback UDP with a live PTY.&lt;/p&gt;

&lt;p&gt;The repository contains the usage instructions, protocol and design notes, security model, limitations and tests:&lt;/p&gt;

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

</description>
      <category>linux</category>
      <category>security</category>
      <category>networking</category>
      <category>opensource</category>
    </item>
    <item>
      <title>URTB: An Encrypted PTY Tunnel Over ESP-NOW and LoRa</title>
      <dc:creator>Nenad Mićić</dc:creator>
      <pubDate>Fri, 17 Apr 2026 00:32:30 +0000</pubDate>
      <link>https://dev.to/nmicic/urtb-an-encrypted-pty-tunnel-over-esp-now-and-lora-3omb</link>
      <guid>https://dev.to/nmicic/urtb-an-encrypted-pty-tunnel-over-esp-now-and-lora-3omb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff5oy5005z91f2unv3se9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff5oy5005z91f2unv3se9.png" alt="transport_modes.png" width="800" height="1049"&gt;&lt;/a&gt;&lt;br&gt;
I have two personal laptops: a MacBook Air I carry around the house, and an old Lenovo that mostly stays in the garage. They sit on different VPNs. When WireGuard testing cuts me off I still need a shell on the other machine, and carrying a 5 kg laptop around the house is not practical.&lt;/p&gt;

&lt;p&gt;A pair of Heltec WiFi LoRa 32 V3 boards, plugged into USB on each laptop, solve that problem. URTB is the host binary and matching firmware that give me an encrypted interactive shell over ESP-NOW, with LoRa as automatic fallback.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;Two &lt;code&gt;urtb&lt;/code&gt; processes, each holding the same passphrase-protected capsule file, establish an XChaCha20-Poly1305 session and carry a PTY shell between them. The primary transport is ESP-NOW. In my indoor tests on a clear 2.4 GHz channel, that meant roughly 1-2 Mbps and sub-5 ms latency. When ESP-NOW fails, the session continues automatically over LoRa: slower, but longer-range and sub-GHz. No session renegotiation. The same binary also works over a UNIX socket or through an SSH jump host, so you can try it without any radio hardware.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./urtb keygen &lt;span class="nt"&gt;--out&lt;/span&gt; pairing.capsule

&lt;span class="c"&gt;# machine A&lt;/span&gt;
./urtb listen &lt;span class="nt"&gt;--transport&lt;/span&gt; heltec &lt;span class="nt"&gt;--device&lt;/span&gt; /dev/cu.usbserial-0001 &lt;span class="nt"&gt;--capsule&lt;/span&gt; pairing.capsule

&lt;span class="c"&gt;# machine B&lt;/span&gt;
./urtb connect &lt;span class="nt"&gt;--transport&lt;/span&gt; heltec &lt;span class="nt"&gt;--device&lt;/span&gt; /dev/cu.usbserial-0002 &lt;span class="nt"&gt;--capsule&lt;/span&gt; pairing.capsule
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Two scenarios worth explaining
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;ESP-NOW primary, LoRa fallback.&lt;/strong&gt;&lt;br&gt;
LoRa is useful as an emergency channel. I tested Reticulum's &lt;code&gt;rnsh&lt;/code&gt; on real hardware. It works, but in my LoRa tests it was doing roughly 200-400 bytes/second and 200-500 ms per keystroke, which makes interactive use painful. &lt;code&gt;top&lt;/code&gt; takes 10-15 seconds to redraw. The bottleneck is LoRa's physical layer, not &lt;code&gt;rnsh&lt;/code&gt;. ESP-NOW fixes the throughput problem for short range. URTB uses both: ESP-NOW when it is available, LoRa when it is not, with the session staying alive across the switch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encrypted terminal through a restricted SSH jump host.&lt;/strong&gt;&lt;br&gt;
Say you need to reach a server in a DMZ through a jump host you do not fully trust. Only port 22 is open. &lt;code&gt;AllowTcpForwarding&lt;/code&gt; is disabled. VPN and Mosh need additional ports. The jump host may be compromised.&lt;/p&gt;

&lt;p&gt;URTB has two useful patterns here. The simple one uses &lt;code&gt;--exec&lt;/code&gt;: the URTB AEAD-encrypted tunnel rides inside an SSH byte stream and does not need port forwarding, ProxyJump, or any extra listener on the jump host.&lt;/p&gt;

&lt;p&gt;For the stricter case, pre-start a listener on the target with &lt;code&gt;--loop&lt;/code&gt; and bridge through the jump host with &lt;code&gt;ssh ... socat STDIO UNIX:/tmp/urtb.sock&lt;/code&gt;. That keeps the capsule passphrase local to the endpoints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# target&lt;/span&gt;
&lt;span class="nv"&gt;URTB_PASSPHRASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;example-passphrase ./urtb listen &lt;span class="nt"&gt;--transport&lt;/span&gt; unix &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--socket&lt;/span&gt; /tmp/urtb.sock &lt;span class="nt"&gt;--capsule&lt;/span&gt; cap.cap &lt;span class="nt"&gt;--loop&lt;/span&gt;

&lt;span class="c"&gt;# client&lt;/span&gt;
&lt;span class="nv"&gt;URTB_PASSPHRASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;example-passphrase ./urtb connect &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--exec&lt;/span&gt; &lt;span class="s2"&gt;"ssh jump ssh target socat STDIO UNIX:/tmp/urtb.sock"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--capsule&lt;/span&gt; cap.cap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The capsule is transferred out-of-band to the target; the jump host is not trusted with it and does not need to persist it. The jump host still relays bytes, but it is not trusted with session plaintext.&lt;/p&gt;

&lt;p&gt;Once the capsule is loaded, &lt;code&gt;--burn&lt;/code&gt; does a best-effort local wipe and unlink of the key files. After that, key material stays in process memory for the lifetime of the process, with &lt;code&gt;mlock&lt;/code&gt; and &lt;code&gt;MADV_DONTDUMP&lt;/code&gt; where the platform supports it. Add &lt;code&gt;--otp&lt;/code&gt; and the attacker also needs a valid HOTP/TOTP code to open the PTY, even if they obtain the capsule file from another channel.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I built it
&lt;/h2&gt;

&lt;p&gt;This is an AI-assisted project. The implementation was generated with AI against a frozen specification that I wrote first and then reviewed in multiple rounds with different models before any code was generated.&lt;/p&gt;

&lt;p&gt;The process, briefly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Specification first.&lt;/strong&gt; About 2,000 lines of markdown across &lt;code&gt;SPEC.md&lt;/code&gt;, &lt;code&gt;PROTOCOL.md&lt;/code&gt;, &lt;code&gt;SECURITY.md&lt;/code&gt;, &lt;code&gt;ACCEPTANCE_CRITERIA.md&lt;/code&gt;, and &lt;code&gt;DECISIONS.md&lt;/code&gt; before any code was generated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Adversarial multi-agent review.&lt;/strong&gt; The spec went through seven review rounds using multiple AI agents with different remits: protocol correctness, crypto audit, numerical consistency, and state-machine verification. The 7th round caught a fragmentation logic contradiction that would have forced a rewrite of the channel multiplexer if it had survived into implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Freeze, then generate.&lt;/strong&gt; Once the spec was clean, I froze it and pointed the code-generation agents at it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation review, same method.&lt;/strong&gt; Multiple blind agents reviewed the code, then a synthesis pass pulled the findings together. The OTP bypass in burn mode (&lt;code&gt;if (s-&amp;gt;otp_path)&lt;/code&gt; instead of &lt;code&gt;|| s-&amp;gt;otp_key_mem&lt;/code&gt;) was caught this way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hardware in the loop.&lt;/strong&gt; Two Heltec V3 boards stayed connected over USB during development. The models could run end-to-end tests on real hardware. I also had them write failure-injection code: the firmware has a test-inject build that can drop ESP-NOW TX, drop LoRa TX, and simulate link failure on command from the host.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Disposable VM for jump-host testing.&lt;/strong&gt; Jump-host scenarios were tested against a KVM virtual machine that could be rebuilt on demand via a signed wrapper script. All eight &lt;code&gt;HOWTO_JUMPHOST&lt;/code&gt; scenarios were validated end-to-end that way.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What came out
&lt;/h2&gt;

&lt;p&gt;The host binary is about 8,000 lines of C with no dependencies beyond libc and Monocypher. The firmware is about 1,050 lines of C++ (Arduino/PlatformIO). Notable properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XChaCha20-Poly1305 AEAD, BLAKE2b key derivation, Argon2id-protected key storage&lt;/li&gt;
&lt;li&gt;256-entry additive-fencepost replay window&lt;/li&gt;
&lt;li&gt;PTY multiplexing with fragmentation for LoRa's 72-byte plaintext MTU&lt;/li&gt;
&lt;li&gt;Automatic ESP-NOW-to-LoRa failover and recovery without session renegotiation&lt;/li&gt;
&lt;li&gt;LoRa duty-cycle-aware batching for the EU 868 MHz 1% limit&lt;/li&gt;
&lt;li&gt;Optional HOTP/TOTP second factor&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--burn&lt;/code&gt;: best-effort local wipe and unlink of capsule and OTP key files after load&lt;/li&gt;
&lt;li&gt;Signal handlers that wipe PSK from memory on SIGTERM, SIGHUP, SIGQUIT, and best-effort on SIGSEGV/SIGBUS/SIGFPE&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MADV_DONTDUMP&lt;/code&gt; to exclude key material from core dumps on Linux&lt;/li&gt;
&lt;li&gt;Landlock + seccomp sandbox profiles for both &lt;code&gt;connect&lt;/code&gt; and &lt;code&gt;listen&lt;/code&gt; modes&lt;/li&gt;
&lt;li&gt;42 acceptance criteria passing, 8 failure-injection tests passing, CI on GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I ran &lt;code&gt;cat /dev/urandom&lt;/code&gt; through the full stack — radio, USB framing, AEAD, reassembly — for 20 minutes without a crash. That was the test that satisfied me the code was not just correct on the happy path.&lt;/p&gt;

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

&lt;p&gt;Worth being explicit about what this is not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not audited.&lt;/strong&gt; This is a personal project. The security surface was designed carefully, but it has not been reviewed by an independent security firm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LoRa is very slow.&lt;/strong&gt; In my tests it was around 200-400 bytes/second. Short commands work; anything that generates significant output needs the throttling mode or the session becomes sluggish.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a VPN.&lt;/strong&gt; No IP routing, no general port forwarding. One encrypted PTY session between two named processes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No general file transfer yet.&lt;/strong&gt; This is terminal-first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;--burn&lt;/code&gt; is best-effort.&lt;/strong&gt; On SSDs and modern filesystems, overwrite-before-unlink is not a guarantee of non-recoverability. It reduces exposure from filesystem access after the process exits; it is not cryptographic erasure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compartment sandbox is optional.&lt;/strong&gt; The Landlock + seccomp profiles in &lt;code&gt;compartment/&lt;/code&gt; are not enabled by default. They require a separate tool ( &lt;code&gt;compartment&lt;/code&gt; , also mine) and manual profile activation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Repository
&lt;/h2&gt;

&lt;p&gt;The project is public at &lt;a href="https://github.com/nmicic/URTB" rel="noopener noreferrer"&gt;github.com/nmicic/URTB&lt;/a&gt;. You can try it without hardware using &lt;code&gt;--transport unix&lt;/code&gt;; the quick start in the README takes about 30 seconds once dependencies are installed. The name stands for USB-Radio Terminal Bridge.&lt;/p&gt;

&lt;p&gt;The code is AI-assisted and I am not hiding that. The specification, the review process, the acceptance criteria, the testing methodology, and the decision to ship or not ship — those are mine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsx8p77jio8yv3a18zex5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsx8p77jio8yv3a18zex5.png" alt="Jump Hosts" width="800" height="1049"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>security</category>
      <category>iot</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Built compartment to Sandbox AI Agents on Linux</title>
      <dc:creator>Nenad Mićić</dc:creator>
      <pubDate>Thu, 02 Apr 2026 12:06:30 +0000</pubDate>
      <link>https://dev.to/nmicic/i-built-compartment-to-sandbox-ai-agents-on-linux-14h4</link>
      <guid>https://dev.to/nmicic/i-built-compartment-to-sandbox-ai-agents-on-linux-14h4</guid>
      <description>&lt;p&gt;AI coding agents are useful, but in a corporate environment they are often too privileged by default.&lt;/p&gt;

&lt;p&gt;They can read files, edit code, run commands, inherit environment variables, and talk to the network. I wanted a smaller trust boundary for tools like Claude Code and Codex CLI.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/nmicic/compartment" rel="noopener noreferrer"&gt;compartment&lt;/a&gt;, a small Linux process isolation toolkit with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;compartment-user&lt;/strong&gt; — rootless confinement using Landlock, seccomp, and no_new_privs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;compartment-root&lt;/strong&gt; — stronger namespace-based isolation when needed&lt;/li&gt;
&lt;li&gt;one shared profile format&lt;/li&gt;
&lt;li&gt;zero external dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is also a rebuild of an old idea. Back in 2003, I wrote shell-guard, a wrapper that intercepted shell execution and applied policy early. Modern Linux finally has the kernel primitives to do that idea properly.&lt;/p&gt;

&lt;p&gt;I built compartment primarily for AI-agent sandboxing, but the same logic also applies to other semi-trusted local tools, including SSH.&lt;/p&gt;

&lt;p&gt;Small tool. Explicit policy. Lower blast radius.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/nmicic/compartment" rel="noopener noreferrer"&gt;github.com/nmicic/compartment&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;README: &lt;a href="https://github.com/nmicic/compartment#readme" rel="noopener noreferrer"&gt;github.com/nmicic/compartment#readme&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjoj4ibeuo25mz1gootw6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjoj4ibeuo25mz1gootw6.png" alt="compartment" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>security</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>From 2-Adic Geometry to Cunningham Chains: Visualization-Driven GPU Search</title>
      <dc:creator>Nenad Mićić</dc:creator>
      <pubDate>Wed, 11 Mar 2026 09:42:27 +0000</pubDate>
      <link>https://dev.to/nmicic/from-2-adic-geometry-to-cunningham-chains-visualization-driven-gpu-search-102n</link>
      <guid>https://dev.to/nmicic/from-2-adic-geometry-to-cunningham-chains-visualization-driven-gpu-search-102n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;**Update (March 17, 2026): Since publishing this post, the campaign found two first-kind CC18s with roots 106103983461039119546815109 (87 bits) and 214325014495971624590189129 (88 bits). A later prior-art review showed that first-kind CC18 had already been documented in John Armitage’s 2021 Oxford thesis via the smallest known example, so these are not the first known CC18s. They do, however, remain the largest listed first-kind CC18 entries on the current public Cunningham tables. The campaign has now finished because my available GPU compute time ran out. The original post below is left mostly unchanged as the March 11 baseline.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  From 2-Adic Geometry to Cunningham Chains: Visualization-Driven GPU Search
&lt;/h2&gt;

&lt;p&gt;Nenad Mićić · &lt;a href="https://be.linkedin.com/in/nenadmicic" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; · March 2026&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxtmktff8g84ala7pq1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxtmktff8g84ala7pq1j.png" alt="2-Adic Tree Explorer" width="800" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What This Is
&lt;/h3&gt;

&lt;p&gt;A visualization hobby project that turned into a high-throughput &lt;a href="https://en.wikipedia.org/wiki/Cunningham_chain" rel="noopener noreferrer"&gt;Cunningham chain&lt;/a&gt; search engine. More about HPC optimization and AI-assisted iteration than the math itself.&lt;/p&gt;

&lt;p&gt;It started with mapping integers in a 2-adic geometry, noticing structured prime paths, recognizing Cunningham-chain recurrences, and then building a GPU/CPU pipeline to search for long chains.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8exuwvj9vrdifyeq0eu2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8exuwvj9vrdifyeq0eu2.png" alt="2-adic square-perimeter map with CC1/CC2 edges and chain paths" width="800" height="816"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;This project ultimately did reach its CC18 target, but not the more ambitious CC19 goal. It remained a compute-limited campaign.&lt;/p&gt;

&lt;p&gt;As of March 2026, the public Cunningham chain tables at &lt;a href="https://www.pzktupel.de/CC/cc.php" rel="noopener noreferrer"&gt;pzktupel.de&lt;/a&gt; list results under my name, Nenad Mićić, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;new CC16 and CC17 entries&lt;/li&gt;
&lt;li&gt;the largest listed first-kind CC16, CC17, and CC18 on the current public tables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The published data snapshot contains &lt;strong&gt;929,574 roots&lt;/strong&gt; in total, including &lt;strong&gt;44 CC16&lt;/strong&gt; roots and &lt;strong&gt;1 CC17&lt;/strong&gt;. The main campaign was centered on the &lt;strong&gt;89–91 bit&lt;/strong&gt; range, and the release includes both the search code and derived analysis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gap statistics and spacing distributions&lt;/li&gt;
&lt;li&gt;immunization / residue summaries and immune-fingerprint distributions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;p+1&lt;/code&gt; breaker analysis&lt;/li&gt;
&lt;li&gt;ghost chains — roots where prime links continue beyond the official chain break, tested to depth 20&lt;/li&gt;
&lt;li&gt;closest CC-twins and CC-clusters (triplets, quadruplets, quintuplets)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think this dataset is useful in its own right and deserves deeper study.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28cjdjojrhcwi3ypwcfl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28cjdjojrhcwi3ypwcfl.png" alt="3D Fold - shell structure across levels" width="800" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;p&gt;Visual learning led to search design.&lt;/p&gt;

&lt;p&gt;The 2-adic coordinate system made chain structure visible. The &lt;code&gt;p+1&lt;/code&gt; factorization view showed which small-factor patterns kill candidates early. That became the sieve.&lt;/p&gt;

&lt;p&gt;For a first-kind chain, a root &lt;code&gt;p&lt;/code&gt; generates: &lt;code&gt;p, 2p+1, 4p+3, 8p+7, ...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The key optimization is &lt;strong&gt;depth filtering&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;generate candidates on the CRT-and-wheel search lattice&lt;/li&gt;
&lt;li&gt;test cheap modular conditions across the first &lt;code&gt;d&lt;/code&gt; projected chain positions&lt;/li&gt;
&lt;li&gt;reject any root whose chain is already doomed modulo a tracked small prime&lt;/li&gt;
&lt;li&gt;send only the tiny survivor set to the CPU for probable-prime testing and full chain confirmation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GPU (CUDA):&lt;/strong&gt; 57–65 billion candidates/sec modular filtering (&lt;code&gt;RTX 4090&lt;/code&gt; / &lt;code&gt;RTX 5090&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CPU (GMP):&lt;/strong&gt; probable-prime testing, true-root recovery for non-roots, and chain-length confirmation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The GPU sieve rejects about &lt;strong&gt;99.9988%&lt;/strong&gt; of candidates before expensive primality work is needed. Only about &lt;strong&gt;0.0012%&lt;/strong&gt; survive to the CPU path.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxwgkw20occwx4dohxyc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxwgkw20occwx4dohxyc.png" alt="topdown view - factor coloring for primes, mod-p view for composites" width="800" height="801"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactive Visualizations
&lt;/h3&gt;

&lt;p&gt;Each tool shaped the search design.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nmicic.github.io/cunningham-chain-search/visualizations/chain-mesh/" rel="noopener noreferrer"&gt;Cunningham Chain Mesh&lt;/a&gt;&lt;/strong&gt;: 2-adic square-perimeter map with CC1/CC2 edges and chain paths&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nmicic.github.io/cunningham-chain-search/visualizations/2adic-tree/" rel="noopener noreferrer"&gt;2-Adic Tree Explorer&lt;/a&gt;&lt;/strong&gt;: inspectable tree with local chain structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nmicic.github.io/cunningham-chain-search/visualizations/3d-fold/" rel="noopener noreferrer"&gt;3D Fold&lt;/a&gt;&lt;/strong&gt;: shell structure across levels; top view becomes the &lt;code&gt;p+1&lt;/code&gt; analysis grid&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nmicic.github.io/cunningham-chain-search/visualizations/p1-analysis/" rel="noopener noreferrer"&gt;&lt;code&gt;p+1&lt;/code&gt; Analysis&lt;/a&gt;&lt;/strong&gt;: factor coloring for primes, mod-&lt;code&gt;p&lt;/code&gt; view for composites&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nmicic.github.io/cunningham-chain-search/visualizations/chain-analyzer/" rel="noopener noreferrer"&gt;Chain Analyzer&lt;/a&gt;&lt;/strong&gt;: single-chain analysis, breaker autopsy, residue immunity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nmicic.github.io/cunningham-chain-search/visualizations/campaign-dashboard/" rel="noopener noreferrer"&gt;Campaign Dashboard&lt;/a&gt;&lt;/strong&gt;: live campaign tracking across bit ranges and chain lengths&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://nmicic.github.io/cunningham-chain-search/visualizations/immunization-dashboard/" rel="noopener noreferrer"&gt;Immunization Dashboard&lt;/a&gt;&lt;/strong&gt;: residue immunity analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xoftqvemn44448tqp0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xoftqvemn44448tqp0w.png" alt="Heatmap + Decay curves" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Search: CUDA filtering, GMP proving, prefix sharding, checkpointing&lt;/li&gt;
&lt;li&gt;Visualization: standalone HTML/JS tools&lt;/li&gt;
&lt;li&gt;Analysis: Python plus HTML tools for autopsy and fingerprinting&lt;/li&gt;
&lt;li&gt;AI-assisted: LLMs used for coding iteration; math direction and search decisions are human-driven&lt;/li&gt;
&lt;li&gt;Extra: a PARI/GP library and a small MCP server wrapper for interactive Cunningham-chain analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Part of the project was also an experiment in AI-assisted iteration: not one-shot prompting, but many rounds of visual exploration, code generation, rejection, correction, and performance tuning. The transferable lesson for me was not number theory itself, but the workflow: isolate the hot path, turn it into something benchmarkable, iterate quickly with AI assistance, and only bring back changes that survive measurement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhf9fk9ofgloxnd7b52tm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhf9fk9ofgloxnd7b52tm.png" alt="Immunization Result" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Code: &lt;a href="https://github.com/nmicic/cunningham-chain-search" rel="noopener noreferrer"&gt;https://github.com/nmicic/cunningham-chain-search&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Data snapshot: &lt;a href="https://github.com/nmicic/cunningham-chain-data" rel="noopener noreferrer"&gt;https://github.com/nmicic/cunningham-chain-data&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Interactive visualizations: &lt;a href="https://nmicic.github.io/cunningham-chain-search/visualizations/" rel="noopener noreferrer"&gt;https://nmicic.github.io/cunningham-chain-search/visualizations/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Cunningham chain tables: &lt;a href="https://www.pzktupel.de/CC/cc.php" rel="noopener noreferrer"&gt;https://www.pzktupel.de/CC/cc.php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;CC16 history: &lt;a href="https://www.pzktupel.de/CC/HCC16.php" rel="noopener noreferrer"&gt;https://www.pzktupel.de/CC/HCC16.php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;CC17 history: &lt;a href="https://www.pzktupel.de/CC/HCC17.php" rel="noopener noreferrer"&gt;https://www.pzktupel.de/CC/HCC17.php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;CC18 history: &lt;a href="https://www.pzktupel.de/CC/HCC18.php" rel="noopener noreferrer"&gt;https://www.pzktupel.de/CC/HCC18.php&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Author: Nenad Mićić, Belgium&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5w3afte2vw2ghsw9vr0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5w3afte2vw2ghsw9vr0.png" alt="Chain Analyzer - single-chain analysis, breaker autopsy, residue immunity" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmysfck0mzmkdk6blmrzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmysfck0mzmkdk6blmrzd.png" alt="3D fold 2adic " width="800" height="719"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>cuda</category>
      <category>hpc</category>
      <category>datavis</category>
    </item>
    <item>
      <title>Compass, Steering Wheel, Destination — Framework for Working with AI on Code</title>
      <dc:creator>Nenad Mićić</dc:creator>
      <pubDate>Mon, 15 Sep 2025 08:42:38 +0000</pubDate>
      <link>https://dev.to/nmicic/compass-steering-wheel-destination-framework-for-working-with-ai-on-code-331</link>
      <guid>https://dev.to/nmicic/compass-steering-wheel-destination-framework-for-working-with-ai-on-code-331</guid>
      <description>&lt;p&gt;I'm sharing this with the team as a summary of my personal workflow when working with AI on code. It's not an official framework, but rather a set of learnings from experience (polished with a little help from AI, of course). My main goal is to start a conversation. If you have a better or similar workflow, I'd genuinely love to hear about it.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Compass, Steering Wheel, Destination — Framework for Working with AI on Code
&lt;/h2&gt;

&lt;p&gt;AI can accelerate coding, but it can also drift, hallucinate requirements, or produce complex solutions without a clear rationale.&lt;br&gt;
This framework provides the guardrails to keep AI-assisted development focused, deliberate, and well-documented.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Sailing Analogy (High-Level Intro)
&lt;/h2&gt;

&lt;p&gt;Working with AI on code is like sailing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compass&lt;/strong&gt; → Keeps you oriented to true north (goals, requirements, assumptions).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steering Wheel&lt;/strong&gt; → Lets you pivot, tack, or hold steady (decide continue vs. change).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Destination Map&lt;/strong&gt; → Ensures the journey is recorded (reusable, reproducible outcomes).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This framework grew out of real-world experience. It’s not brand new theory, but a way to formalize a shared language for teams working with AI.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Compass (Revalidation)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; keep alignment with goals and assumptions.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Template (copy/paste):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What’s the primary goal?
&lt;/li&gt;
&lt;li&gt;What’s the secondary/nice-to-have goal?
&lt;/li&gt;
&lt;li&gt;Which requirements are mandatory vs optional?
&lt;/li&gt;
&lt;li&gt;What are the current assumptions? Which may be invalid?
&lt;/li&gt;
&lt;li&gt;Has anything in the context changed (constraints, environment, stakeholders)?
&lt;/li&gt;
&lt;li&gt;Are human and AI/system understanding still in sync?
&lt;/li&gt;
&lt;li&gt;Any signs of drift (scope creep, contradictions, wrong optimization target)?
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 2: Steering Wheel (Course Correction)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; evaluate if we should continue, pivot, or stop.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Template (copy/paste):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For each assumption: what if it’s false?
&lt;/li&gt;
&lt;li&gt;Does an existing tool/library cover ≥80%?
&lt;/li&gt;
&lt;li&gt;Does this map to an existing framework/pattern (ADR, RFC, design template)?
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Alternatives:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different algorithm/data structure?
&lt;/li&gt;
&lt;li&gt;Different architecture (batch vs streaming, CPU vs GPU, local vs distributed)?
&lt;/li&gt;
&lt;li&gt;Different representation (sketches, ML, summaries)?
&lt;/li&gt;
&lt;li&gt;Different layer (infra vs app, control vs data plane)?
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fit with requirements.
&lt;/li&gt;
&lt;li&gt;Complexity (build &amp;amp; maintain).
&lt;/li&gt;
&lt;li&gt;Time-to-value.
&lt;/li&gt;
&lt;li&gt;Risks &amp;amp; failure modes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Other checks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overhead vs value: is the process slowing iteration?
&lt;/li&gt;
&lt;li&gt;Niche &amp;amp; opportunity: is this idea niche or broadly useful? Where does it fit in the landscape?
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Kill/Go criteria:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kill if effort &amp;gt; value, assumptions broken.
&lt;/li&gt;
&lt;li&gt;Go if results justify effort or uniqueness adds value.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Next step options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continue current path.
&lt;/li&gt;
&lt;li&gt;Pivot to alternative.
&lt;/li&gt;
&lt;li&gt;Stop and adopt existing solution.
&lt;/li&gt;
&lt;li&gt;Run a 1-day spike to test a risky assumption.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 3: Destination (Reverse Prompt)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; capture the outcome in reusable, reproducible form.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Template (copy/paste):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instructions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restate my request so it can be reused to regenerate the exact same code and documentation.
&lt;/li&gt;
&lt;li&gt;Include a clear summary of the key idea(s), algorithm(s), and reasoning that shaped the solution.
&lt;/li&gt;
&lt;li&gt;Preserve wording, structure, and order exactly — no “helpful rewrites” or “improvements.”
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Reverse Prompt (regeneration anchor)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Problem restatement (1–2 sentences).
&lt;/li&gt;
&lt;li&gt;Key algorithm(s) in plain language.
&lt;/li&gt;
&lt;li&gt;Invariants &amp;amp; assumptions (what must always hold true).
&lt;/li&gt;
&lt;li&gt;Interfaces &amp;amp; I/O contract (inputs, outputs, error cases).
&lt;/li&gt;
&lt;li&gt;Config surface (flags, environment variables, options).
&lt;/li&gt;
&lt;li&gt;Acceptance tests / minimal examples (clear input → output pairs).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;High-Level Design (HLD)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Purpose: what the system solves and why.
&lt;/li&gt;
&lt;li&gt;Key algorithm(s): step-by-step flow, core logic, choice of data structures.
&lt;/li&gt;
&lt;li&gt;Trade-offs: why this approach was chosen, why others were rejected.
&lt;/li&gt;
&lt;li&gt;Evolution path: how the design changed from earlier attempts.
&lt;/li&gt;
&lt;li&gt;Complexity and bottlenecks: where it might fail or slow down.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Low-Level Design (LLD)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structure: files, functions, modules, data layouts.
&lt;/li&gt;
&lt;li&gt;Control flow: inputs → processing → outputs.
&lt;/li&gt;
&lt;li&gt;Error handling and edge cases.
&lt;/li&gt;
&lt;li&gt;Configuration and options, with examples.
&lt;/li&gt;
&lt;li&gt;Security and reliability notes.
&lt;/li&gt;
&lt;li&gt;Performance considerations and optimizations.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Functional Spec / How-To&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Practical usage with examples (input/output).
&lt;/li&gt;
&lt;li&gt;Config examples (simple and advanced).
&lt;/li&gt;
&lt;li&gt;Troubleshooting (common errors, fixes).
&lt;/li&gt;
&lt;li&gt;Benchmarks (baseline numbers, reproducible).
&lt;/li&gt;
&lt;li&gt;Limits and gotchas.
&lt;/li&gt;
&lt;li&gt;Roadmap / extensions.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Critical Requirements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always present HLD first, then LLD.
&lt;/li&gt;
&lt;li&gt;Emphasize algorithms and reasoning over just the raw code.
&lt;/li&gt;
&lt;li&gt;Clearly mark discarded alternatives with reasons.
&lt;/li&gt;
&lt;li&gt;Keep the response self-contained — it should stand alone as documentation even without the code.
&lt;/li&gt;
&lt;li&gt;Preserve the code exactly as it was produced originally. No silent changes, no creative rewrites.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When &amp;amp; Why to Use Each
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Compass (Revalidation):&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use at the start or whenever misalignment is suspected (context drift, new requirements).
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Steering Wheel (Course Correction):&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use at milestones or retrospectives to decide continue, pivot, or stop.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Destination (Reverse Prompt):&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use at the end of a cycle/project to capture reproducible documentation &amp;amp; handover artifacts.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  References &amp;amp; Correlations
&lt;/h2&gt;

&lt;p&gt;This framework is simple, but it builds on proven practices:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Systems Engineering: Verification &amp;amp; Validation (build the right thing).
&lt;/li&gt;
&lt;li&gt;Agile: Sprint reviews (revalidation), retrospectives (course correction).
&lt;/li&gt;
&lt;li&gt;Lean Startup: Pivot vs. persevere decisions.
&lt;/li&gt;
&lt;li&gt;Architecture Practices: ADRs (decision rationale, alternatives).
&lt;/li&gt;
&lt;li&gt;AI Prompt Engineering: Reusable prompt templates &amp;amp; libraries.
&lt;/li&gt;
&lt;li&gt;Human-in-the-Loop Design: Oversight to prevent drift in AI systems.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By combining them under a sailing metaphor, the framework becomes:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to remember.
&lt;/li&gt;
&lt;li&gt;Easy to communicate inside teams.
&lt;/li&gt;
&lt;li&gt;Easy to apply in AI-assisted coding where drift, misalignment, and reusability are everyday challenges.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Closing Note
&lt;/h2&gt;

&lt;p&gt;Think of this as a playbook, not theory. Next time in a session, just say:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;“Compass check”&lt;/strong&gt; → Revalidate assumptions/goals.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;“Steering wheel”&lt;/strong&gt; → Consider pivot/alternatives.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;“Destination”&lt;/strong&gt; → Capture reproducible docs.
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>promptengineering</category>
      <category>softwareengineering</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
