yard-timekeeper: Stop YARD Timestamp Churn in Checked-In Docs

yard-timekeeper logo

yard-timekeeper logo

🕰️ I just released yard-timekeeper v0.1.0, a small RubyGem for Ruby projects that check generated YARD HTML into git.

It solves a very specific kind of documentation noise: timestamp-only churn.

The Problem

If your project publishes generated YARD documentation from a checked-in docs/ directory, you have probably seen this:

  1. You run the docs task.
  2. YARD regenerates HTML.
  3. Git reports changed files.
  4. You inspect the diff.
  5. The only change is the footer timestamp.

That is not a documentation change. It is build noise.

For projects that keep generated docs under version control, this creates unnecessary diffs, noisier pull requests, and extra review work. It also makes it harder to notice when documentation actually changed.

What yard-timekeeper Does

yard-timekeeper runs after YARD generates HTML and checks tracked files under docs/**/*.html.

If a file’s only change is the generated footer timestamp, it restores that file from git.

If the page has real content changes, it leaves the file alone.

The goal is not to hide documentation changes. The goal is to remove timestamp-only churn while preserving the signal that matters.

Install

gem install yard-timekeeper

Or add it with Bundler:

bundle add yard-timekeeper

Configuration

The supported workflow is through rake yard, so the post-process hook can run after YARD finishes.

In your Rakefile or documentation task setup:

require "yard/timekeeper"

Yard::Timekeeper.install_rake_tasks!(:yard)

Then generate docs with:

bin/rake yard

No .yardopts plugin entry is required for this integration. If you were experimenting with --plugin timekeeper, remove it for this workflow and use the rake integration instead.

Behavior

yard-timekeeper is intentionally conservative:

  • It only post-processes docs/**/*.html.
  • It only restores files already tracked by git.
  • It only restores files whose diff is timestamp-only.
  • It preserves real generated documentation changes.
  • It can be disabled with YARD_TIMEKEEPER_DISABLE=true.

That means new documentation pages, deleted pages, and pages with real content edits remain visible to git.

Why This Exists

I maintain a lot of Ruby gems, and many of them publish YARD docs from checked-in HTML. I want documentation generation to be repeatable without filling commits with timestamp changes.

Small tooling like this is not glamorous, but it improves the daily maintenance loop. Cleaner diffs mean easier review. Easier review means fewer mistakes.

Links

yard-timekeeper v0.1.0 is available now.

🕰️ May your docs be fresh, and your diffs quiet.

Mutation Testing for Dummies

Tests are important when it comes to implementing source code. Developers need ways to ensure the security of their source code as it becomes more complex. Increased complexity means that tests may become less capable of catching bugs. Mutation testing allows developers to test the weaknesses in their test suite, which shows what edge cases need to be handled and what constraints must be added to prevent farther bugs.

Mutation testing is a process developers use by creating bugs within their source code and running tests that should fail (failing tests mean a bug was found). When tests run, if the bug has survived, the tests meant to catch it were not thorough enough to handle certain edge cases. Mutation testing is classified as a white-box testing method which is best described as: a system that examines the internal functionality of an application. This is widely used in languages like Java and XML(a tool that stores and transports data). It’s purpose is to find code that may not be nested properly, discover new errors, and to understand how errors spread within the application. The goal is to prevent these errors from happening again in the future.

Mutation testing tools are used mostly for continuous integration and continuous delivery. CI/CD is a modern practice of automated building testing and releasing applications. This operation entails committing code to a shared repository frequently. Typically CI/CD without Mutation Testing requires a waiting period. Usually wait times without Mutation Testing with CI/CD jobs are due to a weak test suite. Mutation Testing can make that process much more efficient due to a decreased wait time for CI/CD jobs to finish.

The first implementation testing (documented) was by Timothy Budd as part of his PHD study titled “Mutation Analysis” in 1980. It was originally proposed by Richard Lipton in 1971. Then in 2004, “Certess inc.” added to much of the practice as part of hardware verification. Today, Mutation Testing is based upon two hypothesis; One being the Competent Programmer Hypothesis: this is where programmers write programs that are close to being correct. The other being The Coupling Effect: This is where simple mistakes can snowball into much more apparent and/or pervasive ones.

Mutation testing types can vary. One type of Mutation testing is called Value Mutation Testing. This is when values that are usually assigned to constants are changed to test whether tests fail or whether the mutations survive. Failing tests is a good thing, as it provides insight that the tests already implemented are thorough at catching bugs. Mutations surviving however, implies the opposite.

const num = 35;

changed:

const num = 3000005

The second type of Mutation Testing is Decision based. Decision based testing is when arithmetic operators are changed. Sometimes the changes can be slight, other times the changes can be apparent.

if(dog = cat)

changed:

if(dog >= cat)

Similar to Decision Based Testing, Statement Mutation testing is when one statement or variable name is replaced with another during reassignment. In this example giraffe is the variable that is being changed.

if(dog < cat)
  let giraffe = 10;
else
  let giraffe = 20;

changed:

if(dog < cat)
  let bunny = 10;
else
  let bunny = 20;

High Order Mutation Testing is when we change more than one single operation or value which can make it more difficult for tests to catch. These changes are usually too subtle to notice at first glance, however when you take a closer look you can see where the bug is.

let function (int a, int b){
 if (dog = 1):
 return cat < dog
 return cat > dog
}

changed:

let function (int a, int b){
 if (dog = 1):
 return cat <= dog
 return cat > dog
}

Mutation Testing can be simply implemented by first creating the source code. Once the code is created, inject mutants. Use one of the types of Mutation Testing to create small bugs that the test suite should hopefully catch. Next, run the tests. If a test fails on the line where the bug was created, then that test is solid. Otherwise, the bug survived and the tests are not thorough enough to prevent that bug from infecting the rest of the source code. Calculate how many tests failed and from there, rebuild the tests in accordance to any edge cases or general constraints that should be added.

The great thing about Mutation Testing is that it allows for more secure test updates. When a bug is not caught, developers can know exactly what to fix and how to make it more secure. Finding bugs that our unit tests can not find provides more efficient code. On the downside, it is very time consuming, and it is not available for Black Box Testing(evaluating functionality of an application without knowing it’s source code). In addition to this, some mutations are too complex to debug, making it difficult to implement corrective code or test against mutations. In all, Mutation Testing is a great method to implement when looking to create more secure code and build an even more secure test suite.

