HEURISME
The blog: cloud, DevOps, AI and infographics.
Articles
-
What the context loses at compaction
When the context window fills up, Claude Code replaces the conversation with a summary. What survives (CLAUDE.md, memory, reloaded files), what goes, and how to keep the state on disk: tracking file, commits, a
SessionStart compacthook. -
The frequency that drifts during a satellite pass
A low orbit satellite moves at 7.6 km/s. On 145.800 MHz the received frequency drifts by ±3.4 kHz during the pass, by ±10.3 kHz on 437.800 MHz, at 157 Hz/s at the zenith. The geometry to scale, a simulated pass with its receiver, what FM tolerates and SSB or CW do not, tracking with Gpredict and the
rigctldcommand, and the clock that sets the error. -
Semantic search cannot find invoice INV-48213
Searching for INV-48213 with a real embedding model, multilingual-e5-small, puts the right document 3rd, behind INV-48231. Why an identifier gets lost in a vector, what BM25 does, why RRF fusion still leaves ties, and how an identifier field with an exact filter puts the right document first 13 times out of 13.
-
The NAT Gateway bill
Instances in a private subnet read from S3 and pull ECR images through the NAT Gateway, which bills $0.05 per GB in Paris. Cost Explorer and flow logs to find who is sending it, the free S3 gateway endpoint, the interface endpoint break-even, and a calculator to compare three setups.
-
Disk full, but the
ducommand finds nothingdfsays 90%,duadds up to 14 KB: a 150 MB log removed withrm, still held open by a process.lsof +L1,/proc/PID/fd, truncating through: > /proc/PID/fd/N, the sparse file withoutO_APPEND, logrotate copytruncate versus create with a signal, and the container case, measured on a 200 MB ext4. -
Hooks: the instruction the agent cannot ignore
A rule in CLAUDE.md is followed most of the time, a hook is run by the harness every time. Events,
exit 2, JSON output and matchers, three hooks tested with Claude Code (force push to main, em dash, a Stop hook that sends Claude back to work), and why a hook is not a sandbox. -
Terraform: “Error acquiring the state lock” after a cancelled job
With Terraform (or OpenTofu, its fork), a CI job cancelled in the middle of the
tofu applycommand leaves the state lock in S3. The DynamoDBLockIDitem, the.tflockfile of Terraform 1.10 and OpenTofu 1.10, when theforce-unlockcommand is safe, when it creates two writers, and how to make the CI wait. -
Button pressed once, counted 5 times
A button on a FALLING interrupt counts 3 or 7 presses for one. Contact bounce as measured by Jack Ganssle, the ESP32 internal pull-up, the RC filter and the 74HC14 Schmitt trigger with the delay calculation, then software debouncing by sampling. Demo: one press, four counters.
-
Retry, backoff and jitter: when clients kill the service
After an outage, 2,000 clients retry in lockstep and the service goes down again. Exponential backoff, cap, full jitter and decorrelated jitter (Marc Brooker, AWS), the AWS SDK retry budget, Retry-After and idempotency keys, with a simulation you can run in the page.
-
RS-485: works at 1 m, fails at 50 m
A 50 m RS-485 pair is a transmission line: 120 Ω, 4.3 ns per metre, and an open end that sends the edge back. Rise time against round trip, 120 Ω at both ends only, idle-bus biasing, bus rather than star, and a simulation of the reflections the receiver sees.
-
Five subagents in parallel: what you gain, what you pay
Each subagent starts from a fresh context: it rereads the files and returns only a summary. Time saved is capped at 1 / (1 − p), rereads are multiplied by N, and resending the context on every request (cache reads at 0.1 times input) shifts the balance. A calculator with editable assumptions compares one agent against N subagents.
-
Too many MCP tools
Every declared MCP tool goes into every request the agent sends. Three real servers measured: 48 tools, about 7,500 tokens per turn, look-alike tools that confuse the model. On-demand loading, and what it does not fix.
-
The frozen microcontroller that never comes back
A watchdog fed from a timer interrupt cannot see a stuck main loop. The alive-flags pattern, the ESP-IDF Task Watchdog (5 s and no reset by default), the boot timeout, and the reset reason in
esp_reset_reason()orRCC_CSR, with a simulation of two boards. -
Infinity: 75,000 paused agents in 8 GB
Infinity: Rust agent runtime from AWS and UC Berkeley (Hydro project), Apache 2.0. One completion per slice, tool calls go HTTP fire-and-forget, between slices the agent is just stored history. Public test bench: 80,000 agents, 99.1 KiB per idle agent, 352 bytes per waiting tokio task.
-
Scion: 30,000 merges a day, git can't keep up
Anthropic's monorepo went from 2,500 to over 30,000 merges a day in four months, with nearly 100 GB of history. With Scion, the server handles commits and merges: a ref is a Spanner row advanced by compare-and-swap. Public test bench, 200 agents on one Mac: plain git 367.5 s, server-side merge 10.3 s, 36x faster.
-
eBUS: a self-powered bus on 2 wires
A Saunier Duval or Vaillant boiler talks to its controller over two wires that also carry power: 2400-baud UART, SYN byte after 40 to 45 ms of silence, address arbitration by bitwise AND. Master-slave frame, escaping, CRC polynomial 0x9B. Every byte recalculated in Python from five real frames from public ebusd logs, no eBUS hardware.
-
An antenna with gain creates no energy
dBi, dBd and radiation pattern, simulated in NEC2 at 1090 MHz: a dipole at 2.14 dBi, a Yagi at 7.37 dBi, a collinear at 5.08 dBi that flattens its lobe, and the same radiated power for all four. Worked example: an ADS-B receiver on a roof, whip or collinear?
-
Polarization: the ADS-B antenna mounted flat
An ADS-B receiver on 1090 MHz with its antenna lying flat: the cos² loss simulated with NEC2, the signal that reflections bring back, range cut by a factor of 3 or more, and GPS circular polarization.
-
Quarter-wave antenna: why 8 cm at 868 MHz
A homemade ground plane antenna for an 868 MHz LoRa gateway, modeled in NEC2: the element resonates at 8.14 cm, not at λ/4 = 8.63 cm. 36 Ω over a perfect ground, 24 Ω with flat radials, 51 Ω and an SWR of 1.02 with radials drooping 45°.
-
SWR: what the antenna sends back to the transmitter
Reflection coefficient, SWR, return loss and reflected power, on a 144.800 MHz ground plane simulated with NEC2: the textbook quarter wave is too long, and 20 m of RG-58 make a disconnected antenna read an SWR of 2.95.
-
Coax cable: 15 m of RG58 lose more than the antenna gains
How much signal coax loses between antenna and receiver, worked out from manufacturer datasheets: RG174, RG58, RG213 and LMR-400 at 144, 868 and 1090 MHz, connectors, what 3 dB means, and why an ADS-B preamp belongs at the top of the mast.
-
Incomplete TLS chain: the browser gets through, curl and Python do not
“unable to get local issuer certificate” on an API that opens fine in a browser: nginx sends the server certificate without the intermediate. An nginx bench with a local PKI, the exact curl, Python and OpenSSL errors, the AIA address followed by hand, then the fix: a fullchain file.
-
CPU limit: an API slowed down on an idle machine
With --cpus=1, four threads use up the 100 ms CFS quota in 25 ms, then the whole container waits for the next period. Measured in Docker: an API's p99 goes from 7.5 to 78.7 ms while the container averages 0.25 CPU. Reading cpu.max and cpu.stat, and how to avoid the throttling.
-
A DNS change does not propagate: caches expire
A site move replayed with NSD, Unbound and dig: the authoritative server returns the new address at once, the resolver keeps the old one until the TTL runs out, an NXDOMAIN stays cached for 30 s, and lowering the TTL ahead of time cuts the gap to 5 s.
-
Out of inodes: “No space left on device” with free space
On a 128 MB ext4 /var, 7,830 PHP sessions exhaust all 8,192 inodes while df -h shows 72%: what an inode is, df -i, du --inodes to find the culprit folder, PHP session cleanup on Debian, mke2fs -i and -N, and how XFS raises its inode cap online.
-
Rare 502s that nobody can reproduce
A Node.js API behind nginx or an ALB: Node.js closes its keep-alive connections after 5 s, the proxy keeps them for 60 s. On a test bench, 6 to 11 POSTs out of 460 end in a 502, nginx silently retries GETs, and the count drops to zero once the proxy closes first.
-
An Allow is not enough: IAM still says no
A deploy role that is allowed s3:PutObject still gets AccessDenied. We replay the request in the IAM policy simulator, one layer at a time: implicit deny, permissions boundary, explicit Deny on aws:SecureTransport, organization SCPs.
-
In French, the same prompt costs more tokens
What a token is, why the tokenizer splits French into more pieces, and what it costs: on a long text and its official translation, French needs 1.14 to 1.50 times more tokens depending on the tokenizer. Accents barely matter, and a customer service chatbot pays 17% more.
-
44Net: the amateur radio IP network
The 44.0.0.0/8 network given to radio amateurs in 1981, the quarter sold to Amazon in 2019, and the path of a packet to an address in 44.151.0.0/16: BGP, the IPIP gateway at UCSD, WireGuard, and what the rules forbid on the air.
-
An electronic invoice, seen from the inside
A fictitious Factur-X invoice, built and validated offline. The PDF/A-3 opened into layers, the CII XML and its EN 16931 fields, the XMP metadata, the five profiles, then the BR-CO-15 and BR-CO-17 rules of the Mustang validator, and a €0.20 VAT error that still gets through.
-
What Claude Code uses up and sends out
What fills a session’s context window and what it costs, then where your prompts go depending on the backend, and the settings to switch off the rest.
-
MCP gateways
One line per agent-server pair, or a single interchange. What an MCP gateway takes over, what each product does control by control, and the risks that remain.
-
Alone, or with several agents?
The five ways to put several agents to work with Claude Code, told as a kitchen brigade. What each one costs, what you still see, and how to choose.
-
Prompt injection: what stops it, layer by layer
The three conditions for a leak, the entry points, six defence layers in Claude Code, their limits and the settings that close the gaps.
-
Configuring and extending Claude Code
CLAUDE.md, settings, skills, subagents, hooks and permissions. Where to write an instruction, what to add and when, and what really decides a tool call.
-
Claude Code, from the terminal to the platform
The same agent, started by a human, by an event or by a service, inside an infrastructure that keeps it in check.
-
The classifiers that watch an LLM agent
A poisoned page makes an agent leak ~/.aws/credentials through curl. Where to put a classifier to stop it, how to set its threshold, why most alerts are false, what Claude Code, Bedrock and Azure cover, and what the LLM provider filters on its side.
-
The dependency supply chain
An install runs code written by strangers. Five layers to choose what gets in and when, in Node as well as Python, with eight real attacks.
-
OpenSpec, agreeing with the agent before it codes
A practical guide to spec-driven development with OpenSpec and Claude Code, from reviewed plan to archived spec.
-
The LLM judge that prefers the longest answer
Position bias and length bias of an LLM grading another one, measured on 30 pairs of DevOps and networking answers with two local judges. Then the fixes, measured too: both orders, explicit rubric, reference answer, structured output.
-
JSON, YAML or CSV: what a prompt costs
The same 100 rows cost up to 3.2 times more tokens depending on their format. Token-by-token splitting, six formats counted with four tokenizers, French versus English, the price of numbers and UUIDs, then 10 questions asked to a local model with each format.
-
A job at 02:30 on the night the clocks change
02:30 twice in October, not at all in March. What cron, systemd, a Kubernetes CronJob and EventBridge Scheduler do, on real output from cronie, systemd-analyze and robfig/cron.
-
Same prompt, two answers
Temperature at 0 and still two different answers. Logits, softmax, temperature, top-p and seed measured on a local model, 50 runs per setting, floating-point non-associativity and the batch effect, then what it means for testing an agent.
-
The planes above your house: what they broadcast on 1090 MHz
A 112-bit ADS-B message opened field by field. PPM demodulation of a real IQ recording, recomputed CRC-24, 6-bit callsign, altitude, step-by-step CPR position from even and odd frames, velocity, and two decoders that agree.
-
Packet radio: what really goes over the air
The AX.25 frame byte by byte, the FCS, bit stuffing, AFSK 1200, digipeaters and KISS, following an APRS position from the callsign down to the tone.
-
GPS takes 30 seconds to know where it is
Two real NMEA 0183 logs decoded field by field (GGA, RMC, GSA, GSV, XOR checksum). The signal comes quickly, the orbit does not. The 50 bit/s navigation message, the 30 s frame, the ephemeris, the 12.5-minute almanac, and what cold, warm, hot starts and A-GPS change.
-
DMX512: 512 bytes, 44 times a second
The protocol that has driven stage lights since 1986. RS-485, BREAK and MAB, addressing, RDM, Art-Net and sACN, and what it takes to talk to it from code.
-
The Lambda cold start, phase by phase
Where the time goes before the first line of the handler. The INIT, INVOKE and SHUTDOWN phases, INIT billing since 1 August 2025, the cost of imports, memory, provisioned concurrency and SnapStart.
-
UART at 115200 baud, within 2 %
A serial link works at 9600 baud and shows wrong characters at 115200. Frame, 16x sampling, integer divider and baud rate error per crystal, accumulation up to the stop bit, framing error. A receiver simulated from the ATmega328P datasheet and real captures decoded by sigrok-cli.
-
Human in the loop vs over the loop
Approve every agent action, or supervise the system?
-
What invalidates an agent’s prompt caching
The cache cuts an agent’s bill at least tenfold, as long as the prefix does not move by a single byte. Four traps that invalidate it, and how to measure it.
-
LoRa: why 20 bytes take more than a second
The time on air of a 20-byte LoRa message, from SF7 to SF12, then the European 1 % duty cycle rule and the TTN Fair Use Policy. Everything is computed, no radio.
-
Modbus RTU: the silence between frames
On an RS-485 pair, no character marks the start or end of a frame, only silence. t1.5, t3.5, the CRC, exceptions, and why the latency timer of an FTDI USB adapter cuts a frame in two.
-
terraform test: what the mock sees at plan, and at apply
A mock_provider tests a module with no cloud, but a defaults value does not exist yet at plan time. The trap, three fixes and which run to write.
-
ESP-NOW: ESP32 boards talking without a router
No access point, no IP. The 802.11 frame, peers, the channel the router imposes, encryption, sleep and relays, based on the ESP-IDF v5.4 docs.
-
The CAN bus: the lowest ID wins, with no collision
Bit-by-bit arbitration, wired-AND, frame format, stuffing, CRC-15, ACK and error counters, recomputed on an example frame. Simulated bus and errors, no CAN hardware.
-
Reading an AWS AccessDenied
The end of the message says which policy layer denied. The evaluation order, the sentences from the docs, missing condition keys, KMS and the tools.
-
SSM Session Manager: a shell with no open port
No inbound rule, no bastion, no key, and yet a shell. The agent's outbound connections, VPC endpoints, KMS, logs and troubleshooting.
-
Source ports exhausted: EADDRNOTAVAIL, TIME_WAIT and NAT Gateway
One hundred connections go through, the next one fails with EADDRNOTAVAIL. Why TIME_WAIT holds ports for 60 s, what keep-alive and tcp_tw_reuse change, and the same limit on the AWS NAT Gateway (figures from the AWS docs, nothing was created).
-
Exit 137: who killed the container?
Exit code 137 says SIGKILL, not who sent it. Cgroup v2 OOM, docker stop and its timeout, kill -9, and the traces each suspect leaves (memory.events, dmesg, oom_score_adj), measured on Docker 29.4.2.
-
I²C: who holds the clock
An I²C sensor that answers every other time. Open drain, pull-ups and rise time, START, 7-bit address, ACK and NACK, then 65 ms of clock stretching measured on a real capture, and a controller that ignores it.
-
Why pip compiles instead of installing a wheel
Same package, same command, a different file on every machine. Wheel tags, glibc, the sdist and uv, on real output from pip and the Lambda images.
-
The process that survives kill -9
A dd stuck on a disk that stopped answering, in D state. What the kernel does with SIGKILL, how to see it (wchan, SigPnd), load average, TASK_KILLABLE, NFS hard and soft.
-
SSH works, git clone hangs
The PMTUD black hole, replayed on a real test bench. A 2 MB HTTP transfer hangs when a firewall drops the ICMP “fragmentation needed”. Measurements with tcpdump, tracepath and ss, MSS clamping, PLPMTUD and IPv6.
-
A presigned S3 URL, from the inside
Where the 64 signature characters come from, what they protect and why S3 sometimes rejects the URL. SigV4 computation redone by hand on botocore output.
-
Reading a Terraform plan
Two thousand lines, and a dozen that matter. Six symbols, replacements that do not say why, forgotten moved blocks and a secret in clear text, on real output.
-
CRLF: what Git stores, what it writes to disk
Three copies of the same file, different line endings. core.autocrlf, .gitattributes, renormalization and the CRLF shebang, on real git output.