<?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: Harjot Rana</title>
    <description>The latest articles on DEV Community by Harjot Rana (@harjjotsinghh).</description>
    <link>https://dev.to/harjjotsinghh</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%2F1193425%2Fb5f7b30b-df4d-4bac-9732-6b1e1ac7805a.jpg</url>
      <title>DEV Community: Harjot Rana</title>
      <link>https://dev.to/harjjotsinghh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harjjotsinghh"/>
    <language>en</language>
    <item>
      <title>I mined 1,398 corrections out of my coding agent logs and turned them into a rules file</title>
      <dc:creator>Harjot Rana</dc:creator>
      <pubDate>Thu, 10 Sep 2026 13:08:17 +0000</pubDate>
      <link>https://dev.to/harjjotsinghh/i-mined-1398-corrections-out-of-my-coding-agent-logs-and-turned-them-into-a-rules-file-db9</link>
      <guid>https://dev.to/harjjotsinghh/i-mined-1398-corrections-out-of-my-coding-agent-logs-and-turned-them-into-a-rules-file-db9</guid>
      <description>&lt;p&gt;My coding agent asks me the same things constantly. New file or add to the existing one. Do you want a test for this. Should I clean up the function next to the one I am touching.&lt;/p&gt;

&lt;p&gt;I have answered all of these. Dozens of times. The answers were sitting in my chat history and nobody, me included, was reading them back.&lt;/p&gt;

&lt;p&gt;So I wrote a tool that does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually is
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;jot&lt;/code&gt; is an extractor plus a knowledge base. The extractor finds the session stores your coding agents leave on disk, reads them, and pulls out the moments where you stopped the agent and said no, do it this way instead. Those get clustered into rules, each with a reason and a stated exception, and written to markdown.&lt;/p&gt;

&lt;p&gt;You load that markdown as an agent skill. Your agent reads it before it starts working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add HarjjotSinghh/jot &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in any agent that supports Agent Skills:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/jot should this state be global or local?
/jot review this PR
/jot which model should these subagents run on?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That command installs mine, which is really a worked example. The part worth your time is pointing the extractor at your own logs.&lt;/p&gt;

&lt;p&gt;No training. No GPU. No fine-tune. Text files.&lt;/p&gt;

&lt;h2&gt;
  
  
  The version I sat on for a year
&lt;/h2&gt;

&lt;p&gt;For about a year I wanted to fine-tune a small model, 8B to 20B, on every file I own. Text, audio, PDFs, spreadsheets, decks. A model of me, trained on me.&lt;/p&gt;

&lt;p&gt;I never wrote a line of it. Not once did I open a terminal.&lt;/p&gt;

&lt;p&gt;Then I read Kun Chen's post about distilling himself into a skill, and the thing that clicked was that the hard part of "clone yourself" was never the weights. It was the preferences. And preferences are small enough to just write down.&lt;/p&gt;

&lt;p&gt;By preferences I mean the boring calls with no correct answer, only my answer. Refactor now or ship and come back. Test first or backfill before merge. Ask before touching anything with real users on it, or just go. A generic model has a sensible default for every one of these. Several of mine are not the default, and that gap is the entire reason the agent keeps interrupting me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not interview yourself
&lt;/h2&gt;

&lt;p&gt;The obvious way to build this is to sit with a model and answer questions about how you work. It produces beautiful, useless output, because everyone is aspirational about themselves.&lt;/p&gt;

&lt;p&gt;Ask me if I write tests first and I will say yes with a straight face. Look at what I actually shipped and you find spikes with no tests and coverage backfilled right before merge. The second version is the true one.&lt;/p&gt;

&lt;p&gt;So I skipped the interview and went to the logs.&lt;/p&gt;

&lt;p&gt;The highest-value thing on my disk is not my code. It is every time I typed something at an agent that was one keystroke away from doing the wrong thing. Every agent saves those. Nobody reads them back.&lt;/p&gt;

&lt;h2&gt;
  
  
  The extraction
&lt;/h2&gt;