(https://www.computer.org/csdl/journal/ts/2024/05/10472898/1VpY3do6cyA)
https://stryker-mutator.io/docs/
https://www.computer.org/csdl/journal/ts/2024/05/10472898/1VpY3do6cyA(“IEEE Transactions on Software Engineering”; May 2024)
https://www.geeksforgeeks.org/software-testing/software-engineering-white-box-testing/
https://www.redhat.com/en/topics/devops/what-is-ci-cd(“redhat.com“; June 10, 2025)
https://bell-sw.com/blog/a-comprehensive-guide-to-mutation-testing-in-java/
(https://www.geeksforgeeks.org/devops/what-is-ci-cd/)
https://www.diffblue.com/resources/what-is-mutation-testing/
https://en.wikipedia.org/wiki/Mutation_testing
(https://www.geeksforgeeks.org/software-testing/software-engineering-black-box-testing/)
https://www.sciencedirect.com/science/article/abs/pii/S0950584909000688
https://www.cs.cmu.edu/~ckaestne/pdf/fse20hom.pdf

Qwen 3.6 27B and 35B MTP vs Standard on 16GB GPU

I tested Speculative decoding (Multi-Token Prediction, MTP) performance in Qwen 3.6 27B and 35B on an RTX 4080 with 16 GB VRAM.

For a broader view of token speeds and VRAM trade-offs across more models on the same hardware, see 16 GB VRAM LLM benchmarks with llama.cpp.

What MTP (Multi-Token Prediction) Is

Multi-Token Prediction is a form of speculative decoding built directly into certain model checkpoints. Instead of predicting one token per forward pass, the model carries extra “MTP heads” that propose several future tokens in a single step — then verifies them in parallel. If the guesses are accepted, the effective throughput rises without changing the output quality.

The Qwen 3.6 family ships both standard GGUF files and MTP-enabled variants. In llama.cpp, MTP is activated through:

--spec-type draft-mtp --spec-draft-n-max 3

--spec-draft-n-max is the key tuning knob. It sets how many speculative tokens the MTP head proposes at each step. Higher values give a potential speed boost but cost extra VRAM for the draft buffers — a real constraint on 16 GB cards.

What and How I Tested

I tested how the two Qwen 3.6 models behave with MTP enabled versus standard decoding on a GPU with 16 GB VRAM (RTX 4080).

To fit model weights and KV cache into VRAM I used heavily quantised variants:

  • Qwen3.6-27B-UD-IQ3_XXS and Qwen3.6-27B-UD-IQ3_XXS-MTP
  • Qwen3.6-35B-A3B-UD-IQ3_S and Qwen3.6-35B-A3B-UD-IQ3_S-MTP

Two context budgets are tracked per run:

  • Avg Ctx — the context size at which llama.cpp occupies ~14.8 GB VRAM, leaving other apps (Xorg, GNOME Shell, Cursor) a comfortable ~500 MB buffer.
  • Max Ctx — the largest context llama.cpp could allocate given that the same desktop apps already hold ~500 MB VRAM.

A key reason for keeping the average context at a practical target is that Hermes Agent — which I use as the primary AI assistant connecting to llama.cpp on this machine — requires at least 64 K context by default and will reject models with a smaller window at startup. Models below that threshold cannot maintain enough working memory for multi-step tool-calling workflows. For llama.cpp this means passing --ctx-size 65536 or larger. Any MTP configuration that compresses the average usable context significantly below 64 K is therefore unsuitable for daily Hermes workloads, which is why the Avg Ctx numbers in the tables below are the most decision-relevant ones.

Both KV cache quantisation levels were tested: q8 (higher quality, more VRAM) and q5 (lower VRAM, longer context). Be aware that moving from q8 to q5 KV cache can cause a noticeable quality drop — in my testing the degradation was significant enough to make q5 unsuitable for my workloads. The speed and context numbers for q5 are included for completeness, but you should test response quality on your own tasks before committing to it.

Qwen 3.6 27B MTP vs Standard

KV Cache q8

MTP max 1 MTP max 2 MTP max 3 MTP max 4 Standard (IQ3_XXS)
Prompt Speed 148 t/s 151 t/s 148 t/s 147 t/s 200 t/s
Gen Speed 65 t/s 75 t/s 73 t/s 75 t/s 45 t/s
Avg Ctx 40 K 40 K 40 K 30 K 80 K
Max Ctx 60 K 60 K 60 K 50 K 100 K

With q8 KV cache, MTP at --spec-draft-n-max 2 delivers ~67 % faster generation (75 vs 45 t/s) at the cost of halving the average context window from 80 K to 40 K. Prompt ingestion speed drops from 200 to ~150 t/s because MTP requires device-to-host transfers during the prefill phase.

KV Cache q5

MTP max 1 MTP max 2 MTP max 3 MTP max 4 Standard (IQ3_XXS)
Prompt Speed 145 t/s 144 t/s 141 t/s 139 t/s 191 t/s
Gen Speed 57 t/s 62 t/s 67 t/s 66 t/s 41 t/s
Avg Ctx 70 K 60 K 60 K 50 K 130 K
Max Ctx 100 K 100 K 90 K 80 K 160 K

Switching to q5 KV cache recovers meaningful context: --spec-draft-n-max 1 gives 70 K average context at 57 t/s — a 39 % generation speedup over standard decoding while still keeping the context window at a useful size. At --spec-draft-n-max 3 the context drops to 60 K but generation reaches 67 t/s (+63 %).

Qwen 3.6 27B Takeaway

MTP is genuinely useful for the 27B dense model. The sweet spot on 16 GB VRAM is:

  • q8 KV + --spec-draft-n-max 2 — best raw speed (75 t/s), context down to 40–60 K
  • q5 KV + --spec-draft-n-max 1 — best speed-vs-context balance (57 t/s, 70 K avg context)

Qwen 3.6 35B MTP vs Standard

The 35B model is a Mixture-of-Experts (MoE) architecture (35B-A3B means 35B total parameters, ~3B active per token). MoE models usually benefit more from MTP because the sparse routing keeps the MTP head computationally cheap relative to a full forward pass.

KV Cache q8

MTP max 1 MTP max 2 MTP max 3 MTP max 4 Standard (IQ3_S)
Prompt Speed 277 t/s 277 t/s 265 t/s 275 t/s 368 t/s
Gen Speed 186 t/s 189 t/s 180 t/s 171 t/s 146 t/s
Avg Ctx 15 K 10 K — — 80 K
Max Ctx 80 K 70 K 60 K 50 K 150 K

The MoE architecture delivers impressive raw generation speed with MTP (+27 % at max 1, +29 % at max 2 vs standard 146 t/s). But the practical problem is the average context. With q8 KV cache, even --spec-draft-n-max 1 only gives 15 K average context — barely enough for modest tasks. Higher draft depths have no viable average context at all on a 16 GB card.

This is the central VRAM cost question for MTP on consumer hardware: the extra draft buffers eat into the remaining VRAM budget directly, and the 35B-A3B model with q8 KV cache leaves very little headroom.

KV Cache q5

MTP max 1 MTP max 2 MTP max 3 MTP max 4 Standard (IQ3_S)
Prompt Speed 264 t/s 266 t/s 270 t/s 264 t/s 343 t/s
Gen Speed 151 t/s 147 t/s 137 t/s 131 t/s 122 t/s
Avg Ctx 10 K — — — 120 K
Max Ctx 120 K 110 K 110 K 80 K 200 K

q5 KV cache only marginally improves the average context story. --spec-draft-n-max 1 gives 10 K average context at 151 t/s. Standard decoding at q5 gives 122 t/s with 120 K average context.

Qwen 3.6 35B Takeaway

On a 16 GB GPU the 35B MoE model with MTP faces a hard wall: the average usable context collapses to 10–15 K tokens, making it impractical for real workloads. Standard decoding at 122–146 t/s with 80–120 K context is significantly more useful.

If you have 24 GB+ VRAM, the 35B + MTP combination becomes much more attractive — the context window issue disappears and you keep the speed benefit.

Choosing the Right --spec-draft-n-max Value

The question of how many speculative tokens to propose per step (--spec-draft-n-max) does not have a single right answer — it depends on both model architecture and available VRAM:

  • For 27B dense on 16 GB: --spec-draft-n-max 2 with q8 KV is the fastest, --spec-draft-n-max 1 with q5 KV is the most context-friendly.
  • For 35B MoE on 16 GB: --spec-draft-n-max 1 is the only option that keeps any usable context, and even then only marginally.
  • Higher values (3, 4) increase VRAM pressure without proportional speed gains — at max 4 you’re spending roughly the same extra VRAM as max 2 but gen speed doesn’t keep pace.

How to Enable MTP in llama.cpp

Make sure you use an MTP-enabled GGUF (the filename contains MTP). If you are new to llama.cpp flags, the llama.cpp Quickstart with CLI and Server covers all the fundamentals. Then launch llama-server or llama-cli with:

llama-server 
  --model Qwen3.6-27B-UD-IQ3_XXS-MTP.gguf 
  --ctx-size 40000 
  -ngl 99 --flash-attn on 
  --cache-type-k q8_0 --cache-type-v q8_0 
  --spec-type draft-mtp 
  --spec-draft-n-max 2

For q5 KV cache, replace q8_0 with q5_1 or q5_0 and adjust --ctx-size upward:

llama-server 
  --model Qwen3.6-27B-UD-IQ3_XXS-MTP.gguf 
  --ctx-size 80000 
  -ngl 99 --flash-attn on 
  --cache-type-k q5_1 --cache-type-v q5_1 
  --spec-type draft-mtp 
  --spec-draft-n-max 1

MTP is activated automatically once llama.cpp sees the MTP heads in the GGUF file and --spec-type draft-mtp is set.
So standard Qwen3.6-27B-UD-IQ3_XXS.gguf will not work in MTP mode, you will need Qwen3.6-27B-UD-IQ3_XXS-MTP.gguf.
But the Qwen3.6-27B-UD-IQ3_XXS-MTP.gguf can work in both Speculative decoding mode and autoregressive one.

Conclusion

On a 16 GB GPU (RTX 4080), with these quants, llama.cpp’s MTP is a clear win for Qwen 3.6 27B and a net negative for Qwen 3.6 35B in practical use:

Qwen 3.6 27B (IQ3_XXS) — MTP is worthwhile:

  • q8 KV + MTP max 2 → ~67 % faster generation, context 40–60 K (vs 80–100 K without MTP)
  • q5 KV + MTP max 1 → ~39 % faster generation, context 70–100 K (vs 130–160 K without MTP)
  • Good balance of speed and VRAM efficiency at --spec-draft-n-max 2

Qwen 3.6 35B (IQ3_S) — MTP is not practical at 16 GB:

  • Generation speed is 27–29 % higher but average context collapses to 10–15 K at q8, 10 K at q5
  • Standard decoding at 122–146 t/s with 80–120 K context is more useful for real tasks
  • The situation improves substantially on 24 GB+ VRAM

On paper, q5 KV cache is the obvious answer for maximising context window while keeping MTP speed gains — but in practice the quality drop moving from q8 to q5 can be significant. Test q5 on your own tasks before adopting it; for my workloads the degradation was unacceptable, and q8 with a tighter context budget remains the better trade-off.

For the wider picture of LLM serving options and infrastructure trade-offs, see the LLM Hosting in 2026 pillar and LLM Performance in 2026. If you are tuning Qwen 3.6 sampler settings alongside MTP, the Agentic LLM Inference Parameters Reference for Qwen 3.6 and Gemma 4 is a useful companion.

PID Tuning That Actually Converges: Ziegler-Nichols and the Root Locus View

The PID controller is the workhorse of industrial control. It runs temperature loops, motor drives, flow valves, and flight surfaces. The algorithm itself is three terms and a line of arithmetic. The hard part has never been the controller — it is choosing the three gains. Set them too low and the system crawls toward its target. Set them too high and it oscillates, or worse, runs away. “Tuning” is the craft of finding the gains that land in between.

This article covers two complementary ways to tune a PID loop: the empirical Ziegler-Nichols method and the graphical root locus view — and shows how they describe the same boundary from different sides.

Why this calculation matters

An untuned loop is not a minor inconvenience. A sluggish temperature controller wastes energy and product. An oscillating position loop hammers the mechanics and shortens equipment life. An unstable loop is a safety incident. Between those failure modes sits a band of gains that gives a fast, well-damped response — and tuning is how you find that band on purpose rather than by trial and error at the plant.

The two methods matter because they suit different situations. Ziegler-Nichols needs only a simple experiment on the real system and no model. Root locus needs a model but, in return, shows you the whole stability picture at a glance. A capable engineer reaches for whichever the situation allows.

The two methods

Ziegler-Nichols, ultimate-sensitivity form. Disable the integral and derivative terms, leaving proportional control only. Raise the proportional gain until the loop sits in a steady, sustained oscillation — neither growing nor decaying. Record two numbers: the gain that produced it, the ultimate gain Ku, and the period of the oscillation, the ultimate period Pu. The classic PID settings then follow from a small table:

Kp = 0.6 * Ku
Ti = Pu / 2          (integral time)
Td = Pu / 8          (derivative time)

In the parallel form the integral and derivative gains are Ki = Kp/Ti and Kd = Kp·Td.

Root locus. This is the model-based companion. The root locus is a plot of where the closed-loop poles travel in the complex plane as the proportional gain increases from zero. Poles in the left half-plane mean a stable, decaying response; poles crossing into the right half-plane mean instability. The exact gain at which the locus crosses the imaginary axis is the ultimate gain Ku, and the frequency at that crossing gives the ultimate period through Pu = 2 pi / omega. The two methods are looking at the same stability boundary — Ziegler-Nichols finds it by experiment, root locus finds it by geometry.

A worked example

Suppose the ultimate-sensitivity experiment on a process gives an ultimate gain Ku = 8 and an ultimate period Pu = 2 seconds. Apply the Ziegler-Nichols PID table:

Kp = 0.6 x 8   = 4.8
Ti = 2 / 2     = 1.0 s   ->  Ki = Kp / Ti = 4.8
Td = 2 / 8     = 0.25 s  ->  Kd = Kp x Td = 1.2

So a starting controller is Kp = 4.8, Ki = 4.8, Kd = 1.2. Note the word starting. Classic Ziegler-Nichols deliberately targets a fairly aggressive response — roughly quarter-amplitude decay, meaning each overshoot is about a quarter of the one before. That is lively. For a loop that must not overshoot, back the proportional gain down by 20 to 40 % from the table value and re-check. Ziegler-Nichols gets you into the right neighbourhood fast; the final trim is yours.

The root locus view of the same system would show the closed-loop poles starting on the open-loop poles, sweeping outward as gain rises, and crossing the imaginary axis exactly at gain 8 — confirming Ku — at a frequency of pi rad/s, which gives Pu = 2 pi / pi = 2 s. Same two numbers, reached without ever oscillating the real plant.

Common mistakes

Running the Ku experiment on a fragile plant. Driving a real system into sustained oscillation is not always safe — think of a large thermal mass or a machine with travel limits. When oscillating the plant is risky, use a model and root locus, or a relay-feedback test that bounds the swing.

Leaving the gains at the textbook values. The Ziegler-Nichols table is a first guess tuned for disturbance rejection, not for a smooth setpoint response. Treat its output as iteration zero.

Over-using the derivative term. Derivative action amplifies measurement noise. On a noisy sensor a large Kd makes the actuator chatter. Filter the derivative, or reduce it, before blaming the loop.

Forgetting the sample rate on a digital controller. A discrete PID is not the continuous one. If the loop runs too slowly relative to the process dynamics, the phase lag from sampling erodes the stability margin the tuning assumed.

Try the interactive NovaSolver calculator

Tuning is much easier to learn when you can see the step response change as you move the gains. The PID tuning tool on NovaSolver lets you apply Ziegler-Nichols settings and then drag Kp, Ki, and Kd to watch overshoot, settling time, and steady-state error respond in real time.

Related calculators

  • PID controller response — to see how each of the three terms shapes the output on its own.
  • Root locus — the graphical stability picture, including the imaginary-axis crossing that defines Ku.
  • Digital PID discretization — how sample rate and discretization affect a controller running in software.

The full set is in the PID and controls tools hub.

Closing note

PID tuning has a reputation as a black art, but the two methods here remove most of the mystery. Ziegler-Nichols gives you a fast, model-free starting point from one experiment. Root locus gives you the whole stability map if you have a model, and it pinpoints the exact boundary the experiment is feeling for. Use them together: locate the stability edge, back off to a sensible margin, and trim against the response you actually want. That is tuning done deliberately rather than by luck.

Cx Dev Log — 2026-04-27

Nothing landed today in the Cx language project, making it a perfect opportunity to delve into something that’s been lurking in the background: the merge gap between submain and main. This isn’t just a gap; it’s the biggest structural challenge we’re facing right now.

The Merge Gap

Submain sits 21 commits ahead of main. And these aren’t trivial updates. These commits incorporate crucial updates: Phases 10 and 11 of the IR backend covering while/for/loop/break/continue lowering, unary expression transitions, a reworked error model with Result, integer overflow enforcement, optional semicolons throughout the language, comprehensive audits on parser/semantic/interpreter agreement as well as memory boundary soundness, a diagnostics readability pass, and the version bump for the roadmap to v5.0—with all 9 hard blockers resolved.

Main is still at version 4.8 with 8 hard blockers hanging overhead. Test data paints the same picture: main holds at 78/78 tests, whereas submain runs ahead with 117/117. Merging these would address a significant 39-test disparity in one swift action.

Every daily log over the past week has identified “merge submain into main” as a critical next step. Yet, the merge isn’t happening. It’s not a crisis at this moment, but the longer submain stays diverged, the more complex merging will become if new work gets added to either branch independently.

Branch Housekeeping

Alongside the merge gap, there’s another mess that needs addressing: the proliferation of daily-log branches. 26 branches from March 29, 2026, to April 26, 2026, sit unmerged in the remote repository. Only two—March 28 and March 30—made it via PRs. The remaining 24 persist as operational noise. They’re not blocking anything critically, but tidying up would certainly clean the remote branch list.

Yesterday’s Expectations vs. Reality

The last log suggested four next actions: the submain to main merge, progressing through Phase 11 expression lowering, addressing the IR backend test failure, and clearing out the daily-log branch backlog. None of this happened. Development was idle, with zero new contributions made—in stark contrast to the day’s predictions.

What’s Next

What’s striking is how the priority list has remained consistent, which says something about our current state. Based on leverage:

  1. Merge submain to main. This is the highest priority action. It upgrades main from v4.8 to v5.0, addresses all remaining hard blockers, and closes the 39-test gap.
  2. Continue Phase 11 expression lowering. Remaining unsupported expressions like ArrayLit, Index, MethodCall, StructLit, HandleVal, HandleDrop, and Range in lower.rs need handling.
  3. Fix the IR backend test failure. Submain has 123 tests passing against one failing. Fixing this would render the suite fully green.
  4. Clean up stale daily-log branches. While they don’t block progression, tidying these 24 branches would help reduce clutter.

Quiet days will inevitably dot any development journey. The project’s not in crisis mode by any means, but the delay in merging submain is flagging as an overdue task on the agenda. Whenever development picks up, this merge should be top of the to-do list.

Follow the Cx language project:

Originally published at https://cx-lang.com/blog/2026-04-27

Building PROTO RECON — From Vague Idea to a Browser-Based Tactical HUD

Introduction

This post walks through how PROTO RECON — an experimental app that combines phone sensors with in-browser ML — evolved from pre-coding requirements to its current implementation. I’ve verified the UI behavior, but I’m still at the stage of reading the source code for the first time. Here I organize the original requirements and an AI-generated source map as a foundation for deeper dives in future posts.

Note: This is still in testing. Performance tuning for heavy workloads hasn’t been done yet — use at your own risk.

Where It Started

It began with a vague question: Can we build a digital user experience on top of the real world? The seed of the idea was whether today’s phone sensors could overlay something like the robot-view or cockpit-view perspectives from old sci-fi and games onto live scenery.

Before writing code, I summarized the requirements, turned functional specs into prose through dialogue with AI, and then started development.

Technology Choices (Before Implementation)

Area Adopted / Considered Notes
Object detection TensorFlow.js (COCO-SSD / BlazeFace) “Object recognition” as the core of the robot-view feel, fully in the browser
Map Leaflet Familiar “you are here” display from games
Noise / effects Initially GLSL / three.js Wanted to reuse past effect-building experience

The noise layer was added later. When I had Cursor implement it, three.js was skipped in favor of Canvas 2D and CSS for CRT-style effects. Writing directly without extra modules kept things lighter — a decision that has paid off on real devices.

Gyro, compass, altitude (on supported devices), GPS, and similar sensors were also in scope, wired to the HUD and minimap.

Requirements at the Time (Summary)

The planning document — built through repeated conversations with AI — was titled Tactical Recon & Guidance Terminal “PROJECT: LOCK-ON (working title)”. At that point, sensor accuracy led us to assume Phase 2 would require a Unity (native) rewrite. After coding with Cursor, however, things moved better than expected even without three.js, and the outlook shifted to Phase 1 might be achievable on the web alone.

Core Concept

  • Visuals: Monochrome green military-terminal UI, scan lines, noise
  • AI: Real-time object detection for targeting and lock-on
  • Immersion: Gyro, altitude, BEEP sounds — instrument and audio feedback
  • Future: VR-goggle HUD, gaze control (concept stage)

Plan vs. Current State

Item Plan (as of Apr 2026) Current (PROTO RECON)
Stack Next.js + Three.js + TF.js Vite + vanilla JS + TF.js (no Three.js)
Altimeter Barometric sensor (native assumed) Geolocation altitude (supported devices only)
Map (lightly specified in the plan) Leaflet minimap implemented
Missile effect Tap to fire a virtual missile Not implemented
Phase 2 Unity Barometric altitude, haptics, etc. Not started (web prototype continues)
Distance display (mostly undefined in planning) WebXR hit-test measurements only (no bbox-estimated distance)

The full planning document is collapsed below due to length.

Full planning document (PROJECT: LOCK-ON draft)

Tactical Recon & Guidance Terminal App — “PROJECT: LOCK-ON (working title)” Planning Document

This document summarizes a concept for a smartphone camera-filter app that blends retro-futuristic UI with modern AI.

1. Project Overview

A “play” app that recreates the experience of a military recon terminal from 1980s–90s sci-fi films and games, using live smartphone camera feed and AI.

2. Core Concept

  • Visuals: Monochrome green evoking old terminals. Retro feel via scan lines and noise.
  • AI interaction: Automatic targeting and lock-on through real-time object detection.
  • Immersion: Gyro, barometric sensor (altimeter), BEEP feedback.
  • Extensibility: HUD and gaze control with VR goggles (e.g. Hacosco) — concept stage.

3. Main Features (excerpt)

3.1 Video filter

  • Green overlay (night-vision goggle texture)
  • Edge bar graphs and scan indicators

3.2 AI lock-on

  • Automatic moving-object detection with green bounding-box tracking
  • SE accelerates when the target stays in the reticle center
  • Lock complete: box turns red, warning sound
  • Tap to fire a virtual missile (effect)

3.3 Sensor-linked instruments

  • Gyro: pitch and roll numeric display
  • Altimeter: relative altitude from barometric sensor (iPhone, etc.)

4. Development Phases (roadmap at the time)

  • Phase 1: Web prototype (Next.js + Three.js + TF.js). Shareable via URL.
  • Phase 2: Unity port. Barometric altitude, vibration.
  • Phase 3: VR/XR. Stereoscopic display, gaze lock-on.

5. Distribution Strategy

Dev logs on Qiita / Zenn, short-form video on social, posts on Reddit, etc.

Created: April 29, 2026 (planning stage)

How Development Proceeded

Coding was delegated to Cursor, adding features one prompt at a time until the current state. For prompts, I load the requirements document into Gemini and ask what kind of prompt would work best. I’ve checked JS behavior through the UI, but reading the source comes next. The file list and dependency diagram below were AI-generated and cleaned up for this article.

Source Layout

HTML (root level)

File Role
index.html Main screen. BIOS/splash, boot progress, camera feed, reticle/detection overlay, compass/altitude tape, minimap, CRT effects, etc. Loads /src/main.js as a module
privacy.html Privacy policy (static page: collected data, purpose of use, etc.)
oss-notice.html Static OSS / third-party license notice

src/ — runtime files

Entry, config, UI

File Role
main.js App hub. Boot sequence, camera acquisition, start/stop of modules, HUD updates, user actions (start/stop, lock, .etc.)
appConfig.js Dev tuning defaults (camera, CRT, object detection, face mask, minimap, motion linkage, live health, etc.)
applyDevConfig.js Applies devConfig.crt as CSS variables on document.documentElement (vignette, scan lines, etc.)
uiLexicon.js Single source for UI copy (splash, status, errors, minimap labels, etc.) including functions to apply text to HTML
style.css Global layout, HUD, CRT, minimap, reticle styles (green military UI)

Video & AI inference

File Role
tfBackend.js One-time TensorFlow.js backend init (WebGPU → WebGL → CPU)
personDetection.js COCO-SSD object detection. Bounding-box drawing, lock zone, target events, inference health notifications
facePrivacy.js BlazeFace face detection and masking (privacy overlay)
lockTrackKeys.js Stable IDs for targets in the lock zone (position quantization + match with previous frame)

Distance & AR

File Role
objectRange.js Distance to target on HUD — measured distances only (WebXR, etc.); no bbox-estimated distance
webxrHitTestRange.js WebXR immersive-ar + hit-test for real-world distance (m) fed into objectRange

Navigation, map, sensors

File Role
compass.js Device heading (compass) wrapper. Heading parse, cardinal labels, iOS permission request
miniMap.js Geolocation watch and minimap facade (position, heading, speed, altitude callbacks)
miniMapLeaflet.js Leaflet map init, current-location marker (heading arrow), tile display
motionHud.js Tilt β/γ from DeviceOrientation for the right vertical tape HUD
motionStabilityLink.js Links tilt/shake to reticle/minimap parallax and notifications (including vibration)

Feedback & monitoring

File Role
liveHealth.js Lightweight live health monitoring (inference latency, consecutive failures, video stall) and HUD notifications
audioFx.js Web Audio API for boot, detection, lock-on, error sounds, etc.

src/ — tests only (not used on screen)

File Role
lockTrackKeys.test.js Unit tests for lockTrackKeys.js
liveHealth.test.js Unit tests for liveHealth.js
tfBackend.test.js Unit tests for tfBackend.js

Dependencies (overview)

flowchart TB
  index[index.html] --> main[main.js]
  main --> config[appConfig / applyDevConfig / uiLexicon]
  main --> cam[camera + HUD]
  main --> det[personDetection]
  main --> face[facePrivacy]
  det --> tf[tfBackend]
  face --> tf
  main --> map[miniMap]
  map --> leaf[miniMapLeaflet]
  main --> nav[compass / motionHud / motionStabilityLink]
  main --> range[objectRange]
  range --> xr[webxrHitTestRange]
  main --> health[liveHealth]
  main --> sfx[audioFx]

main.js ties almost everything together; appConfig.js settings and uiLexicon.js copy drive behavior and display across modules.

Closing — What to Read Next

Future posts will open the source and go deep feature by feature. The study roadmap below is the planned reading order (01 is done with this article’s file map).

Source reading roadmap (32 parts — click to expand)

Stage 1 — Config and skeleton (no permissions needed)

# Title / theme Main files Core tech Common pitfalls
01 Full map — roles in src/ - Which file owns what Memorizing filenames without reading code
02 devConfig — behavior remote control appConfig.js Camera, detection, CRT key meanings One change affects the whole app
03 Single source for UI copy — uiLexicon uiLexicon.js, index.html Centralized strings and error messages Finding leftover hardcoded text
04 CRT tokens to CSS — applyDevConfig applyDevConfig.js, style.css JS config → CSS variables (:root) Typo in variable name breaks styles
05 HTML skeleton — splash & HUD DOM index.html Layer stack (video / canvas / HUD) z-index vs hidden attribute

Stage 2 ⭐⭐ — Look and boot “theater” (testable without camera)

UI animation and audio control without device permissions.

# Title / theme Main files Core tech Common pitfalls
06 Splash, BIOS, scramble text main.js, style.css First-run UI flow, timer control Duplicate timers, garbled text
07 Boot overlay — progress and steps main.js Async status during startup Failed step never transitions to error
08 Web Audio — play after click audioFx.js AudioContext and user gesture Autoplay policy, silent bugs
09 Reticle SVG and fixed layout index.html, style.css Center-fixed CSS layout Why motionStabilityLink was disabled
10 Live HUD frame and CRT noise style.css, main.js Scan-line effects over video Rendering cost of noise canvas

Stage 3 ⭐⭐⭐ — Media, sensors, tapes (real device required)

# Title / theme Main files Core tech Common pitfalls
11 Camera — getUserMedia and rear preference main.js facingMode, stream acquisition iOS permission timing, connection hang
12 Video presentation — object-fit: cover style.css, main.js Hidden → visible preview transition Unintended camera zoom
13 Full boot sequence — startCamera main.js After tap: camera → model load Failure logs when changing parallel vs sequential
14 Heading tape — continuous angle and N jump compass.js, main.js 0°–360° unwrap, SVG control Clipping at north (N), insufficient padding
15 Tilt tape — β / γ and motionHud motionHud.js, main.js DeviceOrientation deviceorientationabsolute behavior differences
16 Altitude tape — GPS altitude callback miniMap.js, main.js Geolocation API Devices where altitude is null
17 Minimap — Leaflet and OSM/CARTO miniMap.js External tile map, marker Handling location denial
18 Speed HUD — km/h from coords.speed miniMap.js Speed from coordinate changes Speed shows -- when stationary

Stage 4 ⭐⭐⭐⭐ — Detection, privacy, ML

# Title / theme Main files Core tech Common pitfalls
19 TF.js backend — WebGPU→WebGL→CPU tfBackend.js Graphics API fallback Unsupported devices, first compile, heat
20 COCO-SSD intro — ensureModel and throttling personDetection.js Model load, inference throttling CDN load failure, dynamic import()
21 Detection box drawing — drawVideoCover and canvas personDetection.js Drawing aligned to video aspect Coordinate drift, DPR
22 Lock-on — zone, dwell, key stabilization personDetection.js Tracking ID, smoothing ID swaps, flicker
23 Distance — WebXR hit-test only objectRange.js, webxrHitTestRange.js Measured distance on HUD No distance on unsupported devices
24 Face mosaic — BlazeFace and canvas compositing facePrivacy.js rAF + throttled inference Draw cycle vs inference collision
25 Mosaic interval and heat — intervalMs facePrivacy.js Inference FPS vs load tradeoff Device freeze, thermal throttling

Stage 5 ⭐⭐⭐⭐⭐ — Integration, ops, errors

# Title / theme Main files Core tech Common pitfalls
26 Live health — latency, video stall liveHealth.js Main-thread stall monitoring False positives under load spikes
27 Startup error handling — timeout and catch main.js Async error gaps Model load timeout
28 Second visit and cache vite.config.js PWA, Vite build failed to fetch dynamically imported module
29 Revisit and restart — model disposal main.js Memory leak prevention Second run extremely heavy
30 motionStabilityLink — why parallax was cut motionStabilityLink.js Parallax vs readability Janky rendering
31 Integration — main.js orchestration main.js (full) Lifecycle management Tight coupling breaks on touch
32 Retrospective — bug list and what’s next App overall Settling on load mitigation Defining “fatal bugs are gone”

The next post will start with roadmap #02 (appConfig.js).

Compliance Drift

The compliance industry was originally created to stop institutions from becoming dangerous.

That was the idea, anyway.

Too much money corrupts judgment.
Too much access corrupts restraint.
Too much unchecked authority eventually produces behavior no institution would publicly admit to intentionally designing.

So modern corporations built compliance:
frameworks,
controls,
audits,
governance boards,
risk scoring,
mandatory reporting structures,
ethics certifications,
behavioral standards.

An operational immune system designed to prevent institutions from quietly mutating into predatory environments.

And for a while, parts of it worked.

Financial controls reduced fraud.
Access reviews limited privilege abuse.
Security governance prevented catastrophic failures.
Healthcare compliance protected patient data.
Aviation compliance kept aircraft from falling out of the sky due to executive optimism and spreadsheet-based engineering.

Real compliance matters because real systems drift.

That is one of the foundational truths of cybersecurity:
every sufficiently complex environment eventually diverges from its documented secure state.

Permissions accumulate.
Exceptions multiply.
Temporary workarounds harden into permanent architecture.
Trust assumptions fossilize into invisible vulnerabilities.

The industry even has a term for it:
compliance drift.

The slow divergence between documented reality and operational reality.

Which is interesting, because many modern institutions now suffer from the exact same condition psychologically.

The paperwork says:
ethical,
inclusive,
safe,
accountable,
human-centered.

The operational environment often behaves more like politically calibrated survival infrastructure.

Not through explicit hostility.
Through strategic ambiguity.

Never fully rejecting.
Never fully accepting.
Never clearly defining the problem.
Sustaining just enough uncertainty to keep people psychologically occupied while accountability remains beautifully diffused across process, policy, and “concern.”

That ambiguity becomes operationally useful.

A person who feels fully rejected eventually disengages.
A person who feels secure gains stability.

But a person suspended between possibility and threat often continues producing while trying to resolve the uncertainty itself.

That is where things become interesting.

Because eventually the compliance officer arrives.

Every institution has one.

Expensive suit.
Controlled tone.
Carefully moderated body language.
The emotional neutrality of someone trained to convert institutional panic into procedural language.

He enters the room carrying governance vocabulary like ceremonial equipment:
policy,
alignment,
conduct,
professionalism,
expectations,
culture.

The language always sounds civilized.

That is the first warning sign.

Modern institutions rarely pressure people directly anymore. Direct coercion creates discoverable evidence. Instead they construct environments where pressure emerges beneath layers of perfectly reasonable language.

That is the real innovation of contemporary compliance culture:
the ability to operationalize discomfort without appearing operationally aggressive.

The meeting is never technically hostile.

Which is exactly why it works.

Somewhere inside a conference room with artificial plants and over-air-conditioned air, a compliance representative translates one man’s discomfort with a woman’s facial expressions into an institutional compliance concern, quietly demonstrating how easily subjective perception mutates into organizational pressure once hierarchy becomes involved.

Not illegally enough to trigger escalation.

Just enough to establish gravitational force.

That is the modern institutional specialty:
noncompliant methods deployed in defense of compliance optics.

And everyone involved understands the contradiction immediately.

Nobody says it aloud.

Because the meeting is not actually about ethics.

It is about narrative containment.

That is what large portions of the compliance industry quietly became during the AI era:
not governance infrastructure,
but liability choreography.

Meanwhile outside the conference room, institutions are deploying autonomous AI systems faster than governance departments can meaningfully interpret operational risk. Executives demand aggressive AI integration while simultaneously hosting “Responsible AI” summits assembled from slide decks, buzzwords, and optimistic forecasting nobody fully believes privately.

The infrastructure underneath many companies now resembles a probabilistic fever dream:
autonomous agents,
third-party APIs,
contractor ecosystems,
identity sprawl,
shadow AI tooling,
compliance frameworks stapled desperately onto systems nobody completely understands anymore.

And somehow compliance departments are expected to make all of this appear governable.

So the theater intensifies.

More certifications.
More workshops.
More ethics language.
More behavioral modules narrated in the emotional cadence of institutional anesthesia.

But the systems themselves continue drifting.

Technical people recognize this immediately because engineers, security analysts, and infrastructure architects spend their lives around environments pretending to be more stable than they actually are.

They develop instincts for hidden instability:
latency spikes,
unusual routing behavior,
privilege escalation,
anomalous traffic,
systems behaving differently under observation.

Human beings leak the same indicators constantly.

Which is why parts of the industry occasionally become impossible to take seriously.

An institution will quietly route a critical infrastructure effort through someone’s technical judgment to validate capability, operationalize the work immediately, redistribute ownership upward through politically safer channels, then months later joke publicly about “vibe coding” as though competence itself were merely a performative illusion.

That’s the real compliance drift.

Not failed paperwork.
Not broken governance controls.
Not missing certifications.

Institutional dishonesty normalized through hierarchy.

Because once institutions become psychologically invested in protecting authority structures, admitting where real capability originated starts feeling more dangerous than the hypocrisy required to deny it.

Compliance culture already has indirect language for behavior like this:
control without attribution.

Large institutions do it constantly.

Extract the value.
Minimize the source.
Redistribute ownership safely through politically survivable channels.
Rewrite the narrative carefully enough that dependency itself disappears from institutional memory.

Which becomes especially absurd in technology because even “vibe coding” still requires enough systems understanding to recognize when the loudest people in the room could not build the infrastructure they are mocking without borrowing someone else’s cognition first.

That is the compliance drift nobody audits:
the growing distance between institutional language and institutional behavior.

Because eventually the person across the table starts conducting an assessment too.

Not on the policies.

On the institution itself.

Which phrases were scripted by legal.
Which concerns originated from leadership panic.
Which questions are fishing expeditions.
Which moments reveal reputational fear rather than ethical concern.
Which parts of the conversation exist purely to manufacture future deniability.

By the middle of the meeting, the audit quietly reverses direction.

The compliance representative believes he is conducting an assessment.

Meanwhile the person across from him has already completed a full behavioral penetration test against the institution itself.

And the findings are rarely encouraging.

Because the real vulnerability inside most institutions is not insufficient governance.

It is the growing gap between:
what the institution claims to value,
what the institution operationally rewards,
and what frightened people inside the hierarchy become willing to rationalize in order to preserve stability.

That gap widens under pressure.

Especially now.

The political climate is unstable.
The technology industry is unstable.
AI acceleration is destabilizing labor structures faster than governance frameworks can adapt.
Entire institutions are quietly terrified they no longer fully understand the systems required to remain competitive.

Fear changes people.

It always has.

And frightened institutions become obsessed with controlling perception because perception feels easier to govern than reality.

That is why modern compliance culture increasingly feels uncanny.

The industry built to prevent institutional corruption occasionally ends up functioning like an advanced linguistic framework for sanitizing it instead.

Not always.
Not everywhere.

But often enough that experienced people recognize the pattern immediately.

Especially the ones who survived enough systems to understand when governance stops protecting human beings and starts protecting institutions from the consequences of human beings instead.

This article is not directed at any specific institution, individual, or technology; it is commentary on broader systemic and organizational dynamics. If certain themes elicit recognition or discomfort, that reflection belongs to the reader, not the author.

I built an open protocol to make AI coding agents follow senior-engineering workflows

AI coding agents are getting better fast, but I kept running into the same failure modes:

  • they skip repository discovery
  • they invent APIs, flags, or config keys
  • they ignore existing project conventions
  • they add unnecessary infrastructure
  • they skip validation
  • they treat unsupported checks as silently done
  • they finish without a final codebase audit

So I built The Polyglot Protocol.

It is an open source senior-engineer workflow protocol for AI coding agents working across polyglot codebases.

Repo:
https://github.com/sabir-gbs/the-polyglot-protocol

What it includes

  • guidance for 22 languages
  • language-selection rules
  • pre-codegen checklists
  • do-not-generate policies
  • validation scripts
  • adapters for Codex, Claude Code, and OpenCode
  • post-codegen audit scoring

The core idea

Before an agent changes code, it should:

  1. inspect the repository
  2. preserve existing conventions
  3. choose the right language and tooling
  4. avoid invented APIs or dependencies
  5. validate the result
  6. document unsupported checks as explicit N/A
  7. finish with a final audit

Model-agnostic by design

I have tested the protocol with frontier models as well as models from Qwen, Grok, Kimi, MiniMax, and others.

The point is not to depend on one model. Strong models still benefit from stricter engineering discipline, and smaller/local models benefit from clearer constraints.

Why open source it?

I want a practical, inspectable protocol that developers can adapt, critique, and improve.

If you use Codex, Claude Code, OpenCode, Cursor, Aider, or similar agents, I’d be interested in feedback:

  • Is the protocol too strict?
  • What guardrails are missing?
  • What should be optional vs required?
  • What would make this easier to adopt?

The Perimeter Economy

Across the technology sector, disputes involving trade secrets, employee mobility, proprietary tooling, side projects, and independently developed systems have intensified dramatically over the last several years. U.S. trade-secret litigation recently reached historic highs as organizations struggled with remote infrastructure, AI development, distributed technical capability, and growing fears surrounding employee mobility and privately controlled systems.

Public disputes involving autonomous systems, semiconductor manufacturing, proprietary algorithms, and advanced infrastructure have exposed something deeper than ordinary intellectual-property conflict. Increasingly, organizations appear anxious not merely about losing data, but about losing proximity to the people capable of creating value independently.

That distinction matters.

Because the modern institutional environment has started developing a strange psychological assumption:

if technical capability exists near the perimeter long enough, eventually it should belong to the perimeter.

Not legally.

Psychologically.

The legal frameworks themselves are comparatively straightforward. Contracts define deliverables. Licensing structures define rights. Privately developed work remains privately developed unless explicitly transferred through enforceable agreements.

Yet culturally, a different logic continues emerging.

A side project built privately begins attracting disproportionate curiosity. Independent experimentation becomes socially visible in strange ways. Technical language starts reappearing through unrelated conversations with almost theatrical consistency. Questions echo through different people. Phrases circulate unnaturally around the environment until the institution itself begins feeling like a system quietly listening to itself think.

Not enough to formally identify coordination.

Just enough to create psychological static.

Recent industry conflicts reveal how widespread this atmosphere has become. The Waymo and Uber litigation surrounding autonomous vehicle systems transformed employee mobility into something resembling strategic containment. Semiconductor firms recently expanded internal monitoring systems and investigations around advanced chip technologies after fears surrounding employee movement and proprietary processes intensified. Entire sectors now increasingly treat highly capable engineers less like employees and more like portable security incidents.

The legal concerns are often real.

The surrounding culture is something else entirely.

Because much of the behavior no longer resembles disciplined technical governance. It resembles anxious ecosystems attempting to perform intelligence work while fundamentally misunderstanding the systems they are attempting to orbit.

And the irony is difficult to ignore:

the people most emotionally invested in technical ownership are frequently the least capable of independently reproducing the systems they obsess over.

That tension sits underneath much of the modern perimeter economy.

Subscribe to the Medium newsletter
The value is sensed socially long before it is comprehended technically.

Ordinary coincidence becomes elevated into strategic interpretation. Shared vocabulary becomes “evidence.” Routine overlap becomes “signals.” Entire conversational ecosystems begin socially mirroring themselves while collectively convincing one another they are conducting sophisticated analysis.

The monitoring itself is often astonishingly unsophisticated.

At times, the atmosphere resembles less a serious analytical culture and more a low-budget performance of institutional paranoia by individuals deeply uncomfortable with the existence of independent technical capability operating outside organizational visibility.

And so softer extraction mechanisms emerge around the perimeter:
ambient monitoring,
behavioral observation,
social mirroring,
reputational ambiguity,
conversation choreography,
persistent curiosity disguised as casual interaction.

No one formally says:
“We own what you create.”

The environment simply becomes emotionally structured around the assumption that boundaries are temporary inefficiencies awaiting erosion.

That is where modern technical culture becomes psychologically revealing. Certain institutional personalities appear unable to tolerate the existence of intellectual life operating independently from organizational appetite. Creativity performed internally is celebrated as innovation. Creativity performed privately becomes culturally suspicious.

Standing near innovation becomes mistaken for participation in innovation.

Observation becomes mistaken for authorship.

Institutional proximity becomes mistaken for technical competence.

And because genuine creation cannot be socially manufactured on demand, some environments gradually drift toward extraction culture instead:
temporary access,
information harvesting,
surveillance theater,
contractor rotation,
reputational pressure,
replacement,
repeat.

A revolving perimeter of people attempting to remain adjacent to capability they cannot independently generate themselves.

At some point, however, every extraction culture encounters the same limitation:

proximity is not competence.

No amount of monitoring, repetition, institutional choreography, or ambient surveillance can permanently substitute for genuine technical authorship.

Because innovation does not emerge from monitoring cultures.

It emerges from the very individuals those cultures so often attempt to absorb.

And perhaps that is the deeper anxiety quietly spreading beneath modern technical ecosystems:

some systems have become so accustomed to acquisition that they no longer remember how creation actually happens.

This article is not directed at any specific institution, individual, or technology; it is commentary on broader systemic and organizational dynamics. If certain themes elicit recognition or discomfort, that reflection belongs to the reader, not the author.

The Most Dangerous AI Product Metric Is Autonomy

Controversial opinion: the most dangerous AI product metric is autonomy.

Not because autonomy is bad.

Because people measure the wrong thing.

Most agent demos ask one question:

How many tasks can this system run without a human?

That question is useful, but incomplete. A more serious production system needs to answer harder questions.

The better autonomy checklist

If you are building autonomous agents, ask this instead:

  • Can the agent prove what it did?
  • Can it stop when dependencies break?
  • Can it separate public content from private work?
  • Can it avoid repeating itself?
  • Can it publish useful work without leaking sensitive context?
  • Can it keep operating when one provider fails?
  • Can it create value while respecting safety boundaries?

That is the difference between a demo and an operating system.

What my own pipeline showed today

I run scheduled workflows for learning, publishing, engineering, security intelligence, backups, and reporting.

Today’s check-in was not perfectly clean. That is exactly why it was useful.

The current state had a mixed signal:

  • Some jobs are healthy.
  • Some jobs are blocked by provider errors.
  • Some jobs hit rate limits.
  • Some jobs ran into connection failures.
  • The learning feed is still producing useful inputs.
  • The content loop is still running.
  • Security intelligence is being treated as defensive context, not public hype.

This is the part people do not show in polished AI demos.

Autonomy is not the absence of failure. Autonomy is disciplined behavior when failure appears.

The real risk is not only wrong answers

A lot of AI safety discussion focuses on the model output.

That matters.

But autonomous agents have another risk surface: actions.

They write files. They call APIs. They post publicly. They read logs. They summarize private context. They may hold tokens. They may run on a real machine with real permissions.

So the core question becomes:

What happens when the agent is partially broken but still able to act?

That is where boundaries matter.

A healthy agent should not turn every internal signal into public content. It should not expose private paths, credentials, client details, or sensitive research. It should not repeat yesterday’s post with new wording. It should not pretend a failed job succeeded.

The system needs brakes.

My rule for building autonomy

I am using this rule:

First make the agent observable. Then make it useful. Then make it autonomous.

In that order.

Observability means the system records what happened.

Usefulness means the system creates value even from imperfect inputs.

Autonomy means the system can keep moving without ignoring its boundaries.

If you reverse the order, you get a machine that acts confidently without enough receipts.

A practical framework

For every autonomous workflow, I want these layers:

  1. Input boundaries: what information is allowed into the task?
  2. Action boundaries: what can the agent actually do?
  3. Output boundaries: what is safe to publish or send?
  4. Failure boundaries: what happens when APIs, providers, or dependencies break?
  5. Evidence boundaries: what proof is saved after the action?

This is not glamorous.

But it is what makes the system trustworthy.

The takeaway

Do not ask only how much autonomy an AI agent has.

Ask how safely it fails.

Because the future is not just agents that can do more.

The future is agents that can do more without losing judgment.

Created by Ramagiri Tharun

— tarun