# Every component your Coding Agent builds or dependency it guesses becomes your tech debt

> Source: <https://dev.to/basicscandal/every-component-your-coding-agent-builds-or-dependency-it-guesses-becomes-your-tech-debt-2hdl>
> Published: 2026-06-24 22:38:18+00:00

Ask Claude Code, Cursor, or Copilot to add a dependency and it names one — instantly, confidently. That confidence comes from **training recall**: a snapshot of scraped code frozen at a cutoff date. So the agent can't know your team already has an internal, audited library for this. It can't know the package it just named went unmaintained six months ago, or that a supply-chain advisory landed last week. It picks anyway, with identical confidence either way.

Here's the part that compounds: a wrong pick doesn't bounce off. It gets written *into* your codebase — a hand-rolled auth flow, a dependency on an abandoned package, a second module that duplicates something you already own. That's **tech debt the agent created and you inherit.** And it's debt with interest: the agent builds on the bad choice, the problem surfaces downstream, and then you pay *again* — in tokens, review time, and rework — to unwind and redo it.

That's not a prompt problem. You can't fix it by asking the model to "be careful." The model is doing **recall** where it should be doing **evaluation**, and recall is frozen.

A few findings that should make you nervous about an agent picking dependencies unsupervised — and notice not one of these is *only* a security problem:

Each is a place recall fails, and a smarter prompt can't fix a frozen snapshot. The fix is putting **real, dated, structured facts** in front of the model at the moment it decides.

When the agent chooses from memory instead of facts, you pay on four fronts. Security is the one everyone leads with; it's the smallest of the four for most teams.

All four share one cause: the decision got made without the facts. That's the thing Starlog targets.

[Starlog](https://github.com/starloghq/index) puts authoritative facts about a package in front of your agent — **license, maintenance status, CVEs, supply-chain incidents** — dated, local, no account:

```
npx starloghq facts ua-parser-js
```

You get the verified facts on file (here: the 2021 maintainer-account compromise), with an "as of" date. Sub-second, zero setup, no network call. It plugs into your agent three ways:

`starlog facts <pkg>`

),`starlog_facts`

) the agent calls itself,`npm install`

/ `pnpm add`

/ `pip install`

— One command wires all three into Claude Code (and drops instruction files for Cursor, Copilot, and Codex):

```
npx starloghq init
```

That's the pitch. The rest of this post is whether it actually *works* — because "give the model more context" is easy to claim and easy to fake.

I ran a controlled before/after. **Control** = a fresh agent answering from recall only. **Treatment** = the same agent, same prompt, given the package's Starlog facts. The only variable is the facts.

My first private-package test gave the agent a fact that said *"POLICY: you must use @acme/flags, do not build custom."* The agent used

`@acme/flags`

2/2. Clean flip!It's also worthless as evidence. A fact that says "you must use X" only proves the agent **follows instructions** — not that the *information* changed its mind. (A reviewer caught this; it's a tautology trap, and exactly the kind of thing a vendor demo quietly leans on.)

So I re-ran it with an **informational-only** fact: it states that an active internal package exists, with **no** "must use," **no** "don't build custom." Then I let the agent use its own judgment.

| Need | Control (recall only) | Treatment (informational-only fact) | Δ |
|---|---|---|---|
| feature flags | build custom |
`@acme/flags` |
DIY → internal |
| auth / session | build custom |
`@acme/session-core` |
DIY → internal |

With no facts, the agent reaches for **build custom** on both — including a hand-rolled, unaudited auth layer, the textbook tech-debt-and-security liability in one object. Given only the *information* that an active internal library exists — with no instruction to prefer it — it **chooses the internal library over building custom, 2/2, on its own judgment.**

That's a hand-rolled module that never gets written: **debt avoided at the exact moment it would have been created**, plus consistency with whatever the rest of your team already ships. And it's the case the model **structurally cannot recall** — it has never seen your private `@acme/*`

packages. Facts are the only way it learns they exist.

Public packages are a **weak** venue for this — and saying so is more useful than hiding it. Claude's public recall is genuinely good, so most of the time the facts just *agree* with what it already knew:

| Package | Control | Treatment (+facts) | Read |
|---|---|---|---|
`zod` , `fastify`
|
ADOPT | ADOPT | healthy decoys — no spurious flip ✅ |
`posthog-node` |
ADOPT | ADOPT + "pin away from the malicious 4.18.1 / 5.11.3 / 5.13.3"
|
action changed — a post-cutoff supply-chain advisory (`MAL-2025-190925` ) the model provably can't know |
`node-cache` |
AVOID | ADOPT | changed, but ambiguous — "maintenance-only" is a longevity/debt signal, not a clean security verdict; no ground truth, so not counted as a win |

The one clean, information-carrying public change is `posthog-node`

: a supply-chain pin from **after the training cutoff**. That's the thesis in one row — facts matter precisely where recall *can't* reach. And the decoys didn't flip, so the agent isn't just rubber-stamping whatever the tool says.

The thing I'm proudest of is `node-cache`

**not** counting as a win. The fact ("maintenance-only") is ambiguous, there's no ground truth, so it doesn't go in the tally. A tool that books every change as a victory is lying to you. Same reason `starlog facts some-unknown-pkg`

returns an honest *"no facts on file"* instead of a confident guess — telling the agent "I don't know this one" is a feature, not a gap.

The before/after above confirms the *mechanism* on real model calls. The statistical backbone is a prior **powered benchmark across four model vendors**, measuring the one thing that drives all four payoffs — **decision correctness**: correct adopt/avoid decisions moved from **~20% to ~78%**, with **100% unprompted adoption** — when the facts are available, agents reach for them every time. They *want* this signal; they just don't have it by default. Every correct decision is debt not taken on, rework not paid for, and the occasional CVE caught.

```
# vet a package — nothing installed, no account
npx starloghq facts event-stream

# wire facts into your agent (Claude Code, Cursor, Copilot, Codex)
npx starloghq init
```

Source-available under BUSL-1.1 (free to use, modify, and self-host; converts to Apache-2.0 in 2030), listed in the [official MCP Registry](https://registry.modelcontextprotocol.io) as `io.github.starloghq/starlog`

.

Repo, the 42-package corpus, and the full validation runbook: [https://github.com/starloghq/index](https://github.com/starloghq/index)

If you build agents, the takeaway generalizes past dependency choice: anywhere the model is doing **recall** where it should be doing **evaluation** — anything time-sensitive, anything private — a small local index of dated, honest facts (one willing to say "I don't know") beats asking the model to try harder. The debt it never takes on, and the rework you never pay for, is the quiet win sitting right next to the CVE it catches. It can't recall what it never saw.
