<?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: Sergei Strebulaev</title>
    <description>The latest articles on DEV Community by Sergei Strebulaev (@sergemso).</description>
    <link>https://dev.to/sergemso</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%2F4108460%2Faa705442-1138-48c8-b4e4-4b45a3098896.png</url>
      <title>DEV Community: Sergei Strebulaev</title>
      <link>https://dev.to/sergemso</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sergemso"/>
    <language>en</language>
    <item>
      <title>The Project I Inherited Had No Memory Either</title>
      <dc:creator>Sergei Strebulaev</dc:creator>
      <pubDate>Wed, 09 Sep 2026 14:57:35 +0000</pubDate>
      <link>https://dev.to/sergemso/the-project-i-inherited-had-no-memory-either-25ll</link>
      <guid>https://dev.to/sergemso/the-project-i-inherited-had-no-memory-either-25ll</guid>
      <description>&lt;p&gt;My teammate joined the project on a Tuesday. By Wednesday she asked&lt;br&gt;
the question every new hire eventually asks: &lt;em&gt;"Why is auth handled in&lt;br&gt;
three different places?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I didn't have a good answer — just a fuzzy memory of a decision made&lt;br&gt;
months earlier, in a call nobody wrote down. That's the same problem&lt;br&gt;
I wrote about last time — an AI agent with no memory of what we'd&lt;br&gt;
already decided. Turns out it's not just an AI problem; a team&lt;br&gt;
forgets too. Most real projects aren't a clean slate. Here's what&lt;br&gt;
fixing that actually looks like on one that already has history.&lt;/p&gt;
&lt;h2&gt;
  
  
  Retrofitting memory onto an existing project
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;bootstrap&lt;/code&gt; has two modes. Fresh-project mode creates&lt;br&gt;
&lt;code&gt;docs/{facts,decisions,guardrails,skills}/&lt;/code&gt; from nothing. Gap-fill mode&lt;br&gt;
is for a project that already has &lt;em&gt;some&lt;/em&gt; of that, inconsistent and&lt;br&gt;
incomplete:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/kms:bootstrap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's Claude Code. Codex reads the same skill set through its own&lt;br&gt;
plugin manifest. Kilo Code CLI reads it too once &lt;code&gt;kilo.jsonc&lt;/code&gt; points&lt;br&gt;
at the published skills manifest.&lt;/p&gt;

&lt;p&gt;It found our existing &lt;code&gt;docs/decisions/&lt;/code&gt; folder and extended it instead&lt;br&gt;
of replacing it. Then it scanned git history and existing docs for&lt;br&gt;
decision language — a &lt;code&gt;DECISION:&lt;/code&gt; marker, a "because we need to" — and&lt;br&gt;
came back with draft stubs (id, title, a first-pass motivation,&lt;br&gt;
&lt;code&gt;status: draft&lt;/code&gt;) for decisions I'd genuinely forgotten were decisions&lt;br&gt;
at all — not the full rationale, that's still ours to write, but a&lt;br&gt;
real starting point instead of a blank page. The auth-in-three-places&lt;br&gt;
thing was one of them.&lt;/p&gt;

&lt;p&gt;It also flagged two guardrail files missing the field recording which&lt;br&gt;
decision they came from — not silently, and not by guessing: each got&lt;br&gt;
logged as undeclared debt with a proposed likely source, turning an&lt;br&gt;
archaeology project into a five-minute confirmation.&lt;/p&gt;
&lt;h2&gt;
  
  
  A role-tailored ramp-up, not a wiki page
&lt;/h2&gt;