&lt;p&gt;Six adapters: Claude Code JSONL, Codex rollouts, Grok history, Gemini CLI logs, OpenCode, and Cursor, which stores every message as a row in a 1.5 GB SQLite file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python scripts/extract_corpus.py
python scripts/extract_corpus.py &lt;span class="nt"&gt;--agents&lt;/span&gt; claude codex cursor &lt;span class="nt"&gt;--min-score&lt;/span&gt; 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Normalize everything to turns. Six agents, six schemas, one shape.&lt;/li&gt;
&lt;li&gt;Pair each thing I said with the agent turn it was reacting to. "No, not like that" is meaningless on its own. It only carries information next to the thing it rejected.&lt;/li&gt;
&lt;li&gt;Score against a lexicon weighted toward corrections, rejections, and stated preferences.&lt;/li&gt;
&lt;li&gt;Dedupe hard, because I complain about the same three things constantly and 40 instances of one gripe is one rule, not 40.
First pass: 1,398 distinct judgment events across 1,290 conversations. 505 corrections. 380 stated preferences.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every rule in the knowledge files carries an evidence tag pointing back at the source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[observed Nx]&lt;/code&gt; extracted from N distinct real sessions, dated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[stated]&lt;/code&gt; I wrote it down as a rule&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[inferred]&lt;/code&gt; derived from adjacent behaviour, lower confidence, flagged at use time
A rule with no evidence is a vibe. If it cannot be traced, it does not go in.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Layout
&lt;/h2&gt;

&lt;p&gt;A thin skill stub, and a knowledge base that lives in the repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;skills/jot/SKILL.md   loader; local checkout first, raw repo URLs second
ENTRY.md              routing table plus the decision procedure
PRINCIPLES.md         durable rules that survive a framework change
ENGINEERING.md        backend, debugging, git, review
FRONTEND.md           visual taste, design parity, slop detectors
AGENTIC.md            model routing, autonomy grants, parallelism
WORKFLOWS.md          named sequences: feature, bug, refactor, review, EOD
TOOLS.md              what I reach for, and the friction I hit
BOUNDARIES.md         hard stops, read before anything outward-facing
VOICE.md              how I write; loaded only for text going out under my name
OPERATING.md          attention, cadence, escalation
CONTEXT.md            who I am, what is active
state/                mined evidence, changelog, pending promotions
bench/                the benchmark that says whether any of this works
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stub never changes. All churn happens in the knowledge files, so every agent pointed at the repo stays in sync without a separate update step.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;private/&lt;/code&gt; and &lt;code&gt;state/evidence/&lt;/code&gt; are gitignored and never fetched over the network. The public layer holds preferences. The private layer holds the specifics that make them actionable: named colleagues, clients, money, positioning. The skill only loads those from a local checkout.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does it work
&lt;/h2&gt;

&lt;p&gt;A rules file that sounds like you but decides differently is worse than no file at all. It makes confident wrong calls in your name and you are not there to catch them. So &lt;code&gt;bench/&lt;/code&gt; answers the question properly.&lt;/p&gt;

&lt;p&gt;Three arms. A control model with no skill. The same model with &lt;code&gt;/jot&lt;/code&gt; loaded. And me, answering blind.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python scripts/bench_run.py &lt;span class="nt"&gt;--set&lt;/span&gt; v1
python scripts/bench_score.py &lt;span class="nt"&gt;--run&lt;/span&gt; &amp;lt;timestamp&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ten questions, each one a decision where a competent generic model has a plausible default that is not what I actually do. Both model arms run in clean-room sessions that never saw the conversation where the rules were written, because a session that helped write the answers already knows the answers. Their responses go into sealed files I do not open until I have committed to mine.&lt;/p&gt;

&lt;p&gt;Scored 0 to 2 against my answer. Minus one for fabricating a preference I do not hold.&lt;/p&gt;

&lt;p&gt;First run: skill 13/20, control 7/20.&lt;/p&gt;

&lt;p&gt;The number that matters is the delta between the two model arms. A skill that scores well only because any competent model would have scored well is recording things that did not need recording.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then I sorted the results by where each rule came from
&lt;/h2&gt;

&lt;p&gt;I had written two kinds of rules without really noticing. Ones mined out of real transcripts, and ones I had simply believed about myself and typed in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mined from transcripts:  2, 2, 2, 2
believed about myself:   0, 1, 0, 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exceptions in either direction. The mined rules carried the entire gain. Everything I had assumed about myself was dead weight or actively wrong, and it was wrong in exactly the same confident tone as the stuff that was right.&lt;/p&gt;

&lt;p&gt;The worst one: my file said that once I give a blanket approval, the agent should stop asking. I had generalized that from exactly one line I typed mid-task, once. The benchmark asked what to do at a sub-decision that approval never covered. The skill told the agent not to ask. My real answer was "I would ask first."&lt;/p&gt;

&lt;p&gt;One occurrence is an anecdote. My own precedence rules say three occurrences make a rule. I broke my own precedence rules inside the file that contains them.&lt;/p&gt;

&lt;p&gt;That is how this goes wrong. Not by being wrong about you. By being right about you in one situation and then applying it everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Patched four rules, re-ran, 18/20
&lt;/h2&gt;

