<?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: Aman Bhandari</title>
    <description>The latest articles on DEV Community by Aman Bhandari (@amanbhandari).</description>
    <link>https://dev.to/amanbhandari</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3886724%2Ffd6ccd15-d3c7-4e3d-aff2-e52d288b9977.png</url>
      <title>DEV Community: Aman Bhandari</title>
      <link>https://dev.to/amanbhandari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amanbhandari"/>
    <language>en</language>
    <item>
      <title>Scale-position 5: how I stopped drifting between depth and speed</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 03:23:19 +0000</pubDate>
      <link>https://dev.to/amanbhandari/scale-position-5-how-i-stopped-drifting-between-depth-and-speed-50n5</link>
      <guid>https://dev.to/amanbhandari/scale-position-5-how-i-stopped-drifting-between-depth-and-speed-50n5</guid>
      <description>&lt;p&gt;Every engineering trade-off between &lt;em&gt;"ship faster using the abstraction"&lt;/em&gt; and &lt;em&gt;"derive first, build from scratch"&lt;/em&gt; is implicitly a position on a 0-to-10 axis. Without codifying the axis and naming where you currently sit, you drift between positions session by session — one day demanding a whiteboard derivation, the next day shipping a library import without looking at it. The drift is invisible inside the session. It only shows up weeks later when the skills you thought you were building turn out to have been interrupted by the ones you thought you were also building, and neither compounded.&lt;/p&gt;

&lt;p&gt;I fixed this for myself by codifying the axis as a rule file, pinning each position to a named practitioner, setting my current anchor at 5 with a drift target of 6, and running a weekly recalibration. The rule lives in &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; under &lt;code&gt;scale-position.md&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The axis
&lt;/h2&gt;

&lt;p&gt;Ten positions. Each one is a trade-off profile, not a skill rating.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;0 — Pure vibe-coding.&lt;/strong&gt; Agent writes, operator merges. No spec, no review, no eval loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2 — Simon-Willison-style shipper.&lt;/strong&gt; Prolific throwaway experimentation, explicit about when it is and is not appropriate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3 — Eugene Yan / Hamel Husain / Jeremy Howard shipping-mode applied practitioner.&lt;/strong&gt; Strong problem framing, non-ML baselines, manual eval. Gets systems into production quickly; earns depth over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5 — Chip-Huyen-balanced ML engineer.&lt;/strong&gt; Frames the problem, designs the I/O contract, picks the right primitive, reads the math to the level of explaining &lt;em&gt;why&lt;/em&gt; a loss is appropriate (not only which one to import). Matches the median Anthropic / OpenAI Member of Technical Staff profile around 2025-2026.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 — Karpathy-style educator-practitioner.&lt;/strong&gt; Builds the 40-line version from scratch. Can derive backprop on a whiteboard under interview pressure. Ships a production system in the same week.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7 — Sebastian Raschka / Julia Evans full-mastery.&lt;/strong&gt; Derives from first principles and descends to OS syscalls or CUDA kernels when an abstraction leaks. Teaches the next generation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;9-10 — Research contribution.&lt;/strong&gt; Publishes novel architectures, optimizers, training recipes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Positions 1, 4, and 8 exist as intermediates on the same line. The illustrative poles are the ones you can pin to a working practitioner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the axis matters in practice
&lt;/h2&gt;

&lt;p&gt;Most engineers sitting at 3 and most engineers sitting at 5 do the same daily work. The difference shows up under specific trade-offs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;When to reach for an abstraction.&lt;/strong&gt; At 3, the abstraction is a productivity win and you ship faster. At 5, you read the abstraction's source before importing it and can explain why it works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When a bug lands that the library does not document.&lt;/strong&gt; At 3, you file an issue. At 5, you trace the bug into the library's code and propose a patch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When a new model ships.&lt;/strong&gt; At 3, you swap it in and test against your current harness. At 5, you read the model card, understand what changed in the architecture, and update the harness to test the specific capability that changed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither is wrong. They are trade-offs. Position 3 ships more feature surface per week. Position 5 fails differently when the abstraction leaks — and the abstraction always eventually leaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The driver — why I anchor at 5
&lt;/h2&gt;

&lt;p&gt;The driver matters because the driver decides which way the drift target points. Mine is AI-replacement moat, not income urgency. Stated precisely: the concern is not "I need more money this month" but "the shipping-mode applied work I am currently competent at is exactly the work coding agents are fastest at replacing."&lt;/p&gt;

&lt;p&gt;Position 3 is where LLMs are fastest reaching competence. Shipping-mode applied work — ship against a Jira ticket, write the endpoint, wire the integration — is the profile currently being compressed. Position 5 and above is where the moat lives: problem framing, quality judgment, cross-layer debugging, first-principles derivation. These are the four skills agents do worst at today, and they are what I train for.&lt;/p&gt;

&lt;p&gt;An operator whose driver is income urgency should anchor differently — probably at 3, ship hireable artifacts faster, earn depth after the runway stabilizes. The axis tolerates either anchor. What it does not tolerate is drifting between them without naming it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The weekly Sunday recalibration
&lt;/h2&gt;