&lt;p&gt;Once the knowledge base had real content, I pointed my teammate at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/kms:onboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First question back: which role was she ramping up as. Not guessed —&lt;br&gt;
a backend-leaning plan and a frontend one pull from almost entirely&lt;br&gt;
different decisions and guardrails. What came back was 5 days, each&lt;br&gt;
with a goal, specific artifacts to read (real paths, not "the&lt;br&gt;
decisions folder"), and a skill to run:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Highest-level facts, most consequential decisions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Role-specific decisions and guardrails — what not to violate, and why&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Role-specific facts, current state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;First real task; &lt;code&gt;query&lt;/code&gt; for anything unclear&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Practice a decision with &lt;code&gt;clarify&lt;/code&gt;; &lt;code&gt;capture&lt;/code&gt; afterward&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It also told her the truth: our facts directory was still thin, so the&lt;br&gt;
plan opened with a plain warning that it was built on an incomplete&lt;br&gt;
base. A wiki page doesn't flag its own staleness. This did.&lt;/p&gt;
&lt;h2&gt;
  
  
  Planning the refactor I'd been avoiding
&lt;/h2&gt;

&lt;p&gt;The auth question turned into a real refactor — the kind I'd normally&lt;br&gt;
put off because nobody could tell me what it'd break:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/kms:refactor-plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Phase 1 searched the knowledge base and found two relevant artifacts:&lt;br&gt;
the (now-recorded) decision that split auth in the first place, and a&lt;br&gt;
session-handling guardrail I'd forgotten existed. Phase 2 mapped call&lt;br&gt;
sites and config by reading the code directly — no dependency on any&lt;br&gt;
other skill running first. Phase 3 came back with ordered phases, each&lt;br&gt;
carrying concrete steps, a verification checkpoint, and a rollback&lt;br&gt;
strategy specific to that phase, not "revert everything."&lt;/p&gt;

&lt;p&gt;One planned step would've quietly violated the session-handling&lt;br&gt;
guardrail. It wasn't dropped and it wasn't silently worked around — it&lt;br&gt;
was flagged, cited by path, with an explicit ask to confirm before it&lt;br&gt;
stayed in the plan.&lt;/p&gt;
&lt;h2&gt;
  
  
  What this doesn't do
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;onboard&lt;/code&gt; won't write the facts and decisions that don't exist yet —&lt;br&gt;
that's &lt;code&gt;bootstrap&lt;/code&gt;'s job, run first. &lt;code&gt;refactor-plan&lt;/code&gt; won't tell you a&lt;br&gt;
refactor is worth doing, only what it'll cost and what could break;&lt;br&gt;
if the knowledge base has nothing relevant to what you're touching, it&lt;br&gt;
says so plainly instead of inventing a concern to sound thorough.&lt;br&gt;
Neither replaces the actual conversation with your teammate.&lt;/p&gt;

&lt;p&gt;And if kms isn't for you later, &lt;code&gt;uninstall&lt;/code&gt; finds everything it added&lt;br&gt;
— seeded guardrails, generated files like the doc manifest, the marker&lt;br&gt;
block in your agent instructions — and asks about each one&lt;br&gt;
individually: detach&lt;br&gt;
(keep the content, stop tracking it as kms's) or remove. Same&lt;br&gt;
confirm-first discipline as every other kms skill, including this one.&lt;br&gt;
Nothing about adopting kms locks you in, and this piece exists partly&lt;br&gt;
to prove that's not just a claim in the README.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If this is useful, a star helps other developers find it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ &lt;a href="https://github.com/vivantel/kms" rel="noopener noreferrer"&gt;Star vivantel/kms on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin marketplace add vivantel/kms
/plugin &lt;span class="nb"&gt;install &lt;/span&gt;kms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your project already has some history — an incomplete&lt;br&gt;
&lt;code&gt;decisions/&lt;/code&gt; folder, a wiki nobody trusts — run &lt;code&gt;/kms:bootstrap&lt;/code&gt; on it&lt;br&gt;
before assuming you have to start clean. That's the case it's built&lt;br&gt;
for.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Contributions welcome&lt;/em&gt; — see&lt;br&gt;
&lt;a href="https://github.com/vivantel/kms/blob/master/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt;&lt;br&gt;
for how to propose new skills or improve existing ones.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>cli</category>
    </item>
    <item>
      <title>Two Kinds of Memory</title>
      <dc:creator>Sergei Strebulaev</dc:creator>
      <pubDate>Mon, 07 Sep 2026 19:16:59 +0000</pubDate>
      <link>https://dev.to/sergemso/two-kinds-of-memory-4gin</link>
      <guid>https://dev.to/sergemso/two-kinds-of-memory-4gin</guid>
      <description>&lt;p&gt;I asked my AI agent where the retry logic lived. Four seconds later:&lt;br&gt;
three files, one shared helper, a comment linking to a Slack thread&lt;br&gt;
that doesn't exist anymore. Found it cleanly.&lt;/p&gt;

&lt;p&gt;Then I asked why the retry count was capped at three instead of five.&lt;br&gt;
Silence, then a guess. It could find the code. It had no idea why the&lt;br&gt;
code said what it said.&lt;/p&gt;

&lt;p&gt;Two failures wearing the same complaint — "the AI doesn't know this&lt;br&gt;
project." One's a search problem. The other's a memory problem. I'd&lt;br&gt;
already fixed the memory one; that's what this whole series has been&lt;br&gt;
about. The search problem needed a genuinely different tool.&lt;/p&gt;
&lt;h2&gt;
  
  
  What kms doesn't do
&lt;/h2&gt;

&lt;p&gt;kms retrieves what's been captured as decisions, facts, and guardrails — curated, citable, checkable. &lt;code&gt;query&lt;/code&gt; answers "why does this work this way" with a real citation because the answer was captured on purpose.&lt;/p&gt;

&lt;p&gt;But kms also has skills that &lt;em&gt;discover&lt;/em&gt; knowledge implicitly: &lt;code&gt;bootstrap&lt;/code&gt; extracts intents from git history and facts from existing docs; &lt;code&gt;capture&lt;/code&gt; flags contradictions and drift after every work session; &lt;code&gt;roadmap&lt;/code&gt; interviews a plan and captures every implicit presupposition as a durable record. None of those require someone to have written it down beforehand — they find what's already there in history, code, and conversation.&lt;/p&gt;

&lt;p&gt;What kms doesn't have is semantic search across the raw codebase. Most of a codebase isn't a captured decision, though. It's just code — functions, old comments, a README paragraph, a PR nobody formalized because it never rose to that level. kms has nothing to say about any of it unless a skill captured it. Not broken. Never the job.&lt;/p&gt;
&lt;h2&gt;
  
  
  What virage does instead
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;virage&lt;/code&gt; is a separate vivantel tool for exactly that gap — a&lt;br&gt;
git-aware pipeline that turns a codebase and its docs into a&lt;br&gt;
searchable vector index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;virage init
virage index
virage query "how does authentication work?"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;init&lt;/code&gt; writes &lt;code&gt;virage.config.json&lt;/code&gt; via an interactive wizard. &lt;code&gt;index&lt;/code&gt;&lt;br&gt;
chunks the repo — AST-aware, so a function stays one semantic unit&lt;br&gt;
instead of getting sliced at an arbitrary line count — and embeds it.&lt;br&gt;
&lt;code&gt;query&lt;/code&gt; searches by meaning, not keyword: ask about authentication and&lt;br&gt;
it finds the relevant code even if that word never appears in it —&lt;br&gt;
something grep structurally can't do.&lt;/p&gt;

&lt;p&gt;Every stage is swappable: an OpenAI-compatible embedder or a fully&lt;br&gt;
local ONNX model, an embedded file-based vector store for a solo repo&lt;br&gt;
or Postgres/Qdrant for a team, an optional reranker on top. Same CLI&lt;br&gt;
regardless of what's behind it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why not one tool that claims to do both
&lt;/h2&gt;

&lt;p&gt;"AI memory" tools promising a single system for this exist — Mem0,&lt;br&gt;
Letta, Cognee, and similar. They solve a third, different problem: raw&lt;br&gt;
recall of accumulated facts or conversation history, closer to&lt;br&gt;
virage's mechanism than kms's, but aimed at remembering what happened,&lt;br&gt;
not retrieving a curated decision a human stood behind. None separate&lt;br&gt;
"a fact" from "a commitment the team made" the way kms does, and none&lt;br&gt;
are built for a git repo's own structure the way virage is.&lt;/p&gt;
&lt;h2&gt;
  
  
  Same auth mess, two different tools
&lt;/h2&gt;

&lt;p&gt;An earlier piece in this project's kms series described a real mess:&lt;br&gt;
auth split across three places, nobody could say why.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;virage index&lt;/code&gt; finds all three in seconds — every file touching auth,&lt;br&gt;
ranked by relevance, whether or not "auth" shows up in a variable&lt;br&gt;
name. Search problem, solved.&lt;/p&gt;

&lt;p&gt;It can't tell you &lt;em&gt;why&lt;/em&gt; it's split three ways. That answer, if it&lt;br&gt;
exists, lives in a decision someone wrote down — the kind&lt;br&gt;
&lt;code&gt;bootstrap&lt;/code&gt;'s gap-fill mode goes looking for, or &lt;code&gt;query&lt;/code&gt; retrieves&lt;br&gt;
with a citation once it's captured. &lt;code&gt;virage&lt;/code&gt; has no opinion on that&lt;br&gt;
question. Never asked one.&lt;/p&gt;

&lt;p&gt;Neither tool is weaker — they answer different questions, &lt;em&gt;where is&lt;br&gt;
this&lt;/em&gt; and &lt;em&gt;why is it this way&lt;/em&gt;. Conflating them is how a team ends up&lt;br&gt;
re-grepping the same code every time, or re-deciding the same question&lt;br&gt;
every time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using both without confusing what each is for
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;virage query&lt;/code&gt; for "where"/"what" questions. &lt;code&gt;kms query&lt;/code&gt; for "why"&lt;br&gt;
questions. They're two separate tools today, not one integrated&lt;br&gt;
system — running &lt;code&gt;virage&lt;/code&gt; doesn't feed &lt;code&gt;kms&lt;/code&gt;'s decisions, and vice&lt;br&gt;
versa. Worth saying plainly rather than implying a seamlessness that&lt;br&gt;
isn't there. What they share is a practice, not a product: don't let&lt;br&gt;
either kind of memory live only in someone's head.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If this is useful, a star helps other developers find both:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ &lt;a href="https://github.com/vivantel/kms" rel="noopener noreferrer"&gt;Star vivantel/kms&lt;/a&gt;&lt;/strong&gt; ·&lt;br&gt;
&lt;strong&gt;⭐ &lt;a href="https://github.com/vivantel/virage" rel="noopener noreferrer"&gt;Star vivantel/virage&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;/plugin marketplace add vivantel/kms
/plugin install kms
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's Claude Code. Codex reads the same skill set through its own&lt;br&gt;
plugin manifest. Kilo Code CLI reads it too, once &lt;code&gt;kilo.jsonc&lt;/code&gt; points&lt;br&gt;
at the published skills manifest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @vivantel/virage
virage init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code again first, via virage's own agent plugin. GitHub Copilot&lt;br&gt;
reads the same index through its own agent plugin. Codex reads it&lt;br&gt;
through its own agent plugin. Antigravity reads it through its own&lt;br&gt;
integration.&lt;/p&gt;

&lt;p&gt;If you already run kms, &lt;code&gt;virage index&lt;/code&gt; on the same repo takes about a&lt;br&gt;
minute and costs nothing to try. If you run neither yet, start with&lt;br&gt;
whichever question you actually have: something you can't find, or&lt;br&gt;
something you can't explain.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Contributions welcome&lt;/em&gt; on both —&lt;br&gt;
&lt;a href="https://github.com/vivantel/kms/blob/master/CONTRIBUTING.md" rel="noopener noreferrer"&gt;kms&lt;/a&gt;,&lt;br&gt;
&lt;a href="https://github.com/vivantel/virage/blob/master/CONTRIBUTING.md" rel="noopener noreferrer"&gt;virage&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>rag</category>
    </item>
    <item>
      <title>Building a Terraform Provider for Paddle Billing: Why Real-Sandbox Testing Matters</title>
      <dc:creator>Sergei Strebulaev</dc:creator>
      <pubDate>Sat, 05 Sep 2026 06:08:59 +0000</pubDate>
      <link>https://dev.to/sergemso/building-a-terraform-provider-for-paddle-billing-why-real-sandbox-testing-matters-45ff</link>
      <guid>https://dev.to/sergemso/building-a-terraform-provider-for-paddle-billing-why-real-sandbox-testing-matters-45ff</guid>
      <description>&lt;p&gt;We manage our whole infrastructure as code, and wanted our Paddle Billing catalog — products, prices, discounts, webhook config — to work the same way instead of being the one thing still managed by hand through a dashboard. Existing tooling didn't cover enough of what we actually needed, lifecycle actions for subscriptions and refunds especially, so we built our own.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terraform-provider-paddle&lt;/code&gt; manages Paddle Billing's catalog — products, prices, discounts, discount groups, notification settings — plus six lifecycle actions (refunds/credits, subscription cancel/pause/resume/charge, notification replay), lookup data sources for subscriptions/transactions/customers/events, and a couple of newer Terraform capabilities: an ephemeral resource for a webhook secret that never touches state, and resource identity + list-block support for bulk-discovering existing infrastructure via &lt;code&gt;terraform query&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This post isn't a feature tour, though — it's about one specific decision that shaped how the whole thing got built: every resource and data source is verified end-to-end against Paddle's real sandbox API before each release, not just tested against mocks. Here's a real bug from that process that explains why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with mocking someone else's API
&lt;/h2&gt;

&lt;p&gt;Every API client eventually encodes assumptions about the wire format — what fields exist, what shape they're nested in, what a status value actually means. When those assumptions are right, mocks are great: fast, free, deterministic, no network flakiness. When they're wrong, a hand-written mock just encodes the same wrong assumption and "confirms" it forever. A test suite built entirely on mocks can be green for months while quietly testing the wrong thing.&lt;/p&gt;

&lt;p&gt;Here's a concrete example. A transaction's line items don't carry a flat &lt;code&gt;price_id&lt;/code&gt; field — Paddle nests a full &lt;code&gt;price&lt;/code&gt; object under each line item, and the ID you actually want is &lt;code&gt;price.id&lt;/code&gt;. A mock built around the flat-field assumption would have exercised the same code path, returned a plausible-looking response, and passed — while the real code silently compared against an empty string every time it ran against the real API.&lt;/p&gt;

&lt;p&gt;The fix wasn't just correcting that one field. Paddle publishes a proper machine-readable OpenAPI spec for their whole API, auto-generated from their own backend whenever it changes — so this provider now vendors a copy of it and runs a forward-only contract check on every test run: for every field a client struct actually reads or writes, does that field still exist in Paddle's real API, at the same nested path, with a structurally compatible shape? It's deliberately one-directional — the provider intentionally leaves plenty of Paddle's API surface unmodeled, so checking "does the provider cover everything Paddle has" would just flag every deliberate scope decision as false-positive drift. Checking "does what the provider &lt;em&gt;does&lt;/em&gt; model still match the spec" is the direction that actually matches the bug history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Newer Terraform features, and why they showed up here
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ephemeral resources.&lt;/strong&gt; A webhook signing secret is real, sensitive data that's genuinely needed at apply time — but there's no reason it should sit in a state file forever. &lt;code&gt;Sensitive: true&lt;/code&gt; on a schema attribute only redacts CLI/log &lt;em&gt;output&lt;/em&gt;; it does nothing to state itself, which still stores the real value in plaintext. This provider added an ephemeral resource specifically so that secret can be fetched fresh on every apply and never written to state at all, while keeping the old (now-deprecated, still fully working) attribute in place for anyone already depending on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource identity + list resources.&lt;/strong&gt; &lt;code&gt;terraform query&lt;/code&gt; (Terraform 1.14+) turns out to hard-depend on resource identity being implemented on the target resource first — a list result's identity is required, and it's built from that schema. Once that's wired up for a resource, bulk-discovering everything of that type already sitting in a Paddle account — and generating &lt;code&gt;import&lt;/code&gt; config for it — becomes a first-class Terraform workflow instead of something you'd have to script by hand against the raw API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Terraform Registry: &lt;a href="https://registry.terraform.io/providers/vivantel/paddle" rel="noopener noreferrer"&gt;registry.terraform.io/providers/vivantel/paddle&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/vivantel/terraform-provider-paddle" rel="noopener noreferrer"&gt;github.com/vivantel/terraform-provider-paddle&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feedback and issues welcome — especially anywhere the schema doesn't match real Paddle behavior. That's exactly the kind of thing this whole approach is built to catch, and it's more reliable with more real accounts exercising it.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>testing</category>
      <category>api</category>
      <category>opensource</category>
    </item>
    <item>
      <title>My AI Keeps Forgetting What We Already Decided</title>
      <dc:creator>Sergei Strebulaev</dc:creator>
      <pubDate>Thu, 03 Sep 2026 22:41:57 +0000</pubDate>
      <link>https://dev.to/sergemso/my-ai-keeps-forgetting-what-we-already-decided-4okd</link>
      <guid>https://dev.to/sergemso/my-ai-keeps-forgetting-what-we-already-decided-4okd</guid>
      <description>&lt;p&gt;Every week I re-explain the same architecture choices to my AI coding&lt;br&gt;
agent. New session, zero memory — like we never talked. That's not a&lt;br&gt;
prompting problem, it's a memory problem, and I fixed it with a&lt;br&gt;
git-based knowledge system that lives right next to the code. Here's&lt;br&gt;
the actual walkthrough, the schema it writes, and where it falls&lt;br&gt;
short — not just the pitch.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem in one sentence
&lt;/h2&gt;

&lt;p&gt;I plan a feature with Claude Code on Tuesday. Wednesday, fresh&lt;br&gt;
session: &lt;em&gt;"Where did we leave off?"&lt;/em&gt; No idea. I re-explain everything.&lt;br&gt;
By Thursday I've explained it a third time to a different agent. Each&lt;br&gt;
one asks good questions, gets a good answer, and forgets it the moment&lt;br&gt;
the session ends. The plan was never the problem — nothing durable&lt;br&gt;
ever got written down, so there was nothing for the next session to&lt;br&gt;
read.&lt;/p&gt;
&lt;h2&gt;
  
  
  What I built: kms
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;kms&lt;/code&gt; is a Claude Code plugin that captures decisions, facts, and&lt;br&gt;
guardrails as plain markdown files, version-controlled right alongside&lt;br&gt;
your code. Any agent that reads the repo reads the knowledge base&lt;br&gt;
first, before it asks you anything.&lt;/p&gt;

&lt;p&gt;Install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin marketplace add vivantel/kms
/plugin &lt;span class="nb"&gt;install &lt;/span&gt;kms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four artifact types, each with one job:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Answers&lt;/th&gt;
&lt;th&gt;Lives in&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fact&lt;/td&gt;
&lt;td&gt;What's true right now&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docs/facts/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decision&lt;/td&gt;
&lt;td&gt;What you're committing to, and why&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docs/decisions/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guardrail&lt;/td&gt;
&lt;td&gt;What must (or must not) happen, derived from a decision&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docs/guardrails/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skill&lt;/td&gt;
&lt;td&gt;How to act on all of the above&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docs/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Walkthrough: capturing your first decision
&lt;/h2&gt;

&lt;p&gt;One command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/kms:quickstart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;docs/{facts,decisions,guardrails,skills}/&lt;/code&gt; doesn't exist yet,&lt;br&gt;
quickstart sets it up first. Then it asks one direct question:&lt;br&gt;
&lt;em&gt;"What decision or plan is currently live for you right now?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Mine was the multi-platform content strategy I'd re-explained three&lt;br&gt;
times that week — which platforms, what cadence, what CTA on each.&lt;br&gt;
Quickstart interviews you — what's changing, why, what stays fixed —&lt;br&gt;
then writes the result to&lt;br&gt;
&lt;code&gt;docs/decisions/0002-content-multi-platform-strategy.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0002-content-multi-platform-strategy&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Multi-platform content strategy for kms outreach&lt;/span&gt;
&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;accepted&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2026-08-31&lt;/span&gt;
&lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;kms&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;outreach&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;multi-channel&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;track&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;product&lt;/span&gt;
&lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;All public articles produced in kms_content&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="c1"&gt;## Decision&lt;/span&gt;

&lt;span class="s"&gt;kms public articles expand beyond Medium to Dev.to and Hashnode.&lt;/span&gt;
&lt;span class="s"&gt;Medium stays canonical; the others get manually adapted copies. Weekly&lt;/span&gt;
&lt;span class="s"&gt;cadence. Platform-specific primary CTAs — Medium leads with install,&lt;/span&gt;
&lt;span class="s"&gt;Dev.to with GitHub stars, Hashnode with newsletter signup — rather&lt;/span&gt;
&lt;span class="s"&gt;than one CTA everywhere.&lt;/span&gt;

&lt;span class="c1"&gt;## Rationale&lt;/span&gt;

&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing gets summarized or paraphrased away — that's your call,&lt;br&gt;
captured once, in your own words. The session closes by naming what to&lt;br&gt;
run next, not leaving you to guess: &lt;code&gt;query&lt;/code&gt; to pull this decision back&lt;br&gt;
up later with a citation, &lt;code&gt;capture&lt;/code&gt; after the next session that&lt;br&gt;
touches it.&lt;/p&gt;

&lt;p&gt;From that point on, Claude Code&lt;br&gt;
reads that file the next time it opens the repo and knows exactly&lt;br&gt;
what was decided. Codex reads the same skill set through its own&lt;br&gt;
plugin manifest. Kilo Code CLI reads it too, once &lt;code&gt;kilo.jsonc&lt;/code&gt; points&lt;br&gt;
at the published skills manifest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond decisions
&lt;/h2&gt;

&lt;p&gt;Facts and guardrails link back to why they exist, not just what they&lt;br&gt;
say. Say you decide Medium posts close with an install CTA, Dev.to&lt;br&gt;
posts close with a GitHub-stars ask. That's a decision. The guardrail&lt;br&gt;
that enforces it on every article cites that decision by id. A skill&lt;br&gt;
that tells you how to adapt a draft per platform references the&lt;br&gt;
guardrail. Change the decision later, and &lt;code&gt;capture&lt;/code&gt;/&lt;code&gt;lint&lt;/code&gt; catch the&lt;br&gt;
guardrail and skill silently drifting out of sync with it — instead&lt;br&gt;
of you finding out three articles later.&lt;/p&gt;

&lt;p&gt;Commands worth knowing once you've got a knowledge base going:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;query&lt;/code&gt; — retrieve a past decision with a citation, instead of
re-explaining it.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;capture&lt;/code&gt; — log what a work session changed, after the fact; flags
contradictions it finds along the way.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lint&lt;/code&gt; — validate the whole knowledge base on demand: dangling
references, missing fields, stale derived artifacts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;brainstorm&lt;/code&gt; — generate fresh approaches with no anchor to past
decisions, for exploring before anything's locked in.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onboard&lt;/code&gt; — a role-tailored, 5-day ramp-up plan for a new teammate,
built from the existing knowledge base.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;conform&lt;/code&gt; — check whether a pending change respects the guardrails
before it lands.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What this doesn't solve
&lt;/h2&gt;

&lt;p&gt;It's not magic memory — you still write the interview answers&lt;br&gt;
yourself; quickstart just makes sure they get written down instead of&lt;br&gt;
staying in your head. It doesn't replace tests, code review, or&lt;br&gt;
actual documentation for end users. And it only helps if the habit&lt;br&gt;
sticks — a knowledge base nobody updates after month one is just a&lt;br&gt;
&lt;code&gt;docs/&lt;/code&gt; folder with extra steps. The parts that make that less likely&lt;br&gt;
are &lt;code&gt;capture&lt;/code&gt; (so updating it is a five-minute pass after a session,&lt;br&gt;
not a separate chore) and &lt;code&gt;lint&lt;/code&gt; (so drift gets caught instead of&lt;br&gt;
silently rotting).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this beats a context file you paste in
&lt;/h2&gt;

&lt;p&gt;I've tried system prompts, paste-in context files, separate&lt;br&gt;
note-taking apps I'd open in another window. They all fail the same&lt;br&gt;
way: they live outside the repo, so they don't survive a fresh&lt;br&gt;
session, and they rely on you remembering to open them, paste them in,&lt;br&gt;
and keep them updated. This is different because it's part of the&lt;br&gt;
repository — every decision is version-controlled, every fact is&lt;br&gt;
verified, and a guardrail is derived from a real commitment instead of&lt;br&gt;
vibes. When the project changes, the knowledge base changes with it,&lt;br&gt;
in the same commit history as the code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If this is useful to you, a star helps other developers find it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⭐ &lt;a href="https://github.com/vivantel/kms" rel="noopener noreferrer"&gt;Star vivantel/kms on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then install the plugin and run &lt;code&gt;/kms:quickstart&lt;/code&gt; on one real decision&lt;br&gt;
that's been living in your head. You'll never explain it twice.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Contributions welcome&lt;/em&gt; — see&lt;br&gt;
&lt;a href="https://github.com/vivantel/kms/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt;&lt;br&gt;
for how to propose new skills or improve existing ones.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>coding</category>
      <category>git</category>
    </item>
  </channel>
</rss>