&lt;p&gt;And one question that had scored 2 dropped to 0.&lt;/p&gt;

&lt;p&gt;The rule I added to fix "just take the two-hour refactor now" got applied to a two-minute fix on a live customer list. Which is the opposite of what I do, because that is not my code and those are somebody's real customers.&lt;/p&gt;

&lt;p&gt;A rule that fixes one case and breaks another is written too broadly. Misses now become golden cases in &lt;code&gt;bench/golden/&lt;/code&gt;, and each one turns into a rule with an explicit &lt;code&gt;Doesn't apply when&lt;/code&gt; line. Boundaries outrank every principle in the repo instead of politely tie-breaking with them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is like to use
&lt;/h2&gt;

&lt;p&gt;Uncanny. Not "wow, impressive model" uncanny. Specifically: you ask it something you have never thought about before, it answers, and you get a small jolt of yes, that is exactly what I would have done, and that is exactly why.&lt;/p&gt;

&lt;p&gt;It is talking to yourself, except this version of you has read every correction you have ever issued and never gets tired.&lt;/p&gt;

&lt;p&gt;It disagrees sometimes, and the disagreements turned out to be more useful than the agreements. It was never being stupid. It was faithfully applying a rule I had written badly. The gap between the two model arms measures my preferences. The gap between the skill and me measures my writing. Two different problems, fixable separately.&lt;/p&gt;

&lt;p&gt;Worth doing even if nobody else installs it. Writing a rule with a reason, a stated exception and a piece of evidence forces you to find out whether you actually hold it. A few of mine did not survive the format.&lt;/p&gt;

&lt;p&gt;Not bad for an idea I sat on for a year because I thought it needed a GPU.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add HarjjotSinghh/jot &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/HarjjotSinghh/jot" rel="noopener noreferrer"&gt;https://github.com/HarjjotSinghh/jot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Prior art: &lt;a href="https://github.com/kunchenguid/kun" rel="noopener noreferrer"&gt;https://github.com/kunchenguid/kun&lt;/a&gt;, which made the case that the repeatable part of your judgment is worth externalising, and that it was never the part that was your moat. Read Kun's first.&lt;/p&gt;

&lt;p&gt;If you run the extractor on your own logs, I want to know two things. How many events it found, and how many of the rules you wrote by hand survived contact with a benchmark. My guess is fewer than you expect.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How we built a 14-agent pipeline that ships a deployed app + launch assets in ~7 minutes</title>
      <dc:creator>Harjot Rana</dc:creator>
      <pubDate>Mon, 01 Jun 2026 01:54:28 +0000</pubDate>
      <link>https://dev.to/harjjotsinghh/how-we-built-a-14-agent-pipeline-that-ships-a-deployed-app-launch-assets-in-7-minutes-24ko</link>
      <guid>https://dev.to/harjjotsinghh/how-we-built-a-14-agent-pipeline-that-ships-a-deployed-app-launch-assets-in-7-minutes-24ko</guid>
      <description>&lt;p&gt;Most AI app builders stop at "deployed." You prompt, you get a repo, maybe a preview URL, and then the actual work starts: wiring a domain, writing the landing copy, cutting screenshots, drafting the launch thread. We wanted the pipeline to stop at "launched" instead, so we built one. This is how it works under the hood, including the parts that broke.&lt;/p&gt;

&lt;p&gt;The product is &lt;a href="https://moonshift.io" rel="noopener noreferrer"&gt;Moonshift&lt;/a&gt;. One prompt triggers 14 specialized agents across 10 phases. Average run is ~7 minutes and ~$3 in API spend, with a hard $5 ceiling that aborts the run. Everything ships to your Vercel, your GitHub, your database. This post is the engineering, not the pitch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core problem: parallel agents drift
&lt;/h2&gt;

&lt;p&gt;The naive version of "many agents build an app" falls apart fast. If a backend agent and a frontend agent both work from a vague English spec, they invent incompatible contracts. The backend returns &lt;code&gt;{ user_id }&lt;/code&gt;, the frontend reads &lt;code&gt;userId&lt;/code&gt;, and you find out at runtime in production.&lt;/p&gt;

&lt;p&gt;Our fix is a &lt;strong&gt;planner that emits a JSON contract first&lt;/strong&gt;. Before any code is written, one agent produces a typed contract: routes, request/response shapes, table schemas, env vars, page list. That contract is the single source of truth. Backend, frontend, database, and test agents all build against it in parallel instead of against prose.&lt;/p&gt;