&lt;p&gt;Every Sunday, a four-question check:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hours.&lt;/strong&gt; How many hours did the work actually hit this week versus the floor?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concepts that closed the loop.&lt;/strong&gt; Which concepts passed the Bransford transfer test this week? (Passed the novel-surface-form test without reaching for the original analogy.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fear level.&lt;/strong&gt; Rising / steady / falling. The compass needle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pressure signals.&lt;/strong&gt; Financial, health, life. Anything that changes runway or energy budget.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then one of three proposals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hold at 5.&lt;/strong&gt; Default. Hours hit, concepts landed, fear steady, no pressure signal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drift to 5.5.&lt;/strong&gt; Hours hit comfortably, two or more concepts closed the loop, fear steady or falling. Add one math-depth exercise next week.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compress to 4.5.&lt;/strong&gt; Hours missed two consecutive weeks, concepts stalled, or pressure signal active. Trim depth, ship a visible artifact, rebuild momentum.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logged to &lt;code&gt;CALIBRATION-LOG.md&lt;/code&gt; in the repo. One row per Sunday. Not merged with PROGRESS.md — those are different logs serving different readers (session-level vs trajectory-level).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the recalibration is Sunday-weekly
&lt;/h2&gt;

&lt;p&gt;Weekly is frequent enough to catch drift before it compounds across three sessions. Sunday is the edge between the prior week's evidence and the next week's planning. Running the recalibration on Wednesday loses one signal (the weekend's reflection); running it monthly loses three opportunities to adjust before the next month's plan locks in.&lt;/p&gt;

&lt;p&gt;The check is short — fifteen minutes. The discipline is not the minutes; it is the fact that the check happens at all, regardless of how the week went. Skipping the check because "this week was normal" is how the drift gets back in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 12-week escape hatch
&lt;/h2&gt;

&lt;p&gt;Every twelve weeks, a longer check. Three possible moves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compress to 3.5&lt;/strong&gt; if evidence is behind schedule and finances are tighter. Trim the depth track. Ship the hireable artifact earlier. Build the moat after income stabilizes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Widen to 5.5&lt;/strong&gt; if evidence is on schedule and momentum is strong. Add math depth. Deep-dive into fundamentals that did not make the shipping ordering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hold at 5&lt;/strong&gt; if the evidence is mixed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The 12-week cadence handles strategic drift. The weekly cadence handles short-term variance. Both are first-class.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the axis forbids
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Moving more than one position in a single week.&lt;/strong&gt; Abrupt drift destabilizes the trajectory. If the recalibration says 5 → 7, something is wrong with the diagnosis and it needs to be rerun.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drifting without evidence.&lt;/strong&gt; Moving up to 6 requires concepts that closed the loop, not hours sat in a chair. Compressing to 4.5 requires a real pressure signal, not a bad mood.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anchoring permanently.&lt;/strong&gt; The anchor is the current position. The drift is the trajectory. Both are first-class. If I am still anchored at 5 in six months without having drifted to 5.5 twice, either the framework is wrong or I am not earning the drift.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this is the highest-order rule in the framework
&lt;/h2&gt;

&lt;p&gt;Every trade-off during a teaching session or an engineering choice implicitly resolves at some position on the axis. Without the axis codified, the resolution is random — whichever intuition feels strongest in the moment. With the axis codified, the resolution is a reference: &lt;em&gt;"At 5, we derive before deploying, so we pause the shipping impulse and run the Socratic Q&amp;amp;A first."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The cost of the axis is fifteen minutes a week. The payoff is that six months of work compounds in one direction instead of averaging across two directions and producing neither a shipper nor a derivator.&lt;/p&gt;

&lt;p&gt;Pick your position. Write the axis down. Name the driver. Run the first Sunday check. Most of the compounding you want is downstream of those four actions — not of any specific technical choice.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The portfolio IS the product: recursive meta-engineering with Claude Code</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 03:14:11 +0000</pubDate>
      <link>https://dev.to/amanbhandari/the-portfolio-is-the-product-recursive-meta-engineering-with-claude-code-59nb</link>
      <guid>https://dev.to/amanbhandari/the-portfolio-is-the-product-recursive-meta-engineering-with-claude-code-59nb</guid>
      <description>&lt;p&gt;Most Claude-Code portfolios are &lt;em&gt;"here is a project I built with Claude."&lt;/em&gt; Mine is &lt;em&gt;"here is the system I use to build any project with Claude — and here is that system, on GitHub, dog-fooded by itself."&lt;/em&gt; The difference is structural, not aesthetic. The first shape produces artifacts that demonstrate a specific technique. The second shape produces an artifact that demonstrates the &lt;em&gt;meta-skill of designing systems like it&lt;/em&gt; — which is what the role above "senior engineer using AI tools" actually asks for.&lt;/p&gt;

&lt;p&gt;The framework is &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt;. The QA-automation surface built on top of that framework, demonstrating the pattern in production shape, is &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. The recursion is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The recursive property
&lt;/h2&gt;

&lt;p&gt;Every component of the framework &lt;em&gt;is&lt;/em&gt; the skill the framework teaches. That sentence is not a slogan. It is a checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context engineering.&lt;/strong&gt; The &lt;code&gt;CLAUDE.md&lt;/code&gt; in the framework demonstrates context engineering. Reading it is itself the lesson.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent tool design.&lt;/strong&gt; The &lt;code&gt;.claude/skills/&lt;/code&gt; directory demonstrates skill design. Opening a skill file is the example.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluation methodology.&lt;/strong&gt; The progressive-assessment rule demonstrates evaluation design. Running it on yourself is the practice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production thinking.&lt;/strong&gt; The integrity-check scripts and hooks demonstrate production safeguards. Running them before push is the habit they encode.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-agent architecture.&lt;/strong&gt; The HANDOVER + SYNC protocol (in a separate repo) demonstrates multi-agent coordination. Opening the convention is the lesson.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory and retrieval.&lt;/strong&gt; The two-artifact session capture (narrative + wiki) demonstrates persistent-context design. The wiki is both the example and the retrievable corpus.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most portfolios have one of these. The framework has all six, and each one is both the teaching artifact and the demonstration artifact simultaneously. A RAG system demonstrates RAG skill. This framework demonstrates the &lt;em&gt;skill of designing systems like RAG&lt;/em&gt; — which is the level above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this shape is the strongest hirable signal
&lt;/h2&gt;

&lt;p&gt;Anthropic's careers page says directly: &lt;em&gt;"If you've done interesting independent research, written an insightful blog post, or made substantial contributions to open-source software, put that at the TOP of your resume."&lt;/em&gt; Roughly half of their technical staff do not have PhDs.&lt;/p&gt;

&lt;p&gt;Eugene Yan's published evaluation criteria for AI engineers ask four questions: Can you handle ambiguity? Can you scope influence? Can you manage complexity? Can you execute under constraints?&lt;/p&gt;

&lt;p&gt;The recursive-meta-engineering shape answers all four at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ambiguity.&lt;/strong&gt; Designing a framework for coaching AI-engineering work is ambiguous by construction. There is no existing answer to the problem; the artifact is the answer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Influence.&lt;/strong&gt; A framework used across multiple surfaces (the learning lab, the QA-automation pipeline, any downstream adopter) is an influence-scope artifact that cannot be faked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity.&lt;/strong&gt; The framework has 15 rules, 21 skills, 5 repos, a HANDOVER + SYNC protocol, and a two-artifact session-capture pattern — managed coherently, not as accumulation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution under constraints.&lt;/strong&gt; The integrity-check scripts are what execution under constraints looks like: the framework cannot push without passing its own gates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One artifact, four answers. That is the shape an AI Lead role hires for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five repos as a single coherent artifact
&lt;/h2&gt;

&lt;p&gt;Public surface:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;claude-code-agent-skills-framework&lt;/strong&gt; — the rules, skills, and meta-framework. The teaching surface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;claude-code-mcp-qa-automation&lt;/strong&gt; — the production-QA pipeline built on top of the framework. Demonstrates the framework in working shape against a real workload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;claude-multi-agent-protocol&lt;/strong&gt; — HANDOVER + SYNC convention for multi-agent coordination. The scaling shape.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;llm-rag-knowledge-graph&lt;/strong&gt; — the session-capture + retrievable-wiki pattern as a standalone artifact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ai-engineer-lab&lt;/strong&gt; &lt;em&gt;(soon)&lt;/em&gt; — the lab that generated the prior four.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each repo stands alone. Read as a set, they describe a coherent system: the framework, a production demonstration of the framework, the multi-agent scaling pattern, the knowledge-retention pattern, and the lab that produced all of it. No repo is decoration. Each one is a surface the pattern ships against.&lt;/p&gt;

&lt;p&gt;This is different from a GitHub profile with twenty unconnected weekend projects. Twenty projects communicate breadth. Five interlocking projects communicate &lt;em&gt;that the author builds systems, not snippets&lt;/em&gt; — which is the level that matters for the roles that care.&lt;/p&gt;

&lt;h2&gt;
  
  
  The integrity-check CI pattern
&lt;/h2&gt;

&lt;p&gt;Every repo runs a &lt;code&gt;integrity-check.sh&lt;/code&gt; before push. Five gates: claim-evidence mapping, hype-word deny list, fresh-clone demo, private-identifier grep, secret-pattern grep. Plus artifact-specific checks per repo (determinism tests for the QA-automation pipeline, offline render checks for the report generator, etc.).&lt;/p&gt;

&lt;p&gt;The pattern is described in detail in an earlier post in this series. The fact worth surfacing here: these checks are a &lt;em&gt;recursive application of the framework to the framework&lt;/em&gt;. The rule that says "public artifacts must evidence their claims" is itself evidenced by the integrity-check script in every repo. The rule enforces the rule.&lt;/p&gt;

&lt;p&gt;This is what the meta-property looks like in production. The framework does not just teach the discipline. It runs the discipline against itself before shipping.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the recursion prevents
&lt;/h2&gt;

&lt;p&gt;Portfolios that describe a practice without demonstrating it accumulate claims faster than they accumulate evidence. Six months in, the README says "production-ready" and "scalable" and "comprehensive" and nothing in the repo proves any of those. The drift is quiet because nobody is running a falsifiability check.&lt;/p&gt;

&lt;p&gt;Recursive application catches this. If the framework claims "every rule carries a WHY and a retire-when clause," then the framework's own rules are checked against that claim. If the framework claims "every skill is a markdown contract, not code," then the framework's own skills are checked against that claim. The check is automatic because the same discipline the framework teaches is the discipline it is audited against.&lt;/p&gt;

&lt;p&gt;An artifact that cannot apply its own rules to itself is an artifact whose rules are aspirational. The recursive shape is what makes them operational.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this shape does NOT give you
&lt;/h2&gt;

&lt;p&gt;Three honest limits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It does not replace the specific-domain artifact.&lt;/strong&gt; If you are applying for an LLM-serving role, you still need an LLM-serving artifact. The meta-framework is the level above, not a substitute for the level. Both are needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is not a shortcut to seniority.&lt;/strong&gt; Building a framework that works requires having seen enough failures to know what the failure modes are. The recursion makes the seniority visible; it does not confer it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It does not run itself.&lt;/strong&gt; Someone maintains the framework, runs the audit when a new model ships, and writes the rules that earn their presence. This is work. The recursion is high-payoff; it is not effort-free.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The move you can make this week
&lt;/h2&gt;

&lt;p&gt;If you are building toward an AI-engineering role, the shape I am describing is a concrete pattern you can adopt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pick the &lt;em&gt;one&lt;/em&gt; discipline you find yourself repeating across Claude Code projects — prompt hygiene, skill design, trace labeling, whatever.&lt;/li&gt;
&lt;li&gt;Write it down as a rule file in a public repo with a WHY tag and a retire-when clause.&lt;/li&gt;
&lt;li&gt;Build a second repo that &lt;em&gt;uses&lt;/em&gt; that rule and cite it explicitly in the README.&lt;/li&gt;
&lt;li&gt;Run an integrity-check script that enforces the rule on both repos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two repos with a rule that connects them is the starter shape. Five interlocking repos is the advanced shape. The important thing is that the rule ships and the rule is audited against its own claims.&lt;/p&gt;

&lt;p&gt;That is the recursive-meta-engineering move. It is available to anyone. What it asks for is that you take your own practice seriously enough to codify it and then seriously enough to audit it against the codification.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I turned 10 practitioners into a single .claude/ pedagogy</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 03:04:25 +0000</pubDate>
      <link>https://dev.to/amanbhandari/how-i-turned-10-practitioners-into-a-single-claude-pedagogy-5dje</link>
      <guid>https://dev.to/amanbhandari/how-i-turned-10-practitioners-into-a-single-claude-pedagogy-5dje</guid>
      <description>&lt;p&gt;Every rule in my &lt;code&gt;.claude/&lt;/code&gt; directory cites the practitioner whose working method it leans on. This is not reading-list decoration. It is a traceability requirement: if a teaching exchange or an engineering decision cannot be pinned to a named 2025-2026 practitioner doing that specific thing in public, the rule is ungrounded and gets removed.&lt;/p&gt;

&lt;p&gt;Eight practitioners form the spine. The five-node concentric loop pins each node to one or two of them. The five agentic-engineering habits pin each habit to one. Together they define what the framework inherits from the applied community instead of inventing in a vacuum.&lt;/p&gt;

&lt;p&gt;Framework repo: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The eight, by node and habit
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Chip Huyen — Code / I-O framing (concentric-loop Node 2).&lt;/strong&gt; Every code node opens with explicit input/output specification: what goes in, what comes out, what data is available at what latency tier (online / nearline / offline). The latency-tier framing originates with the Netflix recommendation system (Amatriain and Basilico, 2013). Huyen mainstreamed it in &lt;em&gt;Designing Machine Learning Systems&lt;/em&gt;, Chapter 2. Source: &lt;a href="https://chiphuyen.com" rel="noopener noreferrer"&gt;chiphuyen.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eugene Yan — Start with the problem, not the technology (Node 3 baseline, agentic Habit 4 prerequisite).&lt;/strong&gt; Before any ML or agent component is introduced, ask: what regex, SQL, or rule-based filter already gets 50-70%? The Four Questions (what is the problem, who has it, would a non-AI solution work, what does success look like measurably) come from Yan's applied-LLM writing. Source: &lt;a href="https://eugeneyan.com/start-here/" rel="noopener noreferrer"&gt;eugeneyan.com/start-here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hamel Husain — Manual trace labeling (Node 3, agentic Habit 4).&lt;/strong&gt; Before trusting an LLM or agent at scale, label 20-100 real traces by hand. The trace becomes the eval harness. Husain's 90%+ human-judge agreement in his LLM-judge field guide is a workflow outcome, not a universal KPI — he explicitly warns raw agreement misleads on imbalanced data. Source: &lt;a href="https://hamel.dev/blog/posts/field-guide/" rel="noopener noreferrer"&gt;hamel.dev/blog/posts/field-guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jeremy Howard — Top-down learning (Node 4).&lt;/strong&gt; fast.ai Part 1. Get a working artifact end-to-end first, then spiral into mechanism. Whole game, then atoms, then whole game with new eyes. Source: &lt;a href="https://course.fast.ai" rel="noopener noreferrer"&gt;course.fast.ai&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sebastian Raschka — Bottom-up from scratch (Node 4, paired with Howard).&lt;/strong&gt; &lt;em&gt;Build a Large Language Model from Scratch&lt;/em&gt;. Raw tensors, manual attention, instruction-finetuning implemented by hand. The bottom-up complement to Howard's top-down. Source: &lt;a href="https://sebastianraschka.com" rel="noopener noreferrer"&gt;sebastianraschka.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Andrej Karpathy — Atomic derivation (Node 5, agentic Habit 5).&lt;/strong&gt; Shrink the concept until it fits in your head. micrograd is 100 lines of autograd; nanoGPT is 300 lines of training. The 40-line version is what you review the 40,000-line version against. Source: &lt;a href="https://karpathy.ai/zero-to-hero.html" rel="noopener noreferrer"&gt;karpathy.ai/zero-to-hero&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Julia Evans — OS descent safety net (Node 5 paired with Karpathy).&lt;/strong&gt; When an abstraction leaks, drop to strace, tcpdump, perf, /proc. Evans's zines and blog are the field guide for the moment an explanation stops working at the application layer and the real answer is two layers below. Source: &lt;a href="https://jvns.ca" rel="noopener noreferrer"&gt;jvns.ca&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Harper Reed — Spec first (agentic Habit 1).&lt;/strong&gt; Every agent-led task starts with &lt;code&gt;idea.md&lt;/code&gt; (brainstorm) and &lt;code&gt;plan.md&lt;/code&gt; (plan). The agent executes against the plan; the operator reviews the plan, not every line of code. The compounding artifact is the spec plus plan, not the code. Source: &lt;a href="https://harper.blog/2025/02/16/my-llm-codegen-workflow-atm/" rel="noopener noreferrer"&gt;harper.blog/2025/02/16/my-llm-codegen-workflow-atm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Geoffrey Litt — Primary/secondary split (agentic Habit 2).&lt;/strong&gt; Tight-loop design stays human-primary. The agent is a pair-programmer at most. Well-defined execution goes async to agents and is reviewed in batch. Two parallel streams, rotated consciously. Source: &lt;a href="https://www.geoffreylitt.com" rel="noopener noreferrer"&gt;geoffreylitt.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shrivu Shankar — Agent primitive vocabulary (agentic Habit 3).&lt;/strong&gt; Three reusable patterns for multi-agent work: assembly-line (sequential pipeline), call-center (router + specialists), manager-worker (decompose + aggregate). Pick the one that matches the job shape; do not default to the most complex. Source: &lt;a href="https://blog.sshh.io" rel="noopener noreferrer"&gt;blog.sshh.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(The list counts ten names because Howard/Raschka and Karpathy/Evans each pair on a node. Eight distinct nodes + habits, ten distinct practitioners.)&lt;/p&gt;

&lt;h2&gt;
  
  
  The extraction method — what I actually read for
&lt;/h2&gt;

&lt;p&gt;These practitioners did not write rules for me. They wrote blog posts, books, lectures, tweets. I extracted the rules by reading for a specific thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not what they argue for.&lt;/strong&gt; Their theses are often context-dependent and date fast. Yan's position on when to reach for ML versus a regex is a working stance, not a universal claim.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not their specific tools.&lt;/strong&gt; The tools they reach for (Aider for Reed, fast.ai's library for Howard, a specific Jupyter setup for Raschka) will rotate. Reading for the tool produces a rule that retires in 18 months.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I read for: the workflow and the failure mode.&lt;/strong&gt; Reed writes down his codegen workflow explicitly. Husain writes down the trace-labeling routine explicitly. Shankar names the three agent primitives explicitly. The workflow is transferable. The failure mode each workflow prevents is the part that compounds across domains.&lt;/p&gt;

&lt;p&gt;Applied practitioners publish the workflow, the failure mode, and the eval loop. Researchers publish the result. The result is often non-transferable; the workflow almost always is. The eight practitioners above are applied practitioners specifically because of this property — they write about how they work, not only about what they produced.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this pinning matters
&lt;/h2&gt;

&lt;p&gt;Without practitioner pinning, rules drift. A rule that says "always derive before deploying" sounds authoritative until it has been in the file for six months and nobody can remember why it was written or what it corrects. Six months later somebody else edits it because a different-sounding advice from a different blog post feels more recent, and the original intent gets quietly overwritten.&lt;/p&gt;

&lt;p&gt;With pinning, the rule is anchored: &lt;em&gt;"This rule is the Karpathy atomic-derivation discipline applied to the learning pipeline. If the Karpathy constraint stops being load-bearing for this work, the rule retires."&lt;/em&gt; The retirement condition is falsifiable. The rule's origin is traceable. Edits that drift from the original practitioner's position get flagged on next audit.&lt;/p&gt;

&lt;p&gt;Pinning also blocks a specific failure mode: manufacturing a rule from thin air, calling it a best practice, and committing it to the canon. A rule that cannot be pinned to a practitioner doing that specific thing in public is probably either obvious (and does not need a rule) or invented (and should not be canonized).&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-rule-per-practitioner shape is on purpose
&lt;/h2&gt;

&lt;p&gt;Each practitioner occupies one node in the loop or one habit in the agentic-engineering rule. They do not appear everywhere. Pinning a practitioner to multiple roles is how you lose the specificity that made the pinning worth doing in the first place.&lt;/p&gt;

&lt;p&gt;Husain is on Node 3 (manual trace labeling) and Habit 4 (eval on agent output) because those are the same discipline at two surfaces. He is not on Node 5 or Habit 2, because his public writing is not where I go for atomic derivation or for primary/secondary split. Respecting what each practitioner is specifically good at is what keeps the rules tight.&lt;/p&gt;

&lt;h2&gt;
  
  
  The capstone effect
&lt;/h2&gt;

&lt;p&gt;When the framework reaches the point where every rule has a WHY tag, a retire-when clause, and a practitioner pin, the result is a system that decays cleanly rather than accumulating silently. New model? Audit the WHY tags against the retire-when clauses. Shifted stack? Audit the practitioner pins and check whether the cited 2025-2026 methods still apply.&lt;/p&gt;

&lt;p&gt;This is the opposite of the usual trajectory for &lt;code&gt;.claude/&lt;/code&gt; directories, which grow organically to 50 rules, become furniture, and start fighting improved model defaults without anybody noticing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with this pattern
&lt;/h2&gt;

&lt;p&gt;Pick one practitioner you already read. Name the specific workflow you inherit from them. Turn it into one rule. Tag it with the practitioner. Add the WHY and retire-when clauses. Commit.&lt;/p&gt;

&lt;p&gt;One rule, one practitioner, one audit condition. Do it for three practitioners you respect. The result is a framework you can actually defend in a year — because every rule in it points at somebody doing the work in public, and somebody's public work is a standard you can audit against when the model shifts underneath you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>learning</category>
      <category>career</category>
    </item>
    <item>
      <title>Session capture as a dual artifact: narrative log plus retrievable wiki</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 03:00:01 +0000</pubDate>
      <link>https://dev.to/amanbhandari/session-capture-as-a-dual-artifact-narrative-log-plus-retrievable-wiki-161j</link>
      <guid>https://dev.to/amanbhandari/session-capture-as-a-dual-artifact-narrative-log-plus-retrievable-wiki-161j</guid>
      <description>&lt;p&gt;Only a chat log is a diary you cannot query. Only atomic notes is a corpus you cannot narrate. Writing both — every working session, in real time — is what makes past work both retrievable and tellable without turning Claude into your personal journal service.&lt;/p&gt;

&lt;p&gt;This is the pattern I run against every working session in the lab. Two artifacts, always. The narrative log feeds a future chronicle. The atomic wiki feeds retrieval — via an Obsidian graph for the human, and via a RAG corpus for the system. Same exchange, two audiences, two compounding artifacts.&lt;/p&gt;

&lt;p&gt;Reference surfaces: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; has the rule; &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt; demonstrates the same discipline applied to sprint data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Artifact 1 — The session log (narrative, chronological)
&lt;/h2&gt;

&lt;p&gt;Lives at &lt;code&gt;knowledge/sessions/YYYY-MM-DD.md&lt;/code&gt;. One file per session. Chronological, story-shaped, written in real time as the session unfolds.&lt;/p&gt;

&lt;p&gt;The schema per exchange:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Exchange N — &amp;lt;concept name&amp;gt;&lt;/span&gt;

&lt;span class="gs"&gt;**I asked:**&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;verbatim&lt;/span&gt; &lt;span class="na"&gt;or&lt;/span&gt; &lt;span class="na"&gt;close&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;actual&lt;/span&gt; &lt;span class="na"&gt;words&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;confusion&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;analogy&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gs"&gt;**What I already understood:**&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;the&lt;/span&gt; &lt;span class="na"&gt;correct&lt;/span&gt; &lt;span class="na"&gt;parts&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gs"&gt;**What was missing:**&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;the&lt;/span&gt; &lt;span class="na"&gt;gap&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;exchange&lt;/span&gt; &lt;span class="na"&gt;addressed&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gs"&gt;**The teaching exchange:**&lt;/span&gt; &amp;lt;the analogy used, the mechanism explained,
the real-world context&amp;gt;

&lt;span class="gs"&gt;**Analogy-failure moment:**&lt;/span&gt; &amp;lt;where the opening analogy did not map to
the technical reality — the sentence or mismatch that forced the mental
model to upgrade&amp;gt;

&lt;span class="gs"&gt;**The breakthrough:**&lt;/span&gt; &lt;span class="nt"&gt;&amp;lt;the&lt;/span&gt; &lt;span class="na"&gt;moment&lt;/span&gt; &lt;span class="na"&gt;it&lt;/span&gt; &lt;span class="na"&gt;clicked&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;in&lt;/span&gt; &lt;span class="na"&gt;my&lt;/span&gt; &lt;span class="na"&gt;own&lt;/span&gt; &lt;span class="na"&gt;words&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gs"&gt;**My return line:**&lt;/span&gt; &amp;lt;my own words at the close where the upgraded
mental model landed — verbatim&amp;gt;

&lt;span class="gs"&gt;**Concept linked:**&lt;/span&gt; [[wiki-page]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two beats in that schema are load-bearing and cannot be fabricated after the fact: the &lt;strong&gt;analogy-failure moment&lt;/strong&gt; and the &lt;strong&gt;return line&lt;/strong&gt;. These are the concentric-loop proof-of-completion signals. Without both, the loop collapsed into documentation and the concept did not actually land.&lt;/p&gt;

&lt;p&gt;The session log is not a transcript. It is a curated narrative of the teaching moves that worked, with the specific points where the mechanism upgraded the learner's mental model. A future narrator — whether me writing a chronicle, a chronicler agent reading the session logs, or a reader retracing how the learning happened — uses this file as the primary source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Artifact 2 — The atomic wiki (retrievable, cross-linked)
&lt;/h2&gt;

&lt;p&gt;Lives at &lt;code&gt;knowledge/wiki/&amp;lt;category&amp;gt;/&amp;lt;concept&amp;gt;.md&lt;/code&gt;. One file per atomic concept. Each file cross-links to related concepts using &lt;code&gt;[[wiki-link]]&lt;/code&gt; syntax.&lt;/p&gt;

&lt;p&gt;The shape per wiki page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# &amp;lt;concept-name&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## What it is&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;one-paragraph&lt;/span&gt; &lt;span class="na"&gt;definition&lt;/span&gt; &lt;span class="na"&gt;in&lt;/span&gt; &lt;span class="na"&gt;my&lt;/span&gt; &lt;span class="na"&gt;own&lt;/span&gt; &lt;span class="na"&gt;words&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Mechanism&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;what&lt;/span&gt; &lt;span class="na"&gt;actually&lt;/span&gt; &lt;span class="na"&gt;happens&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;layer&lt;/span&gt; &lt;span class="na"&gt;the&lt;/span&gt; &lt;span class="na"&gt;concept&lt;/span&gt; &lt;span class="na"&gt;lives&lt;/span&gt; &lt;span class="na"&gt;at&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Related&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [[parent-concept]]
&lt;span class="p"&gt;-&lt;/span&gt; [[sibling-concept-1]]
&lt;span class="p"&gt;-&lt;/span&gt; [[sibling-concept-2]]

&lt;span class="gu"&gt;## First encountered&lt;/span&gt;
Session YYYY-MM-DD, Exchange N.

&lt;span class="gu"&gt;## Whiteboard-test status&lt;/span&gt;
Not yet tested / Passed on &lt;span class="nt"&gt;&amp;lt;date&amp;gt;&lt;/span&gt; / Fragile (retry scheduled)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plus three index-level files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;knowledge/wiki/index.md&lt;/code&gt; — updated on every page addition, with the new entry alphabetized.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;knowledge/wiki/log.md&lt;/code&gt; — append-only change log for every wiki edit.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;knowledge/wiki/&amp;lt;category&amp;gt;/&lt;/code&gt; — directory structure by domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The wiki is built incrementally, one atomic concept per entry, cross-linked as it grows. Over months it becomes a second brain — readable by hand (as an Obsidian graph) and queryable by retrieval (as a RAG corpus against my own thinking).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the split matters
&lt;/h2&gt;

&lt;p&gt;Single-artifact patterns fail, and they fail in opposite directions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session-log-only.&lt;/strong&gt; You have a chronological story. You cannot answer &lt;em&gt;"what do I know about dict internals?"&lt;/em&gt; without scrolling through six months of session logs. The log is narrative but not retrievable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wiki-only.&lt;/strong&gt; You have an atomic knowledge graph. You cannot answer &lt;em&gt;"how did I come to understand this?"&lt;/em&gt; because the wiki page strips out the teaching exchange that produced the understanding. The wiki is retrievable but not narrative.&lt;/p&gt;

&lt;p&gt;Both artifacts are the same exchange read two different ways. Writing both in real time costs 20% more than writing one, and buys you both retrieval and narrative — the expensive-to-reconstruct artifact is not the one you write, it is the one you skip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you cannot batch this
&lt;/h2&gt;

&lt;p&gt;The analogy-failure moment and the return line are ephemeral. By the end of the session they have faded from working memory. By the next day they are reconstructed — which means they are lies. Accurate capture requires writing the exchange within minutes of it happening, while the specific words the learner used are still present.&lt;/p&gt;

&lt;p&gt;Batching session capture to "I'll write it up on the weekend" produces sanitized summaries with none of the narrative texture a chronicler needs. The breakthrough beat is where a reader feels the concept land. That beat is in the exact words of the learner at the exact moment, not in a weekend summary written after four other sessions have blurred the original.&lt;/p&gt;

&lt;p&gt;Real-time, or not at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The log.md append-only change log
&lt;/h2&gt;

&lt;p&gt;Every wiki edit gets an entry in &lt;code&gt;knowledge/wiki/log.md&lt;/code&gt;. Timestamp, file edited, summary of the change, reason. Append-only.&lt;/p&gt;

&lt;p&gt;This seems redundant (git already records edits) and is not. Git records &lt;em&gt;what&lt;/em&gt; changed; the log records &lt;em&gt;why&lt;/em&gt;, in the maintainer's own words, at the time of the change. A git blame six months from now will show you the diff. The log will tell you why the diff was worth making.&lt;/p&gt;

&lt;p&gt;For a corpus that compounds, the &lt;em&gt;why&lt;/em&gt; is what keeps edits principled. Without it, the wiki drifts into a collection of edits made because some session surfaced something new — without any record of which edits were critical versus incidental. The log separates the two.&lt;/p&gt;

&lt;h2&gt;
  
  
  The RAG corpus payoff
&lt;/h2&gt;

&lt;p&gt;The wiki is writable by me and readable by me, but also readable by a RAG system against my own thinking. That second reader matters. Over months, the wiki becomes a retrieval corpus whose answers are grounded in the specific understanding of a specific learner — me — not in an average of the internet's understanding of the same concept.&lt;/p&gt;

&lt;p&gt;A RAG query like &lt;em&gt;"what did I conclude about backprop and why?"&lt;/em&gt; returns wiki pages I wrote, with cross-links to the sessions that produced them, and with my own wording of the mechanism. This is different from a generic search over Wikipedia or a generic LLM answer. It is grounded in one specific person's trajectory.&lt;/p&gt;

&lt;p&gt;Building that corpus requires the atomic-wiki discipline. A session-log-only pattern does not produce it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The chronicle payoff
&lt;/h2&gt;

&lt;p&gt;The session log is the raw material for a longer-form narrative — the chronicle of &lt;em&gt;how the learning happened&lt;/em&gt;. A chronicler agent (or a human writing a blog series, or a learner retracing their own path a year later) reads the session logs as the source text.&lt;/p&gt;

&lt;p&gt;The chronicle cannot be written without the narrative texture the session log preserves. The wiki gives you the facts. The session log gives you the story. Stories are what readers engage with; facts are what they refer back to. Both audiences need their own artifact.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does NOT require
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not every conversation.&lt;/strong&gt; Trivial questions, casual checks, throwaway experiments do not earn the dual artifact. The rule fires on teaching exchanges that moved a concept from "not understood" to "understood" — the ones that matter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a perfect schema.&lt;/strong&gt; The format above is what I use; you can adapt it. The two invariants are: (a) chronological narrative file with the analogy-failure and return-line beats preserved, and (b) atomic concept file that cross-links to related concepts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not a substitute for code.&lt;/strong&gt; Session logs and wiki pages are not where production work ships. They are where understanding is preserved so production work can build on it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The move
&lt;/h2&gt;

&lt;p&gt;If you are serious about compounding your own learning: pick one working session this week. Write both artifacts from it. One narrative file, one wiki page per concept that landed. Cross-link the wiki pages to each other as you write them.&lt;/p&gt;

&lt;p&gt;The discipline takes twenty extra minutes per session. The payoff compounds across every future session that retrieves from the resulting corpus.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>HANDOVER + SYNC: multi-agent coordination without a central scheduler</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 02:56:47 +0000</pubDate>
      <link>https://dev.to/amanbhandari/handover-sync-multi-agent-coordination-without-a-central-scheduler-20dc</link>
      <guid>https://dev.to/amanbhandari/handover-sync-multi-agent-coordination-without-a-central-scheduler-20dc</guid>
      <description>&lt;p&gt;Three or more Claude Code agents, each owning their own repo. No central scheduler. No shared database. No message bus. Two markdown files at known paths and a single convention that keeps them consistent. That is it.&lt;/p&gt;

&lt;p&gt;The protocol is &lt;a href="https://github.com/aman-bhandari/claude-multi-agent-protocol" rel="noopener noreferrer"&gt;claude-multi-agent-protocol&lt;/a&gt;. I run it across four agent positions and four repos in my own research setup: the lab itself, a downstream recorder, a publisher, and a shared commons. This post is the protocol written up as a generalizable pattern — not a tutorial for the specific repos.&lt;/p&gt;

&lt;p&gt;The failure mode it prevents: every Claude Code multi-agent setup I have seen attempts to share mutable state, and every one eventually conflates two distinct flows — &lt;em&gt;data&lt;/em&gt; (what happened) and &lt;em&gt;intent&lt;/em&gt; (what we plan to do next). The conflation is what produces rubber-stamp rewrites, where agent B overwrites agent A's change because it could not distinguish "this is a fact" from "this is a proposal."&lt;/p&gt;

&lt;p&gt;Separate the flows. One file per flow. Separate ownership rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flow 1 — Data, one-way, single-writer
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;HANDOVER.md&lt;/code&gt; lives in the upstream agent's repo. It is append-only. It has one writer — the upstream agent. Downstream agents read it, never write to it.&lt;/p&gt;

&lt;p&gt;The content is factual: &lt;em&gt;"Latest run completed. New concepts landed: dict internals, reference semantics. Broken: three whiteboard-test attempts on JSON deserialization. Committed: commit hash X."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The shape is chronological. Each entry is tagged with a timestamp or sequence number. Nothing previously written is modified. If the upstream agent was wrong about something, the correction gets appended as a new entry referencing the old one — not an edit to the old entry.&lt;/p&gt;

&lt;p&gt;The reason for single-writer append-only: &lt;code&gt;HANDOVER.md&lt;/code&gt; is the data source of truth for everything downstream. If any downstream agent can write to it, two agents will write at once, git will produce a merge conflict, and a human will resolve the conflict by picking whichever version looks right — which is how the truth state of the system gets silently corrupted.&lt;/p&gt;

&lt;p&gt;Single-writer is boring. Boring is what makes it reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flow 2 — Intent, bidirectional, per-agent sections
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;SYNC.md&lt;/code&gt; lives in a shared commons repo that every agent has access to. It has bidirectional ownership: each agent owns a section. Every agent reads every section; each agent writes only to their own section.&lt;/p&gt;

&lt;p&gt;The content is forward-looking: &lt;em&gt;"I am about to start X. I need Y from upstream. I am blocked on Z. My next three actions are A, B, C."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The shape is per-agent. The file has five sections if there are five agents: &lt;code&gt;## partner&lt;/code&gt;, &lt;code&gt;## observer&lt;/code&gt;, &lt;code&gt;## publisher&lt;/code&gt;, &lt;code&gt;## commons&lt;/code&gt;, &lt;code&gt;## principal&lt;/code&gt;. Each section has three fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Current focus.&lt;/strong&gt; One sentence on what the agent is working on now.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blocked on.&lt;/strong&gt; What the agent needs to proceed. Empty if nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next action.&lt;/strong&gt; The concrete next step the agent intends to take.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three fields is the minimum that captures intent without encoding a plan. Four fields is where it starts being a planning doc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the two-file split is the specific fix
&lt;/h2&gt;

&lt;p&gt;Most multi-agent setups fail because they use one file for both flows. Either they put planning inline with facts (and agents start editing past facts to make the plan consistent), or they put facts inline with planning (and downstream agents see stale plans mixed with fresh facts and cannot tell which is which).&lt;/p&gt;

&lt;p&gt;The split gives each flow the semantics it needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data (HANDOVER) needs reliability and history.&lt;/strong&gt; Single-writer, append-only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intent (SYNC) needs freshness and bidirectional visibility.&lt;/strong&gt; Per-agent sections, overwritable within the section, reset on each sync.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conflating the two makes both worse. Separating them makes both load-bearing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Single-writer-per-section is what git already gives you
&lt;/h2&gt;

&lt;p&gt;The per-agent section rule on SYNC.md means that in practice, git is the serializer. Two agents writing to different sections produce a clean merge. Two agents writing to the same section — which should not happen because each section has one owner — produces a merge conflict that surfaces the bug.&lt;/p&gt;

&lt;p&gt;You do not need a coordination service. You do not need locks. You do not need Redis. The section-ownership rule plus git is sufficient for coordination at the 5-10 agent scale. Beyond that, you might need something else. Below that, this is enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CLAUDE.md precedence rule
&lt;/h2&gt;

&lt;p&gt;Each repo has its own &lt;code&gt;CLAUDE.md&lt;/code&gt; (or equivalent agent-identity file). Each agent has its own rules of behavior. &lt;code&gt;SYNC.md&lt;/code&gt; does not override those rules.&lt;/p&gt;

&lt;p&gt;The precedence rule: on conflict, the repo's own &lt;code&gt;CLAUDE.md&lt;/code&gt; wins over anything in the shared &lt;code&gt;SYNC.md&lt;/code&gt;. An agent whose repo says "never push to main without review" does not get overridden by a SYNC.md entry from another agent saying "please push your change to main." The identity file of each agent is sovereign.&lt;/p&gt;

&lt;p&gt;This matters because without the rule, a malicious or confused SYNC.md entry could instruct another agent to violate its own constraints. With the rule, SYNC.md is advisory for behavior outside the repo's own rules, and irrelevant for behavior governed by those rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;.last-processed.md&lt;/code&gt; marker
&lt;/h2&gt;

&lt;p&gt;Each downstream agent keeps its own &lt;code&gt;.last-processed.md&lt;/code&gt; marker in its own repo. The marker records: &lt;em&gt;"I last processed HANDOVER.md entries up to sequence N at time T."&lt;/em&gt; When the agent is asked "any update?", it reads HANDOVER.md from N+1 onward, processes the new entries, and updates the marker.&lt;/p&gt;

&lt;p&gt;This is standard offset-based consumption, the same pattern used by Kafka consumers and similar event-log systems. The novelty is that it works with markdown files and git instead of a broker.&lt;/p&gt;

&lt;p&gt;Without the marker, each downstream "check for updates" either reprocesses everything or has to remember a sequence number in memory that is lost on restart. With the marker, the agent restarts cleanly, processes incrementally, and the protocol is stateless across agent sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The research-vs-documentation split
&lt;/h2&gt;

&lt;p&gt;In my setup, the research subject is one specific pair (Principal + Partner). The other agents are infrastructure — a recorder that preserves sessions as narrative, a publisher that renders artifacts for the public. The infrastructure agents read HANDOVER from the research pair; the research pair does not read FROM them.&lt;/p&gt;

&lt;p&gt;This is a deliberate asymmetry. If the downstream agents could write back into the research pair's state, the research subject would be contaminated by its own observers — which is a known failure mode in ethnographic research and a direct failure mode in multi-agent systems where downstream feedback changes upstream behavior.&lt;/p&gt;

&lt;p&gt;The HANDOVER direction is irreversible on purpose. Downstream knows about upstream. Upstream does not know about downstream's interpretation. The protocol preserves this.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this protocol does NOT solve
&lt;/h2&gt;

&lt;p&gt;Three honest limits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. It does not coordinate real-time interactions.&lt;/strong&gt; HANDOVER + SYNC are per-session artifacts. Agents reading each other's files are not reading a live event stream. For anything that needs sub-second coordination, you want a real message bus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. It does not enforce the convention.&lt;/strong&gt; The protocol is discipline, not compilation. If an agent writes to somebody else's section, git will merge-conflict, and a human has to notice. A compiled DSL could enforce section ownership structurally. This protocol does not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. It does not scale past 10-ish agents.&lt;/strong&gt; At that scale, SYNC.md becomes a 500-line file nobody reads. The protocol assumes a small enough team that every agent can read every section in under a minute. If the team is larger, you partition — multiple SYNC.md files by subsystem, or a different coordination pattern entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to reach for this versus not
&lt;/h2&gt;

&lt;p&gt;Reach for HANDOVER + SYNC when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have 2-8 Claude Code agents, each in their own repo.&lt;/li&gt;
&lt;li&gt;The work is async — agents do not need to coordinate in real-time.&lt;/li&gt;
&lt;li&gt;Data and intent flows are genuinely distinct (facts versus plans).&lt;/li&gt;
&lt;li&gt;A compiled scheduler would be overkill; a global file would be underkill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not reach for it when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single repo with good directory structure would suffice.&lt;/li&gt;
&lt;li&gt;The agents are hot-loop coordinated (inference pipeline, live routing).&lt;/li&gt;
&lt;li&gt;The team is large enough that SYNC.md becomes unreadable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my case, the pattern solved a real coordination problem I was going to hit anyway once the setup grew past two agents. Two files, one convention, zero merge conflicts in normal operation. That is the shape. If it matches your setup, steal it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>architecture</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Skills as invocation contracts, not code: how I keep review authority over agent work</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 02:53:46 +0000</pubDate>
      <link>https://dev.to/amanbhandari/skills-as-invocation-contracts-not-code-how-i-keep-review-authority-over-agent-work-1lej</link>
      <guid>https://dev.to/amanbhandari/skills-as-invocation-contracts-not-code-how-i-keep-review-authority-over-agent-work-1lej</guid>
      <description>&lt;p&gt;When a skill is code, you review code. When a skill is a markdown contract, you review the contract — and the implementation gets re-typed by an agent under it. One scales to dozens of agents operating on the same surface. The other collapses the moment the implementation needs to be re-read by a human.&lt;/p&gt;

&lt;p&gt;This is the pattern I run in &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. Sixteen skills live as pure markdown files. The Python implementation underneath can be swapped — rewritten, refactored, replaced — without touching the skill surface. Review authority stays where it belongs: on the contracts, not on every generated line.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a SKILL.md actually contains
&lt;/h2&gt;

&lt;p&gt;A skill file is not documentation. It is an invocation contract. Four sections, each with a specific purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontmatter.&lt;/strong&gt; Name, description, one or two tags. This is what the agent loader uses to select and index the skill. The description is read by the system, not a human — it is optimized for match quality, not prose quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inputs.&lt;/strong&gt; What the skill expects to receive. Types, shapes, required fields, failure conditions on missing inputs. If a caller sends a malformed input, the skill's behavior is determined here, not in the implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Work delegated.&lt;/strong&gt; What the skill does. Not how. The contract names the mechanism at the level a reviewer needs to understand: &lt;em&gt;"pulls the sprint's tickets from Jira, aggregates status transitions into the trending store, writes one row per (ticket, day)."&lt;/em&gt; The implementation details — which Python library, which HTTP client, which pagination strategy — live in code, not in the contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure modes distinguished.&lt;/strong&gt; The specific failure types the skill surfaces separately: transient Jira error, auth failure, schema mismatch, rate-limited retries exhausted. Each with its own handler and its own log shape.&lt;/p&gt;

&lt;p&gt;A reviewer reads those four sections. If they match the intended behavior, the skill passes review. The implementation underneath gets swapped on whatever cadence the team needs — daily, if the agent is rewriting it — without triggering another review cycle, because the contract did not change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this scales and code-skills do not
&lt;/h2&gt;

&lt;p&gt;Two patterns, two scaling curves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code-as-skill.&lt;/strong&gt; Each skill is a Python module or a set of functions. A reviewer has to read the code to understand the behavior. Adding a new skill means writing, testing, and reviewing more code. Swapping implementation means rewriting the review. The scaling bottleneck is human review capacity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Markdown-as-skill.&lt;/strong&gt; Each skill is a contract. A reviewer reads the contract. Adding a new skill means writing a contract. The implementation is produced under the contract by whichever agent or engineer is fastest at that specific stack. Swapping implementation means regenerating under the same contract.&lt;/p&gt;

&lt;p&gt;The second pattern survives agent re-typing. An LLM that regenerates the implementation cannot change the contract without the reviewer noticing. An LLM that regenerates code-as-skill silently changes the surface and the reviewer has to catch it in the diff — which is the failure mode the agentic-engineering discipline names as blind diff-accepting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sub-agent orchestration under the contract
&lt;/h2&gt;

&lt;p&gt;The QA-automation pipeline has a coordinator that fans out work to sub-agents. The sub-agents operate per-board (one per Jira board, in parallel). The coordinator aggregates their output into a unified report.&lt;/p&gt;

&lt;p&gt;In production, the coordinator would use Claude Code's &lt;code&gt;Agent&lt;/code&gt; tool. In the reference implementation, the coordinator uses &lt;code&gt;ThreadPoolExecutor&lt;/code&gt; as a structurally-identical stand-in. Same fan-out shape, same aggregation semantics, same deterministic output — but the reference runs without requiring live Claude calls, which makes it reviewable end-to-end on any CI runner.&lt;/p&gt;

&lt;p&gt;The skill file for the coordinator names the contract: &lt;em&gt;inputs are a list of boards, outputs are one report per board plus one roll-up, failure of any sub-agent does not fail the whole fan-out.&lt;/em&gt; The implementation (ThreadPoolExecutor or Agent tool) is a detail that can change without the contract changing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flag-gated, config-driven execution
&lt;/h2&gt;

&lt;p&gt;Every behavior that could be on or off lives in &lt;code&gt;config/flags.yaml&lt;/code&gt; with global and board-scoped overrides. No inline &lt;code&gt;if FEATURE_FOO:&lt;/code&gt; toggles in the Python.&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="na"&gt;flags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;enable_trending&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;slack_digest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;include_closed_tickets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;boards&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ENG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;include_closed_tickets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;OPS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;slack_digest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regression debugging starts with flipping a flag and re-running, not with a code spelunk. A bug report comes in: "the OPS digest is missing since Tuesday." The first check is &lt;code&gt;config/flags.yaml&lt;/code&gt; — was the flag flipped? If yes, that is the cause. If no, the bug is in the code path, which is the second check.&lt;/p&gt;

&lt;p&gt;This separation is what makes the pipeline auditable. The config is source-controlled. Every flag flip is a commit. The diff between "what produced last Friday's report" and "what produced today's report" is always visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deterministic, reviewable output
&lt;/h2&gt;

&lt;p&gt;The reports themselves are single HTML files with inline CSS, zero JavaScript, no external references. That constraint is not cosmetic. It is what makes them reviewable offline, archivable, diffable byte-for-byte under identical flags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./pipeline.py &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;flags.yaml &lt;span class="nt"&gt;--board&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ENG &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; run1.html
./pipeline.py &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;flags.yaml &lt;span class="nt"&gt;--board&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ENG &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; run2.html
&lt;span class="nb"&gt;sha256sum &lt;/span&gt;run1.html run2.html
&lt;span class="c"&gt;# should print identical hashes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the two hashes differ, something in the pipeline is non-deterministic and needs to be found. Most non-determinism comes from incidental sources: dict iteration order in older Python versions, timestamps in the output, random sampling in pagination. Each one has a fix. The constraint forces the fix rather than allowing the non-determinism to hide.&lt;/p&gt;

&lt;p&gt;Determinism is what makes the output a compliance-grade artifact. A report that is not reproducible is a report a stakeholder cannot trust. A report that is reproducible is one that can be regenerated from source at any future point, which is the actual definition of "reviewable."&lt;/p&gt;

&lt;h2&gt;
  
  
  How this connects to Claude-Code skills in general
&lt;/h2&gt;

&lt;p&gt;The skill pattern above is specific to the QA-automation surface, but the mechanics generalize. A skill in Claude Code is a named, addressable contract the agent loader selects from. The best skill files are the ones a reviewer can read in under a minute and the agent can instantiate without ambiguity.&lt;/p&gt;

&lt;p&gt;Three properties decide whether a skill is good or not:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Invocation-tight.&lt;/strong&gt; The skill's description tells the loader precisely when to fire and when not to. Loose descriptions produce the wrong skill firing at the wrong moment, which is the most common skill-related bug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Implementation-free.&lt;/strong&gt; The skill contract does not name Python modules, specific libraries, or internal file paths. Those are details the implementation owns. A skill that references implementation specifics is one that cannot be reimplemented without rewriting the contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Failure-mode-explicit.&lt;/strong&gt; The contract names the failure modes the skill surfaces, separately from the success path. A reviewer who does not see failure modes in the contract knows the skill is incomplete, regardless of how clean the success path reads.&lt;/p&gt;

&lt;p&gt;Skills that satisfy all three scale across agents, across implementations, across time. Skills that satisfy fewer decay quickly into code-as-skill, at which point the review bottleneck reappears and the markdown layer stops earning its presence.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you do with this pattern
&lt;/h2&gt;

&lt;p&gt;If you are building on Claude Code at any scale, the skills directory is the highest-payoff surface. Two moves that compound:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Audit one existing skill&lt;/strong&gt; for the three properties above. If any property fails, rewrite the contract before adding the next skill. One rewritten contract is worth three new skills with inherited drift.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate config from behavior.&lt;/strong&gt; Move every toggle, every threshold, every environment-specific value out of the code and into a flag file. The next regression hunt runs in five minutes instead of fifty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both moves compound across the agent ecosystem you build on top. The QA-automation repo is one concrete shape of the pattern; the shape generalizes to any Claude Code surface where review authority is the scarce resource.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>devops</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Bransford transfer: the loop-completion test for concepts AND for Claude outputs</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 02:43:49 +0000</pubDate>
      <link>https://dev.to/amanbhandari/bransford-transfer-the-loop-completion-test-for-concepts-and-for-claude-outputs-1p28</link>
      <guid>https://dev.to/amanbhandari/bransford-transfer-the-loop-completion-test-for-concepts-and-for-claude-outputs-1p28</guid>
      <description>&lt;p&gt;&lt;em&gt;"I understood it when Claude explained it."&lt;/em&gt; This is the most dangerous sentence in learning, because it reports recognition (I followed an explanation that was happening right in front of me) and quietly gets filed as comprehension (I now possess the concept and can apply it). The two states are wildly different. The problem is that the first state feels exactly like the second one, right up until the moment you have to use the concept on a new problem and discover that you cannot.&lt;/p&gt;

&lt;p&gt;Bransford and Schwartz's 1999 paper &lt;em&gt;"Rethinking Transfer: A Simple Proposal with Multiple Implications"&lt;/em&gt; is the clearest diagnostic for this failure. Their test: pose a novel problem in a new surface form. If the learner solves it, the concept transferred. If the learner can only reproduce the original explanation, the concept collapsed into memorization.&lt;/p&gt;

&lt;p&gt;Whitehead (1929) called this collapse "inert knowledge" — knowledge the student can recite but cannot apply. Bransford's test is what detects it. I run the test as Node 5 of the concentric-loop discipline in &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt;, and I run the same test against agent output before trusting any Claude-generated artifact.&lt;/p&gt;

&lt;h2&gt;
  
  
  The test for concepts
&lt;/h2&gt;

&lt;p&gt;After a concept has been explained and the descent through its layers has landed, wait — at minimum, a day; ideally, a week. Then pose a problem that satisfies three conditions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;New surface form.&lt;/strong&gt; Different domain, different vocabulary, different concrete example. Not the same problem with the numbers swapped. A genuinely new clothing for the same mechanism.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No scrollback.&lt;/strong&gt; The original explanation is not available. No notes, no conversation history, no re-reading the blog post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different framing.&lt;/strong&gt; If the concept was introduced via one practitioner's lens (Karpathy's build-from-scratch, say), the transfer problem is framed via a different lens (Huyen's latency-tier I/O contract, say).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Solve it. If you can, the concept transferred. If you cannot — or if you can only after hints — the learning did not close.&lt;/p&gt;

&lt;p&gt;Most "I learned X last week" claims fail this test. That is the discovery. The claim was made in good faith at the moment of the original explanation, and it felt true because recognition felt like comprehension. The transfer test separates the two states by requiring the concept to do work outside the environment in which it was introduced.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three failure signals
&lt;/h2&gt;

&lt;p&gt;When the transfer test fails, it fails in one of three specific shapes. Naming the shape matters because each one points to a different remediation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signal 1 — Can only reproduce the original analogy.&lt;/strong&gt; The student's attempt to solve the new problem leans on the original metaphor or example and does not generalize. &lt;em&gt;"Well, in the 3Blue1Brown video, they said neurons are like voters..."&lt;/em&gt; The analogy has become the concept. This is Gentner's analogy-leakage failure: the student is reasoning about the vehicle instead of the mechanism.&lt;/p&gt;

&lt;p&gt;Remediation: descend again, with a different analogy. Not the same analogy rephrased — a genuinely different starting point that forces the mechanism to be re-grounded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signal 2 — Solves the old problem, not the transfer.&lt;/strong&gt; The student can correctly derive backprop on the exact MLP from the lecture, but cannot adapt to a transformer head. The knowledge is real but local. It is not yet a transferable skill; it is a memorized procedure.&lt;/p&gt;

&lt;p&gt;Remediation: the multi-instance requirement from the whiteboard test — run the same concept across three genuinely different architectures or problems, forcing generalization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Signal 3 — Solves the transfer only after a hint.&lt;/strong&gt; The student gets there eventually, but only after the interrogator scaffolds the first step. The concept is semi-transferred — partly held, partly dependent on external prompting.&lt;/p&gt;

&lt;p&gt;Remediation: keep the card in active rotation. Re-test at a longer interval with no hint permitted. If the unaided solution lands, move the card to the less-frequent review pool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same test applied to agent output
&lt;/h2&gt;

&lt;p&gt;This is where the pattern extends beyond learning. Bransford transfer also works as an evaluation for any agent pipeline that purports to generalize.&lt;/p&gt;

&lt;p&gt;The failure mode: an agent that performs well on the exact distribution it was tested against — the exact prompt shape, the exact input schema, the exact phrasing of the instruction — and collapses when any of those shifts. Superficially this looks like an agent that "works." In practice, it is an agent that memorized its evaluation.&lt;/p&gt;

&lt;p&gt;Apply Bransford's test: swap the system prompt, swap the input schema, swap the practitioner's framing of the instruction. Check whether the agent's correctness transfers. If it does, the agent genuinely solves the class of problem. If only the exact form works, the agent memorized the harness.&lt;/p&gt;

&lt;p&gt;Hamel Husain's manual-trace-labeling discipline is the Bransford test run at scale on agent output. Label 20-100 real traces across different surface forms. Extract the cases that fail. Those cases are the non-transferring ones — the ones the agent "knew" in the original framing and could not hold in the new one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this sits at the close of the concentric loop
&lt;/h2&gt;

&lt;p&gt;The concentric loop — analogy → code → system → math → analogy — is only complete when the return lands. The return is not a summary. It is the test: can the student now apply the enriched mental model to the original analogy in a way they could not before?&lt;/p&gt;

&lt;p&gt;Bransford transfer is the formal version of that return. If the transfer holds, the loop closed. If the transfer fails, the descent was not deep enough — the student followed the explanation but never integrated it into a form that generalizes.&lt;/p&gt;

&lt;p&gt;The loop is not a presentation artifact. It is an instrument with a measurable completion criterion. Without the criterion, every teaching session feels successful at the moment it ends, which is how inert knowledge accumulates.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes this practically catchable
&lt;/h2&gt;

&lt;p&gt;The test is cheap to run. The expensive part is the discipline of running it after the concept has been "learned," rather than calling the learning done and moving on. Every new concept goes onto a spaced-review card with a Bransford test associated with it: a specific novel surface form the student has not yet seen.&lt;/p&gt;

&lt;p&gt;The card surfaces on a schedule. The student runs the test. The outcome (pass, fail, fail-with-hint) gets logged. Over months, the log becomes a map of which concepts have genuinely transferred and which remain fragile — which is the input to every decision about what to study next.&lt;/p&gt;

&lt;p&gt;Without the card, the test does not run. Without the test, the transfer is assumed rather than verified. Assumption is the cache layer between recognition and application; the cache gets cleared by novelty, and the reader discovers it only when the novelty arrives.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sentence that replaces "I understood it"
&lt;/h2&gt;

&lt;p&gt;After every concept, the honest sentence is not &lt;em&gt;"I understood it."&lt;/em&gt; It is &lt;em&gt;"I understood the explanation. The transfer test has not been run yet. I will know whether the concept transferred when the test fires on a novel problem in a different surface form."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is longer and less satisfying. It is also true. The shorter version is what produces the six-months-later surprise of realizing you do not actually know the thing you thought you learned.&lt;/p&gt;

&lt;p&gt;Replace one "I understood it" claim with its Bransford-pending version this week. Schedule the test. The discipline compounds across every concept you acquire afterward.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>ai</category>
      <category>claudecode</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The whiteboard test: a FAANG-level gate applied to my own learning</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 02:43:38 +0000</pubDate>
      <link>https://dev.to/amanbhandari/the-whiteboard-test-a-faang-level-gate-applied-to-my-own-learning-30ak</link>
      <guid>https://dev.to/amanbhandari/the-whiteboard-test-a-faang-level-gate-applied-to-my-own-learning-30ak</guid>
      <description>&lt;p&gt;Reciting a YouTube explanation is not derivation. Watching 3Blue1Brown on backpropagation and being able to parrot the explanation back is a recognition skill. It looks like understanding if nobody probes. The moment someone changes the activation function or asks why a minus sign is on a particular term, the recognition collapses and reveals that no derivation ever happened — only pattern-matching against a specific video.&lt;/p&gt;

&lt;p&gt;The whiteboard test is what the top tier of applied ML/AI interviews uses to tell the difference. It is also what I run on myself for every math concept in the curriculum. Six rules. No exceptions. A concept that cannot pass the whiteboard test has not been understood, regardless of how confident the student feels.&lt;/p&gt;

&lt;p&gt;The rule is codified in the &lt;code&gt;math-foundation.md&lt;/code&gt; file of my framework: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt;, under "Hard Verification Protocol (FAANG-level gate)."&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 1 — Blank-sheet start
&lt;/h2&gt;

&lt;p&gt;The test begins with the student erasing all notes. Phone face-down. No videos playing. A camera or shared screen shows an empty page. No reference material within sight.&lt;/p&gt;

&lt;p&gt;The reason: any recall that happens in the presence of notes is indistinguishable from reading the notes out loud. The only derivation that counts is the one produced from memory, under observation, against a problem the student did not set up.&lt;/p&gt;

&lt;p&gt;Without this rule, "I understood the math" means "I once followed someone else's math and it seemed right at the time." Those are different statements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 2 — Randomized variation
&lt;/h2&gt;

&lt;p&gt;The interrogator introduces at least one variation the student has not seen before. Different activation (ReLU instead of sigmoid). Different dimensions (a batch of 3 instead of 1). Different loss (hinge instead of cross-entropy). Different optimizer term (Adam's second moment).&lt;/p&gt;

&lt;p&gt;The student adapts the derivation on the spot.&lt;/p&gt;

&lt;p&gt;This is the rule that separates recognition from understanding. A student who has memorized "the derivative of sigmoid is sigmoid(x) * (1 - sigmoid(x))" can recite that line. A student who understands the derivation can re-derive it for ReLU, or for tanh, or for GeLU — because the underlying pattern (chain rule on the activation) is what they have internalized, not the specific formula.&lt;/p&gt;

&lt;p&gt;Variation is not a gotcha. It is the test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 3 — Three "why" checkpoints
&lt;/h2&gt;

&lt;p&gt;At three random points during the derivation, the interrogator interrupts with a "why" question the student cannot have memorized:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"Why is there a minus sign on this term?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"What happens to this expression if the learning rate doubles?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"Why do we use the transpose here and not the original matrix?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"What would this reduce to if you removed the bias term?"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"What does this term look like in the limit as the batch size goes to infinity?"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the student cannot answer from first principles, the derivation fails and the exercise is not complete.&lt;/p&gt;

&lt;p&gt;The reason these questions matter: they cannot be memorized because the interrogator selects them on the fly from an adversarial pool. A student who has derived the math from primitives can answer any of them in under 30 seconds. A student who has memorized the math can answer none of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 4 — Reverse-direction test
&lt;/h2&gt;

&lt;p&gt;After the forward derivation lands, the interrogator asks the student to explain a specific line in the middle: &lt;em&gt;"Why does this term exist? What would the model look like without it?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the reverse of the usual teaching direction. Usually the student builds up from assumptions to conclusions. The reverse-direction test picks a point in the middle and asks the student to defend it — to explain what the term contributes, what removing it would change, what the alternate formulation would look like.&lt;/p&gt;

&lt;p&gt;A memorized derivation proceeds in one direction; it cannot defend itself at an arbitrary point. A derived derivation can, because every line is a consequence the student can justify from the surrounding context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 5 — Numerical grounding
&lt;/h2&gt;

&lt;p&gt;The student plugs in actual small numbers — an input like &lt;code&gt;[0.5, -0.3]&lt;/code&gt;, weights like &lt;code&gt;[[0.1, 0.2], [-0.1, 0.3]]&lt;/code&gt;, a target of &lt;code&gt;1&lt;/code&gt; — and computes the entire forward and backward pass by hand. The result must match the analytical derivation.&lt;/p&gt;

&lt;p&gt;This rule catches a specific failure mode: a derivation that looks correct symbolically but breaks when actually executed. Off-by-one errors, missing transpositions, sign flips, dimension mismatches — all of them hide in the symbols and only surface under numerical substitution.&lt;/p&gt;

&lt;p&gt;The numerical grounding is also the test case that becomes a unit test in the implementation. A student who has ground the math by hand can write a known-answer test that will catch the first implementation bug. A student who has not is guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rule 6 — Repeat with variation
&lt;/h2&gt;

&lt;p&gt;For core concepts (backprop, attention, gradient descent, the math of a specific loss function), the verification happens at least three times across the curriculum, with different architectures or problems each time.&lt;/p&gt;

&lt;p&gt;Once-pass is not mastery. A student who passed the gate on a single-layer MLP has demonstrated local understanding of that specific case. Mastery is demonstrated when the same derivation fires on a two-layer ReLU network, then on a transformer head, then on a convolutional layer — each time without re-learning the underlying mechanism.&lt;/p&gt;

&lt;p&gt;This is the multi-shot version of the Bransford transfer test applied to mathematical derivation. A concept has transferred when it fires on a new instance without scaffolding. A concept has not transferred if every new instance requires going back to the original explanation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this resists Claude-Operator drift specifically
&lt;/h2&gt;

&lt;p&gt;The vibe-coding failure mode of operator work is accepting agent output without reading it. The learning equivalent is accepting an explanation without deriving it. Both produce the same symptom: apparent competence that collapses under adversarial probing.&lt;/p&gt;

&lt;p&gt;The whiteboard test is specifically designed to resist this drift. No notes means no scrollback to the previous Claude conversation. Randomized variation means no memorization of a specific output. "Why" checkpoints mean no pattern-match against a standard explanation. Numerical grounding means no hand-waving the bits of the derivation the student did not actually check.&lt;/p&gt;

&lt;p&gt;A concept that passes the whiteboard test has been derived by the student, in their own hand, under conditions that would have exposed any gap. That is the condition for calling the concept understood.&lt;/p&gt;

&lt;h2&gt;
  
  
  What failure looks like, and what to do
&lt;/h2&gt;

&lt;p&gt;Failure on any rule is data, not judgment. The test is not pass/fail in the career-consequence sense — it is pass/fail in the "did the descent actually close or not" sense. A failed whiteboard test says: the learning did not land yet. Go back to the source — textbook chapter, paper, Karpathy lecture, the specific section of 3Blue1Brown — study it, and rerun the test within 48 hours.&lt;/p&gt;

&lt;p&gt;What failure does NOT permit: the interrogator giving the student the answer. A failed derivation that gets filled in by the grader has not become a passing derivation; it has become a piece of dictated material that the student will fail on again next week.&lt;/p&gt;

&lt;p&gt;Repeated failure on the same concept is its own signal. If the student has failed three times on the derivation of gradient descent, the underlying material was not absorbed — and the fix is to go back further in the prerequisite chain, not to re-read the same section harder.&lt;/p&gt;

&lt;h2&gt;
  
  
  The log that matters
&lt;/h2&gt;

&lt;p&gt;Every whiteboard verification gets logged. Date, concept, whether the student passed on first attempt or needed retries, which variation was posed, which "why" questions fired. Over months, the log becomes a map of which concepts are load-bearing (passed consistently) versus fragile (required multiple attempts).&lt;/p&gt;

&lt;p&gt;Fragile concepts get re-verified more often. Load-bearing concepts get spaced out. The log is what makes the next retest principled rather than random.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gate in one sentence
&lt;/h2&gt;

&lt;p&gt;If you cannot derive the concept on a blank sheet, adapting to a variation you did not prepare for, defending any line the interrogator points at, and grounding it numerically against a set of small inputs — then you do not understand the concept, regardless of how clearly the YouTube explanation landed.&lt;/p&gt;

&lt;p&gt;That is the gate. Apply it to yourself. The concepts that pass become the ones you can still apply when the frontier shifts and the abstractions you relied on start leaking.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>ai</category>
      <category>interview</category>
      <category>math</category>
    </item>
    <item>
      <title>Every quality gate I ship code past, I ship my learning past</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 02:36:52 +0000</pubDate>
      <link>https://dev.to/amanbhandari/every-quality-gate-i-ship-code-past-i-ship-my-learning-past-2231</link>
      <guid>https://dev.to/amanbhandari/every-quality-gate-i-ship-code-past-i-ship-my-learning-past-2231</guid>
      <description>&lt;p&gt;Shallow learning is the bug class that shows up as &lt;em&gt;"I knew this last week"&lt;/em&gt; six months later, when a new model makes the abstraction leak and you cannot explain what happened. The fix is the same as for production code: gates at every stage, fail-loud at each one, no bypass.&lt;/p&gt;

&lt;p&gt;I run a six-gate pipeline for concept acquisition that is structurally identical to the six-stage QA gate pipeline I run for software deploys. Same shape, different artifact. Same discipline, different failure mode being prevented. The payoff is a concept you can still apply when the original explanation has faded and the new problem does not look like the old one.&lt;/p&gt;

&lt;p&gt;The framework surfaces: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; for the rule files, &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt; for the production-QA-shaped pattern that inspired the pipeline mapping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gate 1 — Requirements (is this concept worth learning right now?)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;QA analogue.&lt;/strong&gt; The requirements review. Is this feature worth building, and does it map to a real user outcome?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning version.&lt;/strong&gt; Eugene Yan's four questions applied to concepts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is the problem this concept is supposed to solve? (Described without jargon.)&lt;/li&gt;
&lt;li&gt;Who actually hits this problem — a real role, not a hypothetical.&lt;/li&gt;
&lt;li&gt;Would a non-technical workaround solve 70% of it? (If yes, that is the first thing to ship.)&lt;/li&gt;
&lt;li&gt;What does competence look like, measurably?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any of the four fails, the concept is either not ready to learn yet (you are reaching for technology without a problem) or not worth learning (the problem is hypothetical).&lt;/p&gt;

&lt;p&gt;Most "I want to learn X" impulses do not survive this gate. The ones that do become durable study — because they started with a problem, not a tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gate 2 — Design (can I describe every piece in my own words, before coding?)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;QA analogue.&lt;/strong&gt; The design review. Reading the architecture doc. Naming which services are touched.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning version.&lt;/strong&gt; The Socratic Q&amp;amp;A phase of my session design. I cannot write the first line of code until I can describe every piece of what I am about to write, in my own words, without prompting.&lt;/p&gt;

&lt;p&gt;The concentric loop opens here: analogy in lived experience, descent through code, through system intermediaries, through hardware/math, return to the analogy with enriched meaning. If the return does not land, the descent was not deep enough and the concept has not been designed into my mental model — only dropped onto it.&lt;/p&gt;

&lt;p&gt;The test for passing Gate 2: pose a variation of the problem to myself. Can I describe the solution shape before writing it? If the answer is "let me try it and see," the design is missing, which means the implementation will be guesswork dressed up as code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gate 3 — Implementation (test before code, always)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;QA analogue.&lt;/strong&gt; The TDD contract applied to production code. RED first. Then minimum GREEN. Then REFACTOR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning version.&lt;/strong&gt; Exact same contract. Every exercise file has a test file created first. The tests must fail. Only then does the implementation start. Then refactor with tests green.&lt;/p&gt;

&lt;p&gt;The reason this works for learning — not just for production — is that a failing test forces the concept into a testable shape. Vague understanding cannot write a failing test; it produces a vague test that passes on anything. If the test is sharp, the concept behind it is sharp.&lt;/p&gt;

&lt;p&gt;For math concepts, the test shape changes but the contract does not: a known-answer test (plug in small numbers, match the analytical result), a convergence test (loss decreases on toy data), a gradient-check test (numerical gradient matches analytical gradient). Same discipline, different domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gate 4 — Integration (can I build the 100-line version with my tools in hand?)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;QA analogue.&lt;/strong&gt; Integration testing. The pre-merge gate that runs the full test pyramid and catches interaction bugs unit tests miss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning version.&lt;/strong&gt; Karpathy's build-from-scratch discipline. Before trusting the 40,000-line library version of a concept, build the 100-line version by hand. micrograd for autograd. nanoGPT for training loops. Your own 40-line RAG pipeline before touching LangChain.&lt;/p&gt;

&lt;p&gt;The operational constraint: every time I build, there must be a tool in my hand. &lt;code&gt;dis&lt;/code&gt; for Python bytecode. &lt;code&gt;sys.getsizeof&lt;/code&gt; for memory layout. &lt;code&gt;time.perf_counter&lt;/code&gt; for timing. &lt;code&gt;mypy --strict&lt;/code&gt; for type propagation. &lt;code&gt;strace&lt;/code&gt; when the abstraction leaks to the OS. The tool forces the mechanism into memory. Without it, the build becomes a pattern-match — which is the exact failure mode I named in an earlier post (the cold-grill diagnostic).&lt;/p&gt;

&lt;p&gt;A concept that survives this gate is one whose mechanism you have observed with instruments, not one you inferred from the documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gate 5 — Acceptance (whiteboard, blank sheet, adapt to a variation)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;QA analogue.&lt;/strong&gt; The pre-deploy gate. Staging canary against a realistic load profile. Not the happy path — the one that breaks if the release is wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning version.&lt;/strong&gt; The whiteboard test. Cold grill. Blank sheet, no notes, camera on the empty page, and I have to derive the concept from first principles while somebody (the Partner in my setup) randomizes at least one variation I have not seen: different activation function, different loss, different input shape. Three "why" checkpoints interrupt the derivation — questions I cannot have memorized the answers to.&lt;/p&gt;

&lt;p&gt;This is a FAANG-level verification standard. I run it on myself. A concept that passes this gate has actually been understood — not recognized from a YouTube explanation, not parroted from a textbook, but built from primitives under adversarial conditions.&lt;/p&gt;

&lt;p&gt;The failure mode without this gate: "I understood it when Claude explained it" becomes "I can recite what Claude said" becomes "I cannot actually use this on a new problem." Every step of that drift is invisible until the new problem arrives and the concept does not fire.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gate 6 — Post-deploy (does the concept still work 4 weeks later on a novel problem?)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;QA analogue.&lt;/strong&gt; The post-deploy observability gate. Alarms, error-rate deltas, user-visible regression detection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning version.&lt;/strong&gt; The Bransford transfer test (Bransford and Schwartz, "Rethinking Transfer," 1999). Pose a novel problem in a new surface form, weeks later. Different domain, different vocabulary, different practitioner's framing. If I solve it, the concept compounded. If I can only reproduce the original analogy, the concept collapsed into memorization and the learning loop did not actually close.&lt;/p&gt;

&lt;p&gt;Paired with spaced review. Cards for load-bearing concepts get re-surfaced on a schedule that lengthens with each successful recall. The review is not passive re-reading — it is re-derivation against a new variation each time. A concept that fails Gate 6 is a concept that needs another descent with a different analogy, not "study more of the same."&lt;/p&gt;

&lt;h2&gt;
  
  
  The bypass failure mode
&lt;/h2&gt;

&lt;p&gt;Every gate has a "look up the answer and move on" bypass. This is exactly Karpathy's reframing of vibe coding: accept the plausible-looking output, ship the exercise, call it progress, and quietly skip the mechanism. Applied to learning, the bypass produces the reflex I named in an earlier post: &lt;em&gt;"If I just start doing exercises now, I will look up the solution from here and there, complete the exercise, move to next."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The fix is the same as for production code: make the bypass expensive by making every gate fail loud. A test that does not exist cannot pass. A whiteboard derivation that does not happen cannot be marked green. A transfer test that is not run leaves the concept in a "not verified" state.&lt;/p&gt;

&lt;p&gt;Bypass-resistance is the whole point of the gate. A gate you can bypass is a gate that will eventually be bypassed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this gives me
&lt;/h2&gt;

&lt;p&gt;Two compounding outcomes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Retention.&lt;/strong&gt; Concepts that survive six gates do not fade into "I knew this last week" six months later. They are still available when the new problem arrives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transferability.&lt;/strong&gt; The fifth gate's variation requirement and the sixth gate's novel surface form force transfer. A concept that transfers is the opposite of inert knowledge — it applies to problems I have not yet met.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both outcomes only come from discipline, not from talent or speed. A person can skip the gates and finish the exercise faster. That person has produced a file, not a concept.&lt;/p&gt;

&lt;p&gt;The QA pipeline and the learning pipeline are the same discipline applied to different surfaces. Same operator, same three hats, same refusal to call anything done that has not passed its specific gate.&lt;/p&gt;

&lt;p&gt;Pick one gate your current learning flow does not have. Add it. Not all six at once — one at a time, sustained for a month. The next concept that lands on your plate will arrive differently.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>productivity</category>
      <category>career</category>
      <category>ai</category>
    </item>
    <item>
      <title>Pipeline freedom: why senior QAs run deploys, tear down environments, and own the release</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 02:34:00 +0000</pubDate>
      <link>https://dev.to/amanbhandari/pipeline-freedom-why-senior-qas-run-deploys-tear-down-environments-and-own-the-release-lk4</link>
      <guid>https://dev.to/amanbhandari/pipeline-freedom-why-senior-qas-run-deploys-tear-down-environments-and-own-the-release-lk4</guid>
      <description>&lt;p&gt;A QA team that cannot create or destroy a test environment is a QA team that cannot actually verify the deploy pipeline. The button a QA clicks to "run the staging tests" is gated behind a ticket to a DevOps team; the tests assume the staging environment is in a state QA did not set up; the deploy the tests are supposed to validate is triggered by somebody else; the rollback is owned by somebody else; the alarm that would catch the regression post-deploy is tuned by somebody else.&lt;/p&gt;

&lt;p&gt;Under those constraints, "QA validated the release" means "QA ran some tests against some environment at some point." That is not validation. It is a status update that happens to include the word "QA."&lt;/p&gt;

&lt;p&gt;Pipeline freedom — the authority to create and destroy environments, trigger and roll back deploys, run load against staging, and author the alarms the team is measured against — is what senior QA work requires to mean what it claims to mean. It is not a privilege. It is what the role is accountable for.&lt;/p&gt;

&lt;p&gt;Four capabilities below, each with the "blocked" version and the senior version. The operator pattern underneath (same as in &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt;) is: the work is reproducible when the person doing it has the authority to set up the reproduction.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Create and destroy ephemeral environments
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Blocked version.&lt;/strong&gt; QA files a ticket to DevOps: &lt;em&gt;"please refresh staging against the &lt;code&gt;feature/X&lt;/code&gt; branch."&lt;/em&gt; Ticket sits for a day. When staging is ready, the code has moved. QA tests against a stale snapshot. Findings are questioned on the grounds that staging was "not really up to date."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Senior version.&lt;/strong&gt; QA has the credentials, the Terraform (or Pulumi, or CDK) access, and the workflow authority to spin up an ephemeral environment against any branch on demand. Runs the test suite against an environment QA just built, against the exact branch QA wants to validate, in the exact state QA wants to validate it against. Tears it down when done.&lt;/p&gt;

&lt;p&gt;The infrastructure cost of an ephemeral environment is measured in cents per hour. The organizational cost of not having one is measured in releases that ship untested. The math is not close.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Trigger and roll back deploys
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Blocked version.&lt;/strong&gt; QA signs off on release readiness. Developer pushes the deploy button. If something goes wrong post-deploy, QA files a ticket. Developer triggers the rollback. By the time the rollback finishes, 10 minutes of user impact have accumulated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Senior version.&lt;/strong&gt; QA has deploy authority for the environments QA is accountable for — at minimum staging, ideally a canary-production cohort. QA triggers the deploy, watches the canary for the first five minutes against a pre-defined set of metrics, and triggers the rollback themselves if those metrics deviate. No ticket-round-trip.&lt;/p&gt;

&lt;p&gt;The deploy button is a quality gate, not an engineering privilege. The person accountable for quality should be the person with hands on the gate. A QA who has to ask somebody else to push the button is a QA being held responsible for something they cannot directly act on.&lt;/p&gt;

&lt;p&gt;The most common objection — &lt;em&gt;"QA should not have production access"&lt;/em&gt; — misunderstands the pattern. QA does not need production &lt;em&gt;write&lt;/em&gt; access to code or data. QA needs deploy-trigger and rollback authority, which are different capabilities. The deploy pipeline is the control surface; write access is what the pipeline applies.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Run load against staging
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Blocked version.&lt;/strong&gt; Load tests are a separate team's domain, run quarterly against a test environment that is never sized to match production. The load "passed" in Q2 does not necessarily hold in Q3 because the schema changed, the traffic pattern shifted, or a new dependency was added.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Senior version.&lt;/strong&gt; QA owns the load-test harness. Can run realistic traffic shapes (including the one that matches the first hour of production after a typical deploy) against staging on demand. Checks p99 latency, connection pool headroom, cache hit ratio, and the specific error shapes the system emits under stress.&lt;/p&gt;

&lt;p&gt;The load-test run is part of the pre-deploy gate for anything that touches a hot path. QA does not ask for permission to run it; QA runs it as part of the release checklist they themselves own.&lt;/p&gt;

&lt;p&gt;This is where QA overlaps with SRE in most orgs. The split that works in practice: SRE owns the platform's capacity model and baseline scaling; QA owns the release-specific load verification. SRE cares about "can the platform handle traffic in general"; QA cares about "does this specific release hold up under the specific load it will meet."&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Write and tune alarms + SLOs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Blocked version.&lt;/strong&gt; Alarms are written by SRE. QA responds to alarm fatigue by filing tickets. The alarm config lives in a repo QA cannot modify. The SLO document was written before QA joined and has not been revisited.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Senior version.&lt;/strong&gt; QA owns the user-visible alarm surface. SLOs live in a file under source control; QA has commit access. Every real incident produces an alarm-quality postmortem, and QA runs the postmortem: did the alarm fire? If not, write one. If the threshold was wrong, tune it. If an alarm has been firing without being actionable for two weeks, delete it.&lt;/p&gt;

&lt;p&gt;The SLO is the QA team's quality contract with the rest of the business. "99.9% of checkouts succeed within 800ms at p95" is QA's claim. If SLOs are not owned by QA, the quality claim belongs to whoever does own them — and that somebody is usually SRE, whose incentives (platform reliability) only partially overlap with QA's incentives (user-visible behavior correctness).&lt;/p&gt;

&lt;h2&gt;
  
  
  The cultural objection, addressed
&lt;/h2&gt;

&lt;p&gt;The objection I hear most often — &lt;em&gt;"giving QA this much authority is dangerous"&lt;/em&gt; — is usually a rephrasing of &lt;em&gt;"this QA does not have the fundamentals to wield it."&lt;/em&gt; The answer is not to withhold the authority. The answer is to require the fundamentals, hire to the fundamentals, and grant the authority to people who have them.&lt;/p&gt;

&lt;p&gt;The specific fundamentals are the same six I wrote about in the previous post: HTTP/TCP, database query plans, async vs sync, memory/GC, containers, distributed tracing. A QA without those cannot reason about what a deploy is doing, what a load test means, or why an alarm is firing. Pipeline freedom without fundamentals is accidents waiting to happen. Pipeline freedom with fundamentals is how the role earns its weight.&lt;/p&gt;

&lt;p&gt;The second form of the objection — &lt;em&gt;"we cannot afford to train QAs to this level"&lt;/em&gt; — is a budget question masquerading as a capability question. A senior QA with pipeline freedom catches releases before they ship bad, which pays back the training cost faster than any interview cycle. The org that does not pay for this role pays for it anyway, in outages, in rework, in customer churn. The invoice just arrives through a different cost center.&lt;/p&gt;

&lt;h2&gt;
  
  
  The operator pattern
&lt;/h2&gt;

&lt;p&gt;The same "spec first, eval on output, foundational fluency" discipline I run on the Claude-Code operator surface is what makes a QA senior instead of blocked. Spec-first means the release criteria are written before the release is built. Eval on output means the alarm-quality postmortem runs after every incident, not before every audit. Foundational fluency means the QA who pushes the deploy button can explain what the deploy does at the layer below the button.&lt;/p&gt;

&lt;p&gt;The role is structurally the same as the architect-orchestrator-reviewer role in agentic engineering. Different artifact — a release, not a PR. Same three hats, rotated consciously, backed by the authority to close each loop without asking.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for QA hiring
&lt;/h2&gt;

&lt;p&gt;The market for senior QA is smaller than it should be because most orgs hire the button-clicker profile and then discover they needed the systems profile. The systems profile is not more expensive; it is selected for differently.&lt;/p&gt;

&lt;p&gt;If you are hiring: interview for the six fundamentals and the pipeline-authority comfort. If you are a QA looking to move up: build demonstrable evidence of pipeline work (a Terraform config you wrote, an alarm suite you own in a public repo, a load-test harness, a deploy you triggered) and publish it alongside the usual test-framework experience.&lt;/p&gt;

&lt;p&gt;The ceiling on the clicker version is flat. The ceiling on the senior-with-pipeline-freedom version is as high as the senior engineering roles that own cross-cutting concerns — which is where this role always belonged, before the market decided otherwise.&lt;/p&gt;

&lt;p&gt;Pick one capability from the four. Build the case for owning it on your current team. The authority follows the demonstrated competence, not the reverse.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>qa</category>
      <category>devops</category>
      <category>cicd</category>
      <category>career</category>
    </item>
    <item>
      <title>CloudWatch literacy: the QA superpower that routes bugs without triage theater</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 02:30:49 +0000</pubDate>
      <link>https://dev.to/amanbhandari/cloudwatch-literacy-the-qa-superpower-that-routes-bugs-without-triage-theater-4hh2</link>
      <guid>https://dev.to/amanbhandari/cloudwatch-literacy-the-qa-superpower-that-routes-bugs-without-triage-theater-4hh2</guid>
      <description>&lt;p&gt;Triage theater is the 40-minute meeting that starts with QA saying &lt;em&gt;"users report the upload is broken,"&lt;/em&gt; continues with devs saying &lt;em&gt;"we do not see anything in the logs,"&lt;/em&gt; goes around the room for half an hour, and ends without anybody opening CloudWatch. A QA who opens CloudWatch first closes the same loop in five minutes — and walks out of the meeting with the ticket already routed to the right developer.&lt;/p&gt;

&lt;p&gt;CloudWatch literacy is not a certification or a platform thing. It is six log-reading patterns that change what a QA can see before triage starts. The same patterns apply on Datadog, Splunk, Grafana Loki, Elastic, or any log-aggregation stack — CloudWatch is just the specific tool I run against in &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;, where the pipeline emits structured reports against sprint and production-health data.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Correlation IDs on every request
&lt;/h2&gt;

&lt;p&gt;The first pattern is the one that makes the other five possible.&lt;/p&gt;

&lt;p&gt;Every request that enters the system gets a correlation ID (sometimes called request ID, trace ID, or transaction ID) generated at the edge — the load balancer, the API gateway, or the first service to receive it. The ID propagates through every downstream call. Every log line emitted by any service handling that request includes the ID.&lt;/p&gt;

&lt;p&gt;The reason this matters: a user-facing bug report ("my upload at 14:32 failed") is useless without a correlation ID. The error is somewhere in the logs, but "somewhere" in a service that produces 10 million log lines a day is not findable. With a correlation ID on the failed request — surfaced to the user in an error dialog, a HTTP response header, or a support ticket — the QA queries the ID directly and pulls every log line for that request across every service.&lt;/p&gt;

&lt;p&gt;The QA action: if the correlation ID is not being surfaced to users at the point of failure, file that as a bug. A system that does not emit a correlation ID at its failure surface is a system you cannot debug.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Structured logging + log-insights queries
&lt;/h2&gt;

&lt;p&gt;Plain-text logs are searchable. Structured logs (JSON, one line per event) are queryable. The difference is the difference between "grep for the user's email" and "show me the 99th-percentile latency of the &lt;code&gt;checkout.submit&lt;/code&gt; event broken down by payment method over the last hour."&lt;/p&gt;

&lt;p&gt;CloudWatch Insights, Datadog's query language, Splunk SPL, Loki's LogQL — all of them work against structured logs to answer questions, not just retrieve lines. The QA who writes a query like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;correlation_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration_ms&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"checkout.submit"&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;sort&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="k"&gt;desc&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;limit&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...produces an answer in ten seconds that would have taken twenty minutes of scrolling through raw logs to construct manually.&lt;/p&gt;

&lt;p&gt;The QA action: ask the dev team to emit structured logs at key events, learn the query language for the specific stack, and use it. "Just grepping" in a structured-logging environment is leaving the best part of the tool unused.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Deployment-edge logs
&lt;/h2&gt;

&lt;p&gt;Half of production regressions land within an hour of a deploy. The question the QA should be asking at the start of any triage is: &lt;em&gt;"What changed most recently, and when?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Deployment-edge logs are the log records emitted around the boundary of a release: the deploy itself (version hash, timestamp, rollout percentage), and the first 30 minutes of traffic against the new version versus the last 30 minutes of the old one. Error rates, latency percentiles, log-level distributions. A delta visible at the boundary is almost always the cause.&lt;/p&gt;

&lt;p&gt;A QA who checks the deploy log first — before doing anything else — catches the "it started at 14:02, the deploy was at 14:01" pattern instantly. A QA who does not ends up re-investigating a bug that was already diagnosed at deploy time.&lt;/p&gt;

&lt;p&gt;The QA action: whenever a new bug report comes in, the first query is &lt;em&gt;"what deployed in the last four hours, and does the bug timing line up?"&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Error-rate deltas, not error-rate absolutes
&lt;/h2&gt;

&lt;p&gt;The button-clicker version of log reading asks &lt;em&gt;"are there errors?"&lt;/em&gt; The systems version asks &lt;em&gt;"are there more errors than yesterday?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every non-trivial production system emits errors all the time. Retry storms, flaky dependencies, user-triggered validation failures, background jobs that time out. "Errors exist" is not information. "The 5xx rate doubled in the last hour relative to the same hour last week" is information.&lt;/p&gt;

&lt;p&gt;The pattern is to build every alarm and every investigation against a baseline, not an absolute. CloudWatch Metric Math, Datadog's anomaly monitors, Grafana's Prometheus &lt;code&gt;rate()&lt;/code&gt; queries — all of them express deltas. The baseline is whatever the system normally emits. The alert fires on deviation from baseline.&lt;/p&gt;

&lt;p&gt;QA who writes and tunes alarms at this level becomes the alarm-quality owner for the team, which is a senior-QA responsibility most orgs leave unowned.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. X-Ray and OpenTelemetry traces
&lt;/h2&gt;

&lt;p&gt;Logs tell you &lt;em&gt;what&lt;/em&gt; happened. Traces tell you &lt;em&gt;where in the call graph&lt;/em&gt; it happened.&lt;/p&gt;

&lt;p&gt;When a request passes through five services, logs alone require you to stitch the correlation ID across five log streams by hand. A trace shows the request as a waterfall: service A took 30ms, service B took 800ms, service C took 5ms. The 800ms span is the ticket. You did not have to read five log streams to find it.&lt;/p&gt;

&lt;p&gt;For a senior QA in a microservices environment, the trace view is the primary diagnostic surface. Logs are the backup when a span is missing detail. Traces make triage a minute-scale task; logs make it an hour-scale task.&lt;/p&gt;

&lt;p&gt;The QA action: learn the trace viewer for the specific stack (AWS X-Ray console, Datadog APM, Honeycomb, Jaeger). The first trace you open is uncomfortable. The hundredth one is faster than reading any log.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Alarm authoring and tuning
&lt;/h2&gt;

&lt;p&gt;The final pattern is the one that separates reactive QA from proactive QA.&lt;/p&gt;

&lt;p&gt;Alarms are the system's self-report. When an alarm fires, somebody gets paged. When an alarm does not fire for something the user will notice, the QA is on the hook for the gap. When an alarm fires for something nobody should be paged about, the team starts ignoring alarms and the real alert gets missed.&lt;/p&gt;

&lt;p&gt;The senior QA writes and tunes alarms. Not as a once-a-quarter audit but continuously. Every real incident produces an alarm postmortem: did the alarm fire? If not, write one. If it did but was too late, tune the threshold. If it was noisy in the previous week, fix the noise. The alarm suite is a living artifact, not a set-and-forget config.&lt;/p&gt;

&lt;p&gt;The QA action: own the alarm config as source-controlled infrastructure (Terraform, CDK, whatever the stack uses). Review alarm changes as PRs. Treat every page as either "useful" or "bug in the alarm" and act on the latter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this belongs to QA specifically, not SRE
&lt;/h2&gt;

&lt;p&gt;SRE owns the platform's reliability. QA owns whether the &lt;em&gt;product&lt;/em&gt; behaves correctly against user expectations. These overlap at the alarm layer, but the authoring centre of gravity differs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SRE writes alarms for &lt;em&gt;platform&lt;/em&gt; failure modes (a pod is unhealthy, a disk is filling, a node is out of memory).&lt;/li&gt;
&lt;li&gt;QA writes alarms for &lt;em&gt;user-visible&lt;/em&gt; failure modes (checkout succeeded with wrong amount, a feature flag leaked to the wrong cohort, the new endpoint returns 200 but the response body is malformed).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The user-visible alarms are the ones that map 1:1 to tickets. A QA who can name a user-visible failure shape in an alarm query is the QA who routes bugs before users file them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cross-pattern with Claude-Code operator discipline
&lt;/h2&gt;

&lt;p&gt;The six patterns above are the same pattern as the Husain manual-trace-labeling discipline for agent output: label the traces by hand, extract a taxonomy of failure shapes, then automate alarms against that taxonomy. Logs in a production service and traces in an agent system are the same artifact — a reviewable time-ordered record of what the system did, readable if you have structure, searchable if you have a query language, alertable if you have deltas.&lt;/p&gt;

&lt;p&gt;A QA who learns CloudWatch literacy is learning the production-observability half of the same operator pattern that makes Claude-Code pipelines reviewable. The tool is different; the shape is not.&lt;/p&gt;

&lt;p&gt;Pick one pattern from the six. Use it on the next bug ticket that lands on your queue. Five minutes of query-writing produces a better routing decision than forty minutes of meeting.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>qa</category>
      <category>aws</category>
      <category>devops</category>
      <category>observability</category>
    </item>
    <item>
      <title>If you know how it's built, you know how it breaks: CS fundamentals as a QA superpower</title>
      <dc:creator>Aman Bhandari</dc:creator>
      <pubDate>Sun, 19 Apr 2026 02:27:55 +0000</pubDate>
      <link>https://dev.to/amanbhandari/if-you-know-how-its-built-you-know-how-it-breaks-cs-fundamentals-as-a-qa-superpower-29ep</link>
      <guid>https://dev.to/amanbhandari/if-you-know-how-its-built-you-know-how-it-breaks-cs-fundamentals-as-a-qa-superpower-29ep</guid>
      <description>&lt;p&gt;A QA who understands the stack does not triage bugs. They diagnose and route them. The difference is not cosmetic — it is the difference between "users report the checkout page is slow" taking 40 minutes of back-and-forth across three teams, and "the Stripe webhook handler is synchronous and it is blocking the main event loop" taking five minutes and producing a patch.&lt;/p&gt;

&lt;p&gt;Six fundamentals compound that difference. Each one changes what the QA can see in a log, a trace, or a report. Each one is teachable — none require a CS degree, all require deliberate study against the specific production stack the QA is responsible for. I run this posture alongside the pipeline work in &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;, and the mechanical-sympathy foundation traces back to the &lt;code&gt;systems-thinking.md&lt;/code&gt; rule in &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. HTTP + TCP
&lt;/h2&gt;

&lt;p&gt;The button-clicker reports: &lt;em&gt;"the page is slow."&lt;/em&gt; The systems QA asks: &lt;em&gt;slow how?&lt;/em&gt; DNS resolution? TCP handshake? TLS negotiation? Time-to-first-byte from the server? Full download? Time-to-interactive on the client?&lt;/p&gt;

&lt;p&gt;The five diagnostic surfaces are different problems with different owners. DNS is infrastructure. TCP SYN retransmits are network-path or server-load. TLS slowness is certificate or key-exchange config. TTFB is the application. Full download is bandwidth or payload size. TTI is frontend.&lt;/p&gt;

&lt;p&gt;Opening Chrome DevTools' Network panel and reading the waterfall — red band before the response, long blocked-on-DNS band, long SSL band — is a 60-second check that routes the bug to the right team instead of parking it in a triage queue for a week. Same check works in &lt;code&gt;curl -w "@format.txt"&lt;/code&gt; or in a traceroute. None of this requires learning a new tool; it requires knowing which of the five things the bar is actually measuring.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Database query plans
&lt;/h2&gt;

&lt;p&gt;The button-clicker reports: &lt;em&gt;"the list page is slow when we have a lot of records."&lt;/em&gt; The systems QA runs &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; on the underlying query and sees the sequential scan, the missing index, or the nested loop that should have been a hash join.&lt;/p&gt;

&lt;p&gt;N+1 queries are the single most common performance bug in real codebases. An N+1 is invisible in the application logs — it shows up as "latency grows linearly with result count" and that is exactly the shape junior QA reports as "it gets slow as data grows." A senior QA with query-plan literacy catches it pre-merge, sometimes by reading the code, often by running the test against a seeded database with 10k rows and watching the plan.&lt;/p&gt;

&lt;p&gt;The fundamentals here: what an index is, what a query plan is, what the cost metric means, what a join order is, why &lt;code&gt;SELECT *&lt;/code&gt; in a hot path is a bug even when it works. None of this requires being a DBA. It requires being able to read &lt;code&gt;EXPLAIN&lt;/code&gt; output.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Async vs sync, event loops
&lt;/h2&gt;

&lt;p&gt;The button-clicker reports: &lt;em&gt;"sometimes it fails."&lt;/em&gt; The systems QA asks which concurrency model the service uses and looks for the specific failure shape that model produces.&lt;/p&gt;

&lt;p&gt;Node and FastAPI services on an event loop fail when somebody puts blocking I/O in the loop. The symptom: p99 latency spikes under load even though the CPU is at 30%. The cause: a sync &lt;code&gt;requests&lt;/code&gt; call or a sync file read is parking the loop for 200ms at a time, and every other request queued behind it. A QA who does not know what "blocking the loop" means files "sometimes slow under load" and waits.&lt;/p&gt;

&lt;p&gt;Thread-pool services fail differently — pool exhaustion, deadlocks, dropped work. Go services with channel-based concurrency have their own idioms (unclosed channels, leaked goroutines). The concurrency model is part of the stack; the failure shapes are determined by it.&lt;/p&gt;

&lt;p&gt;The fundamentals here: cooperative vs preemptive scheduling, where the context switch happens, what a blocking call costs in each model. A week of study, applied to one stack the QA owns, pays back every time a "sometimes" bug lands on the queue.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Memory layout, garbage collection
&lt;/h2&gt;

&lt;p&gt;The button-clicker reports: &lt;em&gt;"the pod keeps getting killed."&lt;/em&gt; The systems QA opens &lt;code&gt;kubectl describe pod&lt;/code&gt; and sees &lt;code&gt;OOMKilled&lt;/code&gt;. Then the QA asks whether the process is actually using that much memory or whether the RSS grew while the Python heap stayed flat — which is the classic &lt;code&gt;musl&lt;/code&gt;/&lt;code&gt;jemalloc&lt;/code&gt; fragmentation signature BetterUp wrote about, where the fix is not a memory leak patch but an allocator change.&lt;/p&gt;

&lt;p&gt;Or the process is a Python service forking threads and each thread's 10MB C stack is accumulating against the heap, as in the Brex incident. Or it is a Java service with a heap size that does not match the container limit. Or it is a Go service that genuinely is leaking.&lt;/p&gt;

&lt;p&gt;Four different failures, four different owners, one OOM kill. The senior QA does not file "OOM kill" as the ticket. They file "OOM kill with RSS pattern X under load Y, pods from version Z forward, heap flat/growing, here are the metrics" — and the ticket lands on the right desk the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. CI/CD and container isolation
&lt;/h2&gt;

&lt;p&gt;The button-clicker reports: &lt;em&gt;"the test passes on my branch but fails on main."&lt;/em&gt; The systems QA asks what is different between the two environments and starts eliminating variables.&lt;/p&gt;

&lt;p&gt;Container isolation breaks when tests share state: a port, a database, a cache, a filesystem mount, an environment variable inherited from the runner. Flakes often come from tests that pass in isolation and fail when scheduled alongside another test that pollutes shared state.&lt;/p&gt;

&lt;p&gt;The fundamentals here: what a Docker image is, what the difference between a container and a VM is, what the CI runner's filesystem looks like between jobs, how environment variables get injected. Plus a working knowledge of the specific CI system (GitHub Actions, GitLab, CircleCI) — not every feature, but the mental model of "how does a job start and what state does it see."&lt;/p&gt;

&lt;p&gt;Without this, flake investigation becomes "re-run the failing job." With it, the flake gets localized to the specific shared resource and fixed at the root.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Distributed tracing
&lt;/h2&gt;

&lt;p&gt;The button-clicker reports: &lt;em&gt;"the checkout API is returning 500."&lt;/em&gt; The systems QA opens the trace for the failing request and sees exactly which downstream service threw the 500, which span had the long latency, and which upstream request was correlated to the same user action.&lt;/p&gt;

&lt;p&gt;Distributed tracing (X-Ray, OpenTelemetry, Datadog APM, whatever the stack uses) is the single highest-payoff thing a QA can learn in a microservices environment. Without traces, every cross-service bug is a detective game. With traces, the span with the error is the ticket's answer.&lt;/p&gt;

&lt;p&gt;The fundamentals here: trace ID, span ID, parent-span ID, how context propagates across service boundaries, how a trace gets sampled. Plus the specific tool. Not all of it at once — enough to open a trace, read the critical path, and name the failing span.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this pattern is durable
&lt;/h2&gt;

&lt;p&gt;These six fundamentals rotate very slowly. HTTP, TCP, SQL query plans, event loops, memory layout, containers, distributed tracing — the specific tools change every few years, the concepts almost never do. A QA who invests in the concepts once redeploys that knowledge against every stack they encounter.&lt;/p&gt;

&lt;p&gt;Compare to the button-clicker skills that get hot every hiring cycle: Selenium, Cypress, Playwright, Puppeteer, Robot Framework. Each one is a five-year tool. The concepts above have held for twenty. The senior QA keeps the concepts up and rotates the tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this connects to the Claude-Code operator pattern
&lt;/h2&gt;

&lt;p&gt;The same &lt;code&gt;systems-thinking.md&lt;/code&gt; rule that says every concept is taught in three layers — mental model, OS/hardware model, production model — is the foundation both for Claude-Code teaching and for QA diagnostic work. The lab reference is a running list of real production incidents that traced back to a fundamentals gap: the Brex OOM, the BetterUp RSS growth, the Cloudflare TCP bug, the Google SRE file descriptor leak. Each one is a QA-diagnosis story with an operator-pattern conclusion: the engineer who understood the layer below the abstraction solved it in 20 minutes; the one who did not stared at application logs for three hours.&lt;/p&gt;

&lt;p&gt;QA that reaches for a fundamental first — before filing the ticket, before escalating, before re-running the test — is the QA that becomes indispensable. The tool-hoarding alternative is exactly the version of the role that coding agents replace fastest.&lt;/p&gt;

&lt;p&gt;Pick one fundamental from the six. Learn it against the stack you own. The next time a "sometimes" bug lands on your queue, diagnose it before filing. You will be unrecognizable to the team within a quarter.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Aman Bhandari. Operator of an AI-engineering research lab running Claude Opus as the coaching partner, plus a QA-automation surface shipping against a real sprint workload. Public artifacts: &lt;a href="https://github.com/aman-bhandari/claude-code-agent-skills-framework" rel="noopener noreferrer"&gt;claude-code-agent-skills-framework&lt;/a&gt; and &lt;a href="https://github.com/aman-bhandari/claude-code-mcp-qa-automation" rel="noopener noreferrer"&gt;claude-code-mcp-qa-automation&lt;/a&gt;. &lt;code&gt;github.com/aman-bhandari&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>qa</category>
      <category>testing</category>
      <category>computerscience</category>
      <category>career</category>
    </item>
  </channel>
</rss>