&lt;p&gt;Then a &lt;strong&gt;contract-validator agent&lt;/strong&gt; runs after the parallel build and diffs the actual code against the contract. When the frontend's fetch shape doesn't match the backend's handler, the validator doesn't just flag it. It patches the mismatch. This one agent removed the largest single class of "looks done, 500s on click" failures we had.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 10 phases
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt; - generate the JSON contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaffold&lt;/strong&gt; - lay down the framework skeleton (Next.js, config, deny-globs that protect files agents shouldn't touch).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt; - API routes and server logic against the contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt; - pages and components against the same contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database&lt;/strong&gt; - schema + migrations (Drizzle + Turso).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate&lt;/strong&gt; - contract-validator reconciles 3-5 in parallel, auto-fixes drift.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test + fix&lt;/strong&gt; - generated tests run; a fixer loop addresses failures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy&lt;/strong&gt; - ships to &lt;em&gt;your&lt;/em&gt; Vercel via your token.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit&lt;/strong&gt; - security and a11y passes on the live deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market + publish&lt;/strong&gt; - a marketer agent drafts X and LinkedIn launch posts in your voice, image-gen produces hero images, and a publisher gates everything behind your one-tap approval.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The interesting phases are 6, 7, and 10. Everyone has a code-gen step. Almost nobody has a reconcile step, a real fixer loop, or a phase whose only job is launch assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reliability: not every failure is equal
&lt;/h2&gt;

&lt;p&gt;Long multi-agent runs fail in boring ways: a rate limit, a flaky deploy, a model that returns prose where you asked for JSON. If you retry all of them the same way, you either give up too early on transient errors or burn money death-looping on deterministic ones.&lt;/p&gt;

&lt;p&gt;We run a &lt;strong&gt;failure classifier&lt;/strong&gt; that buckets every failure into &lt;code&gt;transient&lt;/code&gt;, &lt;code&gt;deterministic&lt;/code&gt;, or &lt;code&gt;permanent&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;transient&lt;/strong&gt; (429s, network blips, stream idle) - retry with backoff.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;deterministic&lt;/strong&gt; (a test that fails the same way every time) - hand to a fixer agent, don't blindly retry the same call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;permanent&lt;/strong&gt; (bad auth, missing token) - stop and surface it. No point spending more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Retries are capped on three axes at once: per-phase, per-agent, and a global per-run ceiling. The global cap is what keeps a single bad run from quietly turning into a $40 bill. Combined with the hard $5 abort, the worst case is bounded and visible instead of a surprise invoice.&lt;/p&gt;

&lt;p&gt;A subtle one we hit: a long LLM stream can go &lt;em&gt;idle&lt;/em&gt; without erroring (the upstream connection gets severed but the socket never closes). A naive loop waits forever. We added an idle watchdog in the agent loop so a silent stall is treated as a transient failure and retried, instead of hanging the whole run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design constraints that shaped everything
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your infra, zero lock-in.&lt;/strong&gt; Code lands in your GitHub, the app deploys to your Vercel, the database is yours. Cancel the subscription and you keep a working product. This forced the deployer to operate purely through user-supplied tokens, which is more work than deploying to our own infra but is the entire point.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The publisher physically cannot post without you.&lt;/strong&gt; Social publishing is gated per post, per platform, behind an explicit human tap. Autonomy ends at the point where it would speak as you in public. Generation is automatic; publishing is not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hard cost ceiling.&lt;/strong&gt; $5/run, enforced mid-run, not reconciled after. Agents check remaining budget before expensive calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;Next.js for web, Drizzle + Turso (libSQL) for data, Playwright for browser automation in the marketing/audit phases. The orchestrator is a separate runtime from the web app, spawned per run from source so a fix ships without a full rebuild.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest lessons
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A typed contract beats a smarter prompt.&lt;/strong&gt; We spent weeks trying to make agents "just agree." Making them agree on a machine-checkable artifact was the actual fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A reconcile phase is worth more than a better code-gen model.&lt;/strong&gt; Catching drift after the fact, cheaply, beat every attempt to prevent it perfectly up front.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Classify failures before you retry them.&lt;/strong&gt; Uniform retry is how multi-agent systems burn money and still fail.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bound the blast radius in money, not just time.&lt;/strong&gt; A per-run dollar cap is the single most important guardrail in an autonomous pipeline that calls paid APIs in a loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to see the output, the first run is free with your own API key at &lt;a href="https://moonshift.io" rel="noopener noreferrer"&gt;moonshift.io&lt;/a&gt;. Happy to answer architecture questions in the comments.&lt;/p&gt;

</description>
      <category>devtools</category>
    </item>
  </channel>
</rss>
