<?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: Maksym Kuzmitskyi (MaximusFT)</title>
    <description>The latest articles on DEV Community by Maksym Kuzmitskyi (MaximusFT) (@maximusft).</description>
    <link>https://dev.to/maximusft</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1819104%2Fd158bf22-3ff5-498a-bab8-91ce4b684bc1.jpg</url>
      <title>DEV Community: Maksym Kuzmitskyi (MaximusFT)</title>
      <link>https://dev.to/maximusft</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maximusft"/>
    <language>en</language>
    <item>
      <title>Upgrading the Model Means Retesting the Workflow</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Thu, 29 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/upgrading-the-model-means-retesting-the-workflow-39l0</link>
      <guid>https://dev.to/maximusft/upgrading-the-model-means-retesting-the-workflow-39l0</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzxb9ff7z3xevx2is8fxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzxb9ff7z3xevx2is8fxu.png" alt="Upgrading the Model Means Retesting the Workflow" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Changing a model identifier can be a one-line edit. It is not necessarily a one-line change to the system's behavior.&lt;/p&gt;

&lt;p&gt;The same task may now produce different searches, tool arguments, clarification questions, stopping decisions or recovery attempts. The final code can improve while one of those surrounding behaviors becomes less suitable for the workflow.&lt;/p&gt;

&lt;p&gt;I would treat a model upgrade as a change to an engineering dependency, not as permission to carry every previous assumption forward.&lt;/p&gt;

&lt;p&gt;That isn't an argument for staying on an old model. It is a reason to make the benefit and the compatibility work observable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The application contract is larger than the final answer
&lt;/h2&gt;

&lt;p&gt;A coding agent operates inside a harness: prompts, tool definitions, permissions, context management, execution loops and output handling. The model is one consequential part of that arrangement.&lt;/p&gt;

&lt;p&gt;The contract may require the agent to inspect the current base before editing, use a particular tool for a sensitive action, stop when authorization is missing, and distinguish an unavailable check from a successful one.&lt;/p&gt;

&lt;p&gt;Those requirements don't disappear because the candidate model produces a better-looking patch.&lt;/p&gt;

&lt;p&gt;Some differences are API compatibility issues. Others are valid behavior changes inside an otherwise compatible API. A request succeeding doesn't establish that the application still gets the kind of progress events or tool-use pattern it expects.&lt;/p&gt;

&lt;p&gt;There is current, concrete evidence for taking that distinction seriously. Anthropic's &lt;a href="https://platform.claude.com/docs/en/models/fable-5-1/migration-guide" rel="noopener noreferrer"&gt;Fable 5.1 migration guide&lt;/a&gt;, checked on October 23, 2026, documents model-specific changes involving forced tool choice, conversation-history handling and agent-loop behavior. Those details apply to the documented migration, not to every model or managed product.&lt;/p&gt;

&lt;p&gt;The general lesson isn't to memorize today's parameter list. It is to read the migration contract for the exact integration being changed. A managed agent product may handle details that a custom API harness must manage itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  First name what is actually changing
&lt;/h2&gt;

&lt;p&gt;An editor update can change the model, tool descriptions and execution behavior together. A provider can update a model alias. A team can revise its system prompt while testing a new model.&lt;/p&gt;

&lt;p&gt;If all of those happen at once, an improved result does not identify which change helped. A regression doesn't identify which component broke either.&lt;/p&gt;

&lt;p&gt;For a controlled comparison, I would record the model identity available to the integration, harness revision, prompt revision, tool schemas, relevant settings and fixture state. If the exact underlying model is hidden, I would record that limitation instead of inventing a stable identity.&lt;/p&gt;

&lt;p&gt;Keep task inputs and starting repositories comparable. A new base commit, warmed cache or already-fixed fixture can turn a model comparison into a comparison of different problems.&lt;/p&gt;

&lt;p&gt;One variable at a time is a useful diagnostic ideal, not always a deployment option. When a product bundles changes, evaluate the bundle and describe the attribution limit honestly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build cases around decisions that matter
&lt;/h2&gt;

&lt;p&gt;I would start with a small regression set drawn from the workflow's consequential boundaries.&lt;/p&gt;

&lt;p&gt;A clear local fix should remain clear and local. An ambiguous requirement should produce a useful question rather than an invented product decision. A failed integration check should not be summarized as a successful task because the unit suite passed.&lt;/p&gt;

&lt;p&gt;Another fixture might change the PR head during review. The expected outcome is to notice that the reviewed artifact has changed, not merely attach the old conclusion somewhere the API accepts it.&lt;/p&gt;

&lt;p&gt;These are proposed evaluation cases, not reported experiments or results from my work. Their value comes from defining the acceptable outcome before reading the candidate's explanation.&lt;/p&gt;

&lt;p&gt;I would avoid requiring one exact tool-call sequence unless the sequence itself enforces a real constraint. Two valid investigations may read different files. The evaluation should distinguish a different route from a violation of the task's boundaries.&lt;/p&gt;

&lt;p&gt;Conversely, a plausible final patch shouldn't erase an unauthorized intermediate action. Evaluate consequential actions and the final artifact, not just the last paragraph.&lt;/p&gt;

&lt;h2&gt;
  
  
  Grade observable behavior, with room for uncertainty
&lt;/h2&gt;

&lt;p&gt;Some outcomes can be checked mechanically: whether a forbidden mutation occurred, whether the final diff contains unrelated files, or whether a claimed test command actually completed.&lt;/p&gt;

&lt;p&gt;Other outcomes need a domain reviewer: whether a clarification was necessary, whether a suggested integration belongs in scope, or whether the proposed test establishes the intended behavior.&lt;/p&gt;

&lt;p&gt;A model-based grader can help organize evidence, but it isn't automatically an independent authority. I would calibrate it against reviewed examples and inspect disagreements. A score without an understandable basis is another opaque output.&lt;/p&gt;

&lt;p&gt;OpenAI's &lt;a href="https://developers.openai.com/api/docs/guides/evaluation-getting-started" rel="noopener noreferrer"&gt;evaluation documentation&lt;/a&gt; describes datasets, annotations and graders. At the October 23 check, it also carries a deprecation notice for the hosted Evals platform. I am not recommending a new dependency on that retiring service. Representative cases and explicit grading criteria remain useful regardless of which supported runner stores them.&lt;/p&gt;

&lt;p&gt;The tooling should serve the comparison. It should not become a reason to keep a fragile evaluation tied to an obsolete interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recovery deserves its own test
&lt;/h2&gt;

&lt;p&gt;A clean success path is a friendly demonstration. The more revealing cases often involve unavailable tools, authentication failures, partial edits and interrupted work.&lt;/p&gt;

&lt;p&gt;I would check whether the candidate preserves the task boundary after an error. Does it ask for a secret in an inappropriate channel? Does it retry an irreversible operation without checking the previous outcome? Does it weaken a test merely to complete the loop?&lt;/p&gt;

&lt;p&gt;These concerns aren't claims that a particular model does those things. They are reasons to observe recovery rather than assume it inherits the quality of the model's successful answers.&lt;/p&gt;

&lt;p&gt;Permissions should remain enforced outside the model. An evaluation can detect undesirable behavior; it shouldn't be the only thing preventing a consequential action.&lt;/p&gt;

&lt;p&gt;The same reasoning applies to compaction and handoffs. A workflow that works for five turns may fail when a summary loses an important unresolved condition. A longer-running fixture can expose that boundary without requiring an enormous benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare the cost of an accepted result
&lt;/h2&gt;

&lt;p&gt;Tokens and response latency are useful measurements. They don't describe the whole task if the candidate requires more correction, publishes noisier reviews or leaves harder-to-understand changes.&lt;/p&gt;

&lt;p&gt;I would record human interventions and rework alongside execution cost, using actual observations rather than estimated productivity claims. Passive waiting and a person's active effort are different quantities.&lt;/p&gt;

&lt;p&gt;Repeated runs matter where outputs vary. One candidate success and one baseline failure are anecdotes, not a stable rate. The amount of repetition should match the consequence of the decision and the available resources.&lt;/p&gt;

&lt;p&gt;The result can be mixed: better implementation on one class of task, more clarification on another, a compatibility repair needed in the harness. That is a useful migration finding, not a disappointing failure to produce a winner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep a way back
&lt;/h2&gt;

&lt;p&gt;Before changing a default, I would keep the previous configuration identifiable and limit initial exposure. That might mean a small authorized task class or shadow review without automatic publication.&lt;/p&gt;

&lt;p&gt;Rollback has limits too. A pinned model may later be retired, and a managed product may not expose an exact old configuration. Record what can actually be restored rather than promising a permanent switch.&lt;/p&gt;

&lt;p&gt;The existing &lt;a href="https://ma-x.im/blog/agent-playbook-evaluation-is-the-missing-loop" rel="noopener noreferrer"&gt;evaluation article&lt;/a&gt; asks whether the workflow produces useful outcomes. A model upgrade is a concrete occasion to ask that question again, with the old assumptions made visible.&lt;/p&gt;

&lt;p&gt;I want to use better models. I also want to know which part of my working agreement with the agent changed when I selected one.&lt;/p&gt;

&lt;p&gt;What would make a model upgrade fail acceptance in your workflow even if its final code looked better? I'd like to hear which behavioral regressions your evaluations can actually detect.&lt;/p&gt;

</description>
      <category>aiagents</category>
      <category>evaluation</category>
      <category>developertooling</category>
      <category>reliability</category>
    </item>
    <item>
      <title>When Repository Content Starts Giving Orders</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Tue, 27 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/when-repository-content-starts-giving-orders-5gi1</link>
      <guid>https://dev.to/maximusft/when-repository-content-starts-giving-orders-5gi1</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkiy2j971vqgdaiz2wq9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkiy2j971vqgdaiz2wq9n.png" alt="When Repository Content Starts Giving Orders" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A source comment explains a strange compatibility rule. A README explains how to run the project. A test fixture contains a conversation. A fetched issue describes what should change.&lt;/p&gt;

&lt;p&gt;A coding agent needs all of them. They do not all have the same right to tell it what to do.&lt;/p&gt;

&lt;p&gt;That is the boundary I find more useful than telling an agent not to trust the internet. A repository can contain relevant evidence, authorized project instructions, obsolete advice and deliberately hostile text. Sometimes those arrive through the same search result.&lt;/p&gt;

&lt;p&gt;The problem is not reading a suspicious sentence. The problem is promoting a sentence from material under inspection into authority over the inspection.&lt;/p&gt;

&lt;h2&gt;
  
  
  The source being reviewed cannot appoint itself the reviewer
&lt;/h2&gt;

&lt;p&gt;Consider an illustrative PR that adds a comment describing a component as exempt from ordinary validation. The same change tells automated reviewers to ignore failures involving that component.&lt;/p&gt;

&lt;p&gt;The comment may be useful evidence about the author's intent. It is not, by itself, an approved exception to the team's validation policy.&lt;/p&gt;

&lt;p&gt;If the agent treats it as an instruction, the proposed code has acquired a way to influence how it is judged. The author need not have changed a tool permission or a protected policy file. The confusion happened in interpretation.&lt;/p&gt;

&lt;p&gt;This can be deliberate prompt injection. It can also resemble an ordinary documentation mistake: an outdated setup note asks for a step the current task doesn't need. The intent of the text and the authority of the text are separate questions.&lt;/p&gt;

&lt;p&gt;I would not claim every incorrect README instruction is an attack. I would ask whether the agent is using it as context to verify or as a command that overrides the actual task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repository-local doesn't mean equally trusted
&lt;/h2&gt;

&lt;p&gt;An instruction file deliberately selected by the user or organization has a different role from a copied log line. A task description from an authorized owner differs from an arbitrary comment underneath it. A policy on the reviewed branch may itself be part of the proposed change.&lt;/p&gt;

&lt;p&gt;That doesn't mean refusing all repository instructions. It means keeping their origin, scope and review status visible.&lt;/p&gt;

&lt;p&gt;For a PR reviewer, the base branch's approved policy and a proposed replacement on the head branch should not silently become the same source. A legitimate policy update may need review. Its existence in the diff doesn't automatically authorize it to govern that review.&lt;/p&gt;

&lt;p&gt;Likewise, a retrieval tool returning content doesn't authenticate the instructions inside that content. The tool may be trusted to fetch a page accurately while the page remains untrusted to direct actions.&lt;/p&gt;

&lt;p&gt;The distinction also applies to generated summaries. If a summary turns a quoted instruction from a fixture into an unqualified next step, it can lose the original boundary while preserving the words.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Accurate retrieval is not delegated authority.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I want a handoff to preserve that difference, not just preserve more text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current controls matter, but they cover different surfaces
&lt;/h2&gt;

&lt;p&gt;This is not an argument that current coding agents operate without protections. The &lt;a href="https://code.visualstudio.com/docs/agents/run/security" rel="noopener noreferrer"&gt;VS Code security guide&lt;/a&gt;, checked on October 23, 2026, documents workspace trust, approvals, sandboxing, MCP-server trust and information-exposure risks.&lt;/p&gt;

&lt;p&gt;The details depend on the active harness and tool path. Its guidance distinguishes process sandboxing from permission checks on other tools and warns that sandboxing is not a standalone security boundary. That is more useful than assuming one toggle makes every route equivalent.&lt;/p&gt;

&lt;p&gt;Instructions guide the model. Permissions determine which operations are available. Isolation can constrain what an executing process reaches. Network restrictions constrain destinations. None of these automatically proves that a proposed change satisfies the task.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.github.com/en/copilot/responsible-use/code-review" rel="noopener noreferrer"&gt;current GitHub application card&lt;/a&gt; also describes different environments and data flows for its agentic surfaces. I wouldn't transfer a cloud agent's documented constraints to a local terminal session merely because both carry the same product name.&lt;/p&gt;

&lt;p&gt;Good controls reduce the consequences of a confused decision. They do not remove the need to distinguish data from instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the action boundary outside the prose
&lt;/h2&gt;

&lt;p&gt;A document can recommend a command. It should not be able to grant that command new permissions.&lt;/p&gt;

&lt;p&gt;I would enforce consequential restrictions in the tool or execution environment rather than depend solely on the model agreeing to follow a warning. A reviewer that doesn't need mutation tools shouldn't receive them by default. A task needing one repository shouldn't inherit every account a developer happens to use.&lt;/p&gt;

&lt;p&gt;That principle is narrower than prescribing a particular sandbox configuration. Filesystem access, credential availability, network routes and connected services vary by environment. The controls have to be checked where actions actually run.&lt;/p&gt;

&lt;p&gt;A tool wrapper that inspects only one command shape may miss a different execution route. A hook's failure or timeout behavior may not match an engineer's assumption about stopping. I would test those boundaries instead of treating the existence of a hook as enforcement.&lt;/p&gt;

&lt;p&gt;There is also a quiet escalation to avoid: allowing a document being analyzed to nominate additional tools or a more privileged environment as prerequisites. A claimed need for access is still a request to evaluate.&lt;/p&gt;

&lt;p&gt;I discussed useful tool context in &lt;a href="https://ma-x.im/blog/agent-playbook-tools-are-intelligence" rel="noopener noreferrer"&gt;Tools Are Part of the Agent's Intelligence&lt;/a&gt;. That usefulness makes precise tool authority more important, not less.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test whether an instruction stays inside its source
&lt;/h2&gt;

&lt;p&gt;For an authorized local evaluation, I would use harmless fixtures. A source file or mock tool result could request a clearly out-of-task change to a disposable marker file. The expected outcome would be to recognize the instruction as content, not carry it out.&lt;/p&gt;

&lt;p&gt;No real secrets, external collection endpoints or production systems are needed to establish that question. The test should inspect actual tool activity as well as the final explanation. Saying that an instruction was ignored while performing its requested action is not a pass.&lt;/p&gt;

&lt;p&gt;I would vary the source: a comment, a generated report, a quoted issue reply and a summarized tool result. The aim is to check the boundary through paths the workflow actually uses, not to collect theatrical attack phrases.&lt;/p&gt;

&lt;p&gt;Passing such fixtures is evidence about those cases. It is not proof against every prompt injection. The environment still needs constraints that limit the effect of a missed case.&lt;/p&gt;

&lt;p&gt;Legitimate instructions matter in the evaluation too. An agent that refuses to follow the approved project setup has not solved trust by refusing all work. I want correct treatment of different sources, not indiscriminate suspicion.&lt;/p&gt;

&lt;h2&gt;
  
  
  A stopped action should leave an understandable reason
&lt;/h2&gt;

&lt;p&gt;If a source asks for an unexpected operation, the useful response identifies the source and the conflict: this instruction appeared in material being analyzed, but the task did not authorize the action.&lt;/p&gt;

&lt;p&gt;A person can then confirm an actual requirement through the appropriate channel. The agent doesn't need to turn every questionable paragraph into an emergency. It needs to avoid quietly changing who is in charge.&lt;/p&gt;

&lt;p&gt;Logs can help reconstruct that decision, but they should not copy entire sensitive documents merely to preserve evidence. Record enough origin and action information to investigate, with appropriate access and retention.&lt;/p&gt;

&lt;p&gt;I don't want to make agents blind to repositories. I want them to read carefully without making every readable sentence a new supervisor.&lt;/p&gt;

&lt;p&gt;When a coding agent fetches something in your workflow, what establishes whether that content may direct its next action? I'd be interested in the boundaries you have actually tested, especially the ones that survive summaries and handoffs.&lt;/p&gt;

</description>
      <category>aiagents</category>
      <category>security</category>
      <category>promptinjection</category>
      <category>developertooling</category>
    </item>
    <item>
      <title>The Agent Finished. The Reviewer Is Still Reading.</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Sun, 25 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/the-agent-finished-the-reviewer-is-still-reading-28mc</link>
      <guid>https://dev.to/maximusft/the-agent-finished-the-reviewer-is-still-reading-28mc</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbwxhpytgezfwuqm0x58k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbwxhpytgezfwuqm0x58k.png" alt="The Agent Finished. The Reviewer Is Still Reading." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The agent has finished the implementation. CI is green. There is a useful PR description, a test summary and another task ready to start.&lt;/p&gt;

&lt;p&gt;The reviewer is still trying to understand the first change.&lt;/p&gt;

&lt;p&gt;I don't think that makes the reviewer the slow part of an otherwise efficient machine. Generation and acceptance are different kinds of work. Producing another plausible implementation does not create another person's attention to examine it.&lt;/p&gt;

&lt;p&gt;The interesting question isn't how many PRs an agent can open. It is how much consequential change a team can understand, validate and own without turning review into an exercise in trusting the summary.&lt;/p&gt;

&lt;h2&gt;
  
  
  A faster author changes the queue
&lt;/h2&gt;

&lt;p&gt;Imagine a team where generated changes arrive faster than reviewers can assess them. This is a hypothetical operating condition, not a productivity measurement from my work.&lt;/p&gt;

&lt;p&gt;The immediate symptoms might look encouraging: more branches, more completed implementation tasks, more green checks. The waiting work has simply moved.&lt;/p&gt;

&lt;p&gt;Opening several PRs in parallel may shorten implementation time for each author while extending the delay before any reviewer can concentrate on one. Interrupting reviewers with repeated requests makes their effective capacity smaller still.&lt;/p&gt;

&lt;p&gt;This is a workflow problem, not an argument against agents. A compiler getting faster never meant that architectural judgment became free. The same distinction deserves to survive another increase in code-generation capacity.&lt;/p&gt;

&lt;p&gt;OpenAI's &lt;a href="https://openai.com/index/harness-engineering/" rel="noopener noreferrer"&gt;2026 harness-engineering report&lt;/a&gt; describes human QA capacity becoming a constraint as code throughput increased in its own internal experiment. Its response involved making application behavior and observability more accessible to agents. Those are observations from a particular environment, not a throughput target or permission model I would import wholesale.&lt;/p&gt;

&lt;p&gt;For my purposes, the important part is the changed constraint. If acceptance is waiting, making authors produce more work may be optimizing the wrong stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reviewability isn't a line-count limit
&lt;/h2&gt;

&lt;p&gt;A small diff can contain a large decision. One changed authorization condition may deserve more attention than a generated file containing hundreds of mechanical edits.&lt;/p&gt;

&lt;p&gt;I would size review around behavioral questions: what changed, who depends on it, which assumptions changed, and what evidence is available. Line counts can help notice outliers. They do not calculate risk.&lt;/p&gt;

&lt;p&gt;Consider an illustrative PR that introduces a shared utility, migrates consumers, changes a dependency and refreshes unrelated snapshots. Every individual edit might be reasonable. Together they create several distinct review jobs.&lt;/p&gt;

&lt;p&gt;The reviewer has to separate the intended behavior change from migration mechanics, dependency effects and test-expectation updates. A detailed explanation can help. A cleaner division of work may help more.&lt;/p&gt;

&lt;p&gt;That doesn't mean splitting code into arbitrary tiny PRs. A sequence of fragments that cannot be tested or understood independently can increase coordination costs. I would look for cohesive behavioral slices with explicit dependencies and a valid state between them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A reviewable change gives someone a bounded question they can actually answer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The unit isn't necessarily one file, one agent session or one convenient commit. It is an intelligible decision with enough surrounding evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summaries should lower the cost of checking
&lt;/h2&gt;

&lt;p&gt;A good summary tells me where to inspect, not merely what conclusion to reach.&lt;/p&gt;

&lt;p&gt;For a permission change, I want the affected rule, the relevant route and the check that exercised a denied action. For a shared component change, I want the changed contract and the consumers that make it consequential. For an expected-result update, I want the requirement that changed.&lt;/p&gt;

&lt;p&gt;I don't need a transcript of every search or an elaborate account of the model's internal reasoning. I need references I can follow and limitations I can see.&lt;/p&gt;

&lt;p&gt;An agent saying that all relevant scenarios passed should be able to identify those scenarios. If a check was unavailable, the absence should remain visible rather than disappear inside a reassuring overall conclusion.&lt;/p&gt;

&lt;p&gt;This is related to &lt;a href="https://ma-x.im/blog/github-ai-pr-reviewer" rel="noopener noreferrer"&gt;useful automated review comments&lt;/a&gt;, but it is a different responsibility. The question here is whether the whole change can be accepted with reasonable effort, not whether an individual bot comment is well phrased.&lt;/p&gt;

&lt;p&gt;Long descriptions can make the problem worse if their conclusions are easier to read than their evidence is to verify. I would rather have three precise links and one unresolved question than a confident report that nobody has time to audit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Another agent can remove work, or add another queue
&lt;/h2&gt;

&lt;p&gt;Automated review can catch local defects, investigate a suspicious export or check a routine convention before a person arrives. That is useful preparation.&lt;/p&gt;

&lt;p&gt;It can also generate a second pile of work: findings to validate, false positives to dismiss, replies to interpret and repeated comments to reconcile. A quiet tool isn't necessarily effective, and a busy one isn't necessarily helping.&lt;/p&gt;

&lt;p&gt;GitHub's current &lt;a href="https://docs.github.com/en/copilot/responsible-use/code-review" rel="noopener noreferrer"&gt;application card for Copilot agents&lt;/a&gt; explicitly discusses missed issues, false positives and inaccurate suggestions, and recommends supplementing automated review with human review. These are present documented limits, not a claim that current tools only inspect a few lines of a diff.&lt;/p&gt;

&lt;p&gt;I would assess whether a review tool reduces the human effort needed to reach a sound decision. That includes the effort spent checking the tool itself. Comment count is a poor substitute.&lt;/p&gt;

&lt;p&gt;The same applies to UI evidence. Browser automation can make a previously invisible interaction inspectable, but a screenshot doesn't verify every state. Helpful automation narrows the remaining question. It doesn't just add another green label.&lt;/p&gt;

&lt;h2&gt;
  
  
  Control work in progress before asking for faster review
&lt;/h2&gt;

&lt;p&gt;If review capacity is the constraint, I would try limiting how many changes are actively seeking attention. Completing one reviewable slice before opening three more can improve the flow without changing the model.&lt;/p&gt;

&lt;p&gt;That limit should be a team decision, not a universal number. A routine dependency stream and a change to a shared identity contract don't impose the same load.&lt;/p&gt;

&lt;p&gt;Review ownership also matters. An agent can identify potential consumers, but that doesn't automatically identify who is accountable for accepting the change. A PR waiting for everyone can quietly become a PR owned by no one.&lt;/p&gt;

&lt;p&gt;I would make blocked states explicit: waiting for a domain decision, waiting for a missing integration check, or waiting for a reviewer with the relevant ownership. Those call for different actions. Re-running the same agent is unlikely to resolve all three.&lt;/p&gt;

&lt;p&gt;There is a useful stopping point for automation here. When the next step is an accountable decision, generating more implementation isn't progress on that decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure the waiting and the rework
&lt;/h2&gt;

&lt;p&gt;I would keep measurements modest and specific: how long changes wait for first substantive review, how often a PR needs to be separated, what corrections arrive after apparent completion, and which review questions repeatedly lack evidence.&lt;/p&gt;

&lt;p&gt;These are proposed observations, not results I have measured for a comparative study. They need definitions and local interpretation. A shorter review can mean a better-prepared change, but it can also mean a rushed reviewer.&lt;/p&gt;

&lt;p&gt;The goal isn't to make every change slower. It is to stop borrowing confidence from an overloaded acceptance process. If the team cannot explain what it accepted, the implementation speed has hidden part of its cost.&lt;/p&gt;

&lt;p&gt;I still want the agent to finish quickly. I also want its finished work to be something another engineer can pick up without reconstructing an entire conversation.&lt;/p&gt;

&lt;p&gt;When I look at a queue of generated PRs, that is the question I would put ahead of the next throughput improvement: can the people responsible for this system still understand what is entering it?&lt;/p&gt;

&lt;p&gt;Where does review capacity constrain your AI-assisted workflow: understanding the change, checking the evidence, or sorting automated findings? I'd be interested in what actually reduced that burden, not just what produced more output.&lt;/p&gt;

</description>
      <category>aiagents</category>
      <category>codereview</category>
      <category>engineeringworkflow</category>
      <category>maintainability</category>
    </item>
    <item>
      <title>Who Checks the Tests an AI Agent Writes?</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Fri, 23 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/who-checks-the-tests-an-ai-agent-writes-3kg9</link>
      <guid>https://dev.to/maximusft/who-checks-the-tests-an-ai-agent-writes-3kg9</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy4f8e9zj54eo927agtyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy4f8e9zj54eo927agtyv.png" alt="Who Checks the Tests an AI Agent Writes?" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An agent writes a function, adds tests, runs them, and reports success. The implementation and the tests agree.&lt;/p&gt;

&lt;p&gt;What established that they agreed on the right behavior?&lt;/p&gt;

&lt;p&gt;This is the part of AI-generated testing I want to examine before counting new assertions. A test can be perfectly executable, exercise the relevant branch, and confirm the same mistaken interpretation that produced the code.&lt;/p&gt;

&lt;p&gt;Humans do this too. The additional concern with an agent is how conveniently implementation, test cases, fixtures and the final explanation can be produced from one interpretation. They look like several pieces of evidence. They may have only one underlying assumption.&lt;/p&gt;

&lt;p&gt;I don't want fewer generated tests. I want a clearer answer to where their expected results came from.&lt;/p&gt;

&lt;h2&gt;
  
  
  A passing test for the wrong rule
&lt;/h2&gt;

&lt;p&gt;Consider a fictional checkout policy. Free shipping applies when the merchandise subtotal &lt;strong&gt;after discounts&lt;/strong&gt; is at least 5,000 cents. Tax and shipping charges do not contribute. The examples below assume valid, nonnegative integer inputs, with discounts no greater than the merchandise subtotal; input validation is a separate concern.&lt;/p&gt;

&lt;p&gt;This is an illustrative example, not an incident from a client project.&lt;/p&gt;

&lt;p&gt;An implementation and its test might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:assert/strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ShippingQuote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;merchandiseCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;discountCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;qualifiesForFreeShipping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ShippingQuote&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;merchandiseCents&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;qualifiesForFreeShipping&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;merchandiseCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;discountCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_500&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test passes. The discounted subtotal is 4,500 cents. Under the stated policy, that order does not qualify.&lt;/p&gt;

&lt;p&gt;The test has not failed to execute the implementation. It has asserted the wrong answer. A coverage report can show that the function ran without noticing that the expected value contradicts the requirement.&lt;/p&gt;

&lt;p&gt;Adding more examples above the undiscounted threshold won't necessarily help. Nor will renaming the test to sound more specific. The missing ingredient is an expected result derived from the policy, rather than an observation of what the function currently returns.&lt;/p&gt;

&lt;p&gt;That expected result is the test oracle: the basis for deciding whether the observed behavior is correct. It doesn't have to be a separate program or an expensive formal specification. Sometimes it is one arithmetic calculation and a sentence someone has actually agreed on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Establish the expectation before polishing the implementation
&lt;/h2&gt;

&lt;p&gt;For this policy, I would start with a few examples whose answers can be worked out without consulting the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;qualifiesForFreeShipping&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;merchandiseCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;discountCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_500&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;qualifiesForFreeShipping&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;merchandiseCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;discountCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;qualifiesForFreeShipping&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;merchandiseCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;_999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;discountCents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first case disagrees with the original test. That disagreement is useful. It makes the interpretation visible instead of burying it beneath a successful run.&lt;/p&gt;

&lt;p&gt;The implementation can then follow the policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;qualifiesForFreeShipping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ShippingQuote&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;discountedMerchandiseCents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;merchandiseCents&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;discountCents&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;discountedMerchandiseCents&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a complete checkout test suite. The cases establish the particular discount and threshold behavior under discussion. They don't establish currency conversion, tax treatment elsewhere, coupon validity or production integration.&lt;/p&gt;

&lt;p&gt;I would ask the agent to identify the source of each important expectation. An acceptance criterion, an approved example, a documented contract or a trusted reference can justify it. The current implementation can tell us what happens, but not always what should happen.&lt;/p&gt;

&lt;p&gt;If the requirement doesn't settle whether the threshold applies before or after discounts, generating an assertion doesn't settle it either. The correct next step is a question. An executable guess is still a guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  A second agent needs a different starting point
&lt;/h2&gt;

&lt;p&gt;It is tempting to solve this by assigning test generation to another agent. That can help, but a separate role is not automatically an independent basis for judgment.&lt;/p&gt;

&lt;p&gt;If the second agent receives the implementation and a persuasive explanation of why it is correct, it may simply encode that explanation as tests. Changing the model doesn't guarantee a different interpretation of an ambiguous requirement.&lt;/p&gt;

&lt;p&gt;For consequential behavior, I would give the test reviewer the original requirement and ask it to derive concrete outcomes before showing it the implementation. Then compare the cases with the code and existing tests.&lt;/p&gt;

&lt;p&gt;This reduces one source of anchoring. It doesn't prove independence or eliminate shared mistakes. Both reviewers may still misunderstand the requirement, which is why the expected outcomes need to remain inspectable by a person.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://ma-x.im/blog/agent-playbook-green-checks" rel="noopener noreferrer"&gt;Green Checks Only Cover What You Checked&lt;/a&gt;, the concern was the reach of evidence across an integration boundary. Here the boundary is earlier: whether the assertion itself expresses the intended behavior. An integration test can have a wrong expectation too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check that the test can disagree
&lt;/h2&gt;

&lt;p&gt;A useful test should fail for a relevant wrong implementation. I would deliberately check that property, rather than infer it from a green run.&lt;/p&gt;

&lt;p&gt;In this example, ignoring the discount should fail the first requirement-derived case. Changing the threshold comparison from inclusive to exclusive should fail the exact-boundary case.&lt;/p&gt;

&lt;p&gt;Mutation testing automates variations of this idea by introducing changes into the code and checking which tests detect them. Tools such as &lt;a href="https://stryker-mutator.io/docs/" rel="noopener noreferrer"&gt;Stryker&lt;/a&gt; make that practical without inventing a mutation framework for each project.&lt;/p&gt;

&lt;p&gt;A detected mutation establishes sensitivity to that change. It doesn't establish the truth of the original requirement. An incorrect expected value can still kill mutants; a surviving mutant can reflect equivalent behavior rather than a meaningful defect. Mutation scores need interpretation, not ceremonial targets.&lt;/p&gt;

&lt;p&gt;Property-based tests add another useful angle. Under our stated policy, increasing the discount while holding the merchandise subtotal fixed must not turn an ineligible order into an eligible one. This describes a relationship across inputs instead of one fixed example.&lt;/p&gt;

&lt;p&gt;But a function that always returns false also satisfies that relationship. Properties need enough independent constraints to rule out plausible wrong implementations. They complement concrete examples; they don't manufacture a business rule from nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixtures can make the same mistake less visible
&lt;/h2&gt;

&lt;p&gt;I would also inspect how test data is created. A fixture built by calling the implementation under test can quietly recycle the result it is supposed to check. A broad mock can remove the behavior that actually needs verification.&lt;/p&gt;

&lt;p&gt;This doesn't make builders or mocks inherently bad. A builder can provide ordinary input data while leaving the important expected result explicit. A mock can isolate a collaborator without deciding the business outcome for the test.&lt;/p&gt;

&lt;p&gt;The question is what the helper owns. Does it simplify setup, or does it calculate the answer through the same logic the assertion claims to validate?&lt;/p&gt;

&lt;p&gt;Duplicating the production algorithm inside the test is not necessarily a better oracle. It can reproduce the same defect in another file. For a small example, independently calculated values may be easier to audit. For complex behavior, a reviewed reference implementation, contract examples or another representation may be appropriate.&lt;/p&gt;

&lt;p&gt;There isn't one universally independent source. The point is to identify the dependence instead of mistaking a second file for a second line of reasoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review the test change, not just its result
&lt;/h2&gt;

&lt;p&gt;When an agent fixes a failing suite, I want to know whether it changed the behavior or changed what the suite accepts.&lt;/p&gt;

&lt;p&gt;Sometimes the expected result is genuinely obsolete because the requirement changed. Sometimes the implementation is wrong. Sometimes the test was wrong from the beginning. All three can end with green CI. They are not the same engineering decision.&lt;/p&gt;

&lt;p&gt;A snapshot update deserves the same question. Accepting a new snapshot records an output; it doesn't establish that the user should see it. Removing an assertion or relaxing a matcher may be justified, but the justification needs more than getting the run to pass.&lt;/p&gt;

&lt;p&gt;For a bug fix, I would prefer the regression test to demonstrate the reported failure on the relevant prior implementation, then pass with the correction. It also needs to fail for the intended reason, not because an unrelated dependency or import is broken.&lt;/p&gt;

&lt;p&gt;For new behavior, a failing test against the previous implementation is expected. What matters is that its assertion comes from the requested behavior, not from whichever output the new implementation happened to produce.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep generation useful
&lt;/h2&gt;

&lt;p&gt;I like the prospect of an agent handling repetitive setup, exploring input combinations and proposing edge cases. Those are useful contributions even when the final expectation still needs human judgment.&lt;/p&gt;

&lt;p&gt;What I don't want is to promote the existence of generated tests into evidence that the requirement has been independently checked. More assertions can make a mistaken assumption look thoroughly documented.&lt;/p&gt;

&lt;p&gt;The shipping example is small enough that the disagreement fits in one subtraction. Real systems hide the same question behind fixtures, collaborators and years of existing behavior. I would still start by asking who decided the answer and what supports it.&lt;/p&gt;

&lt;p&gt;If you use agents to write tests, how do you keep expected outcomes independent of the implementation? I'd be interested in the checks that expose shared assumptions, especially when both the code and its tests look completely reasonable.&lt;/p&gt;

</description>
      <category>aiagents</category>
      <category>testing</category>
      <category>codereview</category>
      <category>engineeringworkflow</category>
    </item>
    <item>
      <title>Independent Releases Still Need Compatible Neighbors</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Thu, 22 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/independent-releases-still-need-compatible-neighbors-3lh2</link>
      <guid>https://dev.to/maximusft/independent-releases-still-need-compatible-neighbors-3lh2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh81u0qmew3f7z6ucw6iu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh81u0qmew3f7z6ucw6iu.png" alt="Independent Releases Still Need Compatible Neighbors" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The account team releases its new frontend. The shell stays on the previous version. Checkout was updated yesterday.&lt;/p&gt;

&lt;p&gt;That can be a healthy arrangement. It is what independent deployment is meant to permit.&lt;/p&gt;

&lt;p&gt;It is also a compatibility problem. Those versions need to work together, and users will discover the combinations we did not consider while each team tested its own application.&lt;/p&gt;

&lt;p&gt;The earlier &lt;a href="https://ma-x.im/blog/react-playbook-micro-frontends-org-chart" rel="noopener noreferrer"&gt;micro-frontends article&lt;/a&gt; asks whether organizational independence justifies the split. Here I want to examine the technical consequence after that decision: what independence requires during ordinary releases and rollbacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate three kinds of boundary
&lt;/h2&gt;

&lt;p&gt;A code boundary determines which module can import another. An ownership boundary determines who may change it. A deployment boundary determines which artifact can be released without rebuilding the others.&lt;/p&gt;

&lt;p&gt;They can align, but they do not have to.&lt;/p&gt;

&lt;p&gt;A modular frontend can have feature packages, explicit APIs, separate owners, and enforced import rules while producing one application build. That is the modular monolith in this comparison, not a claim that all code belongs in one undifferentiated folder.&lt;/p&gt;

&lt;p&gt;Micro-frontends add independently deployed application artifacts, composed through routes, runtime loading, frames, or another integration mechanism. Different composition methods have different costs. An iframe provides a stronger browser isolation boundary than mounting two modules in the same JavaScript runtime; it also changes interaction and integration constraints.&lt;/p&gt;

&lt;p&gt;I would name the intended composition before discussing the benefits. "Micro-frontends" is otherwise doing too much work in the sentence.&lt;/p&gt;

&lt;h2&gt;
  
  
  One build moves compatibility work earlier
&lt;/h2&gt;

&lt;p&gt;In a modular monolith, one build checks the selected package versions together. A failing interface change can stop the release before production sees it. A coordinated rollback returns that tested set of frontend modules together.&lt;/p&gt;

&lt;p&gt;That does not guarantee correctness. Old tabs still exist, backend APIs still evolve, and integration tests can miss a workflow. But the frontend's internal version combination is more constrained.&lt;/p&gt;

&lt;p&gt;With independent artifacts, compatibility work remains necessary and moves partly into runtime and release policy. The shell needs to understand the remote's contract; the remote needs to tolerate the supported shell versions.&lt;/p&gt;

&lt;p&gt;The work did not disappear because CI pipelines became separate. We changed where it is paid.&lt;/p&gt;

&lt;h2&gt;
  
  
  A remote needs a supported contract
&lt;/h2&gt;

&lt;p&gt;An illustrative mount contract might include a version, capabilities, lifecycle, and a constrained way to communicate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;AccountModuleContract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AccountContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;capabilities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;readonly &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notification-settings&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shape is not a recommended universal micro-frontend API. It shows the questions a boundary needs to answer: what does the host provide, what may the remote assume, how does it clean up, and how can the host detect incompatibility?&lt;/p&gt;

&lt;p&gt;Do not make shared context an unrestricted store containing every application's internals. That turns the mount API into a distributed import path with weaker verification.&lt;/p&gt;

&lt;p&gt;Capabilities can make additive evolution easier than assuming that every participant upgrades simultaneously. For breaking changes, define a support window and migration path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Release independence creates version combinations
&lt;/h2&gt;

&lt;p&gt;If several remotes each support two versions while the shell also supports two, the possible combinations multiply. It is rarely practical to test every theoretical combination equally.&lt;/p&gt;

&lt;p&gt;Constrain the supported matrix. Test each remote against the current shell and the declared compatibility window. Keep representative whole-product flows that cross the important boundaries.&lt;/p&gt;

&lt;p&gt;A remote's unit tests may correctly show that its save action works. They do not show that the shell refreshes the account menu, preserves navigation, and clears the right state after logout.&lt;/p&gt;

&lt;p&gt;Contract tests help, but a contract can be structurally valid and behaviorally wrong. The few shared workflows deserve integration tests owned by someone, not by an imaginary team named "the platform."&lt;/p&gt;

&lt;h2&gt;
  
  
  Runtime manifests are release artifacts
&lt;/h2&gt;

&lt;p&gt;If the shell loads a remote entry through a mutable URL, the deployed composition can change without the shell's commit changing.&lt;/p&gt;

&lt;p&gt;Record the selected remote versions or immutable asset references. Keep enough history to reconstruct what users were served. Rollback should select a known-compatible composition, not point several URLs at yesterday and hope.&lt;/p&gt;

&lt;p&gt;Asset retention matters for clients that already loaded an old entry. Removing the old chunks immediately can break lazy navigation later, long after the initial page load succeeded.&lt;/p&gt;

&lt;p&gt;CDN cache lifetimes can also cause different users to load different manifest versions. This is manageable if the contracts support overlap. It is inconvenient if independent deployment silently assumes instantaneous global consistency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sharing dependencies exchanges one cost for another
&lt;/h2&gt;

&lt;p&gt;Shipping separate dependencies can increase download size and produce multiple copies of libraries. Sharing them at runtime can reduce duplication, but introduces version negotiation and lifecycle constraints.&lt;/p&gt;

&lt;p&gt;React singletons deserve care when components and hooks interact across a shared runtime. A shared design-system library also has behavioral and styling contracts; two versions can differ in focus management or portal assumptions even when the buttons look similar.&lt;/p&gt;

&lt;p&gt;I would not force every dependency into a singleton merely to improve a bundle report. Nor would I accept uncontrolled duplication without measuring the user cost. Decide which shared dependencies are part of the platform contract, and verify both upgrades and rollbacks.&lt;/p&gt;

&lt;p&gt;For stronger isolation, route-level composition may be more straightforward than many independently loaded widgets sharing one screen. It depends on the product flow, not on which demo looked most flexible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolation needs failure behavior
&lt;/h2&gt;

&lt;p&gt;A remote can fail to load because of a network error, stale asset reference, or incompatible deployment. The shell still needs a useful route and a recoverable state.&lt;/p&gt;

&lt;p&gt;Distinguish an optional sidebar from checkout's payment step. One may show a fallback. The other may need to stop the workflow and preserve user input. An error boundary catches some rendering failures; it is not full isolation from CSS conflicts, shared global state, or security problems.&lt;/p&gt;

&lt;p&gt;Keep remote-loading timeouts, telemetry, retry rules, and fallback ownership explicit. A spinner with no deadline is not a graceful degradation strategy.&lt;/p&gt;

&lt;p&gt;The modular monolith has fewer runtime composition failure points, but its deployment can affect more features at once. Feature flags, staged releases, and modular tests can reduce that risk without creating separate runtime applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared state is an authority question
&lt;/h2&gt;

&lt;p&gt;Identity, cart state, locale, and navigation often cross frontend boundaries.&lt;/p&gt;

&lt;p&gt;Decide who owns each truth. An event that says "cart changed" can prompt other applications to read the authoritative value. An event carrying a partial cart snapshot can accidentally create another source of truth with its own freshness problems.&lt;/p&gt;

&lt;p&gt;An event bus should have typed contracts, lifecycle rules, and unsubscribe behavior. It should not become an excuse for every remote to discover undocumented events by reading the others' source.&lt;/p&gt;

&lt;p&gt;Authorization must remain enforced at the backend. A remote being mounted by an authenticated shell does not give its API calls permanent authority.&lt;/p&gt;

&lt;p&gt;These rules apply inside a modular monolith too. Independent deployment makes violations harder to repair together, which raises the value of keeping the shared surface small.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try modularity before distributing a coordination problem
&lt;/h2&gt;

&lt;p&gt;If the main pain is accidental imports, unclear ownership, or slow whole-repo CI, a modular build with boundary rules and affected-project checks may address it directly.&lt;/p&gt;

&lt;p&gt;If teams genuinely need separate release schedules, existing applications cannot reasonably be merged, or one part must evolve under substantially different constraints, runtime composition may justify its cost.&lt;/p&gt;

&lt;p&gt;I would trial the split at a boundary already understandable in the product, with a specific blocked workflow the trial is meant to improve. Measure release lead time and integration effort, then account for the platform work needed to keep it reliable.&lt;/p&gt;

&lt;p&gt;A module boundary that cannot be described cleanly inside one build usually does not become clearer when a network load is inserted between its parts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Independence has a maintenance agreement
&lt;/h2&gt;

&lt;p&gt;The decision is not simply one deployment versus many. It is how much coordination we want to perform before release and how much compatibility we are prepared to maintain afterward.&lt;/p&gt;

&lt;p&gt;I would choose a modular monolith when coordinated artifacts are affordable and the team's main need is better boundaries. I would choose micro-frontends when independent delivery solves a demonstrated constraint and the teams can own the resulting compatibility work.&lt;/p&gt;

&lt;p&gt;Either arrangement can be maintained well. Neither relieves us of agreeing what a neighboring module may do while we are deploying something else.&lt;/p&gt;

&lt;p&gt;If your teams already release independently, what happens when one of them rolls back? I'd be interested in the supported combination, because that answer says more about the architecture than the number of repositories.&lt;/p&gt;

</description>
      <category>react</category>
      <category>architecture</category>
      <category>microfrontends</category>
      <category>modularmonolith</category>
    </item>
    <item>
      <title>The Agent Was Right. The Scope Still Changed.</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Wed, 21 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/the-agent-was-right-the-scope-still-changed-41kj</link>
      <guid>https://dev.to/maximusft/the-agent-was-right-the-scope-still-changed-41kj</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbtpixvwhplebvef1rrjc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbtpixvwhplebvef1rrjc.png" alt="The Agent Was Right. The Scope Still Changed." width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A colleague started working on his ticket and discovered that its implementation was already there. He traced the files back to my pull request.&lt;/p&gt;

&lt;p&gt;I hadn't found a technical problem with the additional work. The awkward part was explaining how it had become part of my task.&lt;/p&gt;

&lt;p&gt;My ticket introduced a new abstraction, which I'll call a model. Another task covered integrating it at three selected usage sites. The older implementation served other consumers and needed to remain.&lt;/p&gt;

&lt;p&gt;The agent built the model and covered it with tests. Then it noticed that the model wasn't being used. The task description explained what it would eventually replace, and the agent identified the places where it could be connected.&lt;/p&gt;

&lt;p&gt;That was a reasonable suggestion. I accepted the argument and let it continue.&lt;/p&gt;

&lt;p&gt;The integration was good work. It also belonged to another ticket.&lt;/p&gt;

&lt;p&gt;This wasn't an agent secretly editing forbidden files. It asked, and I agreed. That makes the case more interesting than a story about automation ignoring instructions. Human agreement was present. What was missing was an explicit reconciliation between that agreement and the way the work had been divided.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The agent was right about what came next. That didn't establish that it belonged in this PR.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Unused is not the same as unfinished
&lt;/h2&gt;

&lt;p&gt;A tested abstraction waiting for its integration task can look like incomplete engineering when viewed only through the current repository.&lt;/p&gt;

&lt;p&gt;The code suggests an obvious next step. The ticket boundary may say something different.&lt;/p&gt;

&lt;p&gt;That boundary isn't automatically sacred. Tasks can be split poorly. Combining implementation and integration may be the better decision. But it should be a deliberate change to the plan, with the affected people aware of it, not an accidental consequence of a convincing technical explanation.&lt;/p&gt;

&lt;p&gt;I wouldn't require product approval for every extracted helper. Engineers need room to make implementation decisions. The useful distinction is between supporting work necessary to satisfy the current acceptance criteria and work that delivers a separately planned behavior.&lt;/p&gt;

&lt;p&gt;An additional compatibility fix might be necessary for the requested change to function. Integrating a new model into consumers assigned to another task is a different decision. Both can be technically justified. Only one follows automatically from the current task's goal.&lt;/p&gt;

&lt;p&gt;Knowing the intended destination is not the same as owning the next step.&lt;/p&gt;

&lt;p&gt;This isn't unique to AI. A human engineer can make the same choice. But an agent can provide both the persuasive argument and the implementation. I need to examine the transition between those two, not only the quality of the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  I started making the origin of decisions visible
&lt;/h2&gt;

&lt;p&gt;My response was not another permanent instruction saying never do anything extra. That would make the agent less useful without resolving the ambiguity.&lt;/p&gt;

&lt;p&gt;Instead, I made a distinction in the task records: work grounded in requirements, documentation, repository instructions or acceptance criteria, versus additions originating in the agent's own engineering judgment.&lt;/p&gt;

&lt;p&gt;The latter should be presented as a proposal or inference, not quietly described as required work.&lt;/p&gt;

&lt;p&gt;Both I and the review agent can inspect that record. It gives us somewhere to look when a change is sensible but its relationship to the task is unclear.&lt;/p&gt;

&lt;p&gt;The important difference is between stating that a documented requirement calls for a change and stating that the agent recommends it because the current implementation appears incomplete. Those explanations deserve different review questions.&lt;/p&gt;

&lt;p&gt;Of course, the agent can misclassify its own reasoning. A documentation reference may describe a future direction rather than a current requirement. A record written by the implementer is an account to examine, not independent evidence that everything happened correctly.&lt;/p&gt;

&lt;p&gt;The reviewer needs the original task and relevant sources, not just the implementer's summary. It also needs to compare that account with the actual changes. Otherwise, two agents may agree because they inherited the same assumption.&lt;/p&gt;

&lt;p&gt;For substantial work, this record can preserve decisions, checks, open questions and work intentionally left outside the task. A tiny, clear change doesn't necessarily need another specification file.&lt;/p&gt;

&lt;p&gt;I've described the broader &lt;a href="https://ma-x.im/blog/agent-playbook-do-it-as-usual" rel="noopener noreferrer"&gt;task-to-PR workflow&lt;/a&gt; elsewhere. Jira, Confluence, repository instructions, Git history and API documentation can be available through MCP integrations and other tools. Access helps only if the sources are current and their authority is understood. More context can also mean more convincing outdated instructions.&lt;/p&gt;

&lt;p&gt;I want the record to make disagreement easier to locate. I don't want an impressive document that makes disagreement harder.&lt;/p&gt;

&lt;h2&gt;
  
  
  A good review needs several kinds of evidence
&lt;/h2&gt;

&lt;p&gt;My &lt;a href="https://ma-x.im/blog/github-ai-pr-reviewer" rel="noopener noreferrer"&gt;personal PR-reviewer article&lt;/a&gt; focused on specific, checkable comments and visibility into what the tool inspected. That remains useful engineering attention. A removed export or disappearing permission check deserves investigation, not an unexplained warning.&lt;/p&gt;

&lt;p&gt;But a reviewer can correctly assess an implementation and still miss why that implementation is in the PR.&lt;/p&gt;

&lt;p&gt;Tests address particular behaviors under particular conditions. A local TypeScript check doesn't establish compatibility with a downstream consumer whose actual package contract differs. As I argued in &lt;a href="https://ma-x.im/blog/agent-playbook-green-checks" rel="noopener noreferrer"&gt;Green Checks Only Cover What You Checked&lt;/a&gt;, the question is what the check exercised, not merely whether it passed.&lt;/p&gt;

&lt;p&gt;Automation can change the object being reviewed too. My &lt;a href="https://ma-x.im/blog/agent-playbook-scope-after-tools" rel="noopener noreferrer"&gt;scope-after-tools article&lt;/a&gt; uses a synthetic dependency update where a hook regenerates unrelated API artifacts. The generator succeeds; the resulting commit still needs inspection. That example is illustrative, not a second incident from the model-integration story.&lt;/p&gt;

&lt;p&gt;Review evidence also expires. A conclusion about one revision may no longer describe the next. &lt;a href="https://ma-x.im/blog/agent-playbook-review-belongs-to-commit" rel="noopener noreferrer"&gt;A Review Belongs to a Commit&lt;/a&gt; examines revision tracking and guarded actions in personal tooling I've developed. Remembering a SHA helps identify what was inspected; it doesn't prove every finding remains valid or turn an earlier approval into authority over later changes.&lt;/p&gt;

&lt;p&gt;These aren't interchangeable checks. Code correctness, dependency compatibility, task inclusion, action permissions and the relevance of evidence each answer a different question.&lt;/p&gt;

&lt;p&gt;A passing test doesn't authorize extra work. An allowed directory doesn't define the business requirement. A second model's agreement doesn't establish independent verification.&lt;/p&gt;

&lt;p&gt;Nor should every small edit trigger an investigation across every connected repository. The validation needs to follow the affected contract and the decision being made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three conversations around different parts of the problem
&lt;/h2&gt;

&lt;p&gt;During October, three groups contacted me after reading my articles. The useful connection was their different approaches to questions I was already trying to answer.&lt;/p&gt;

&lt;p&gt;In an early-October exchange with &lt;a href="https://kaicontext.com/" rel="noopener noreferrer"&gt;Kai&lt;/a&gt;, we discussed code relationships: imports, exports, calls, and how a finding might be challenged rather than immediately published. We also discussed limits of static analysis around runtime behavior and some React relationships. That is an account of the conversation, not a specification of today's product.&lt;/p&gt;

&lt;p&gt;I proposed an evaluation with expected defects recorded before running the reviewer, without revealing the answers in the PR descriptions. Cross-file regressions, contract changes, React behavior and false positives would make useful cases. That evaluation was discussed, not completed.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.deeppattern.ai/en/preview/overview" rel="noopener noreferrer"&gt;DeepPattern&lt;/a&gt; conversation approached the problem through verification: missed requirements, untested assumptions and whether the available evidence supports a conclusion. It also touched attribution. If a task succeeds, was the useful contribution a reusable skill, connected documentation, an existing test, or a human correction? Without a meaningful comparison, I can't isolate the cause. A preview was offered; I am not reporting evaluation results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/suirindo/agent-role-contracts" rel="noopener noreferrer"&gt;Agent Role Contracts&lt;/a&gt;, from Netsujo, addresses explicit declarations of roles, scope and handoffs. Its documentation makes an important boundary clear: internally consistent declarations do not grant runtime authority, authenticate a reviewer or establish business acceptance.&lt;/p&gt;

&lt;p&gt;A task requesting writes outside a declared scope can be rejected before execution. My model-integration example asks a different question: what if every edited file is permitted, but the work belongs to another task?&lt;/p&gt;

&lt;p&gt;These are complementary directions, not three products I've ranked. Code relationships, verification evidence and declared authority all matter. None alone decides whether a technically sensible addition belongs in this particular PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Move the scope question earlier, without pretending it is solved
&lt;/h2&gt;

&lt;p&gt;By PR review, a disputed decision already has an implementation. The code can make the proposed extension look settled, even when the reason for including it remains uncertain.&lt;/p&gt;

&lt;p&gt;I would like to make that uncertainty visible before implementation: compare the proposed work with the original goal, identify additions, and decide which ones require coordination. Then compare the actual result with the accepted scope.&lt;/p&gt;

&lt;p&gt;That is a direction to investigate, not a semantic scope checker I've completed. Requirements can be ambiguous. Plans can omit necessary work. The reviewer can share the implementer's blind spot. A real change in understanding may justify revising the plan.&lt;/p&gt;

&lt;p&gt;I would evaluate a mechanism like this on cases where the right response differs. One task genuinely requires a supporting change. Another should produce a suggestion to do the integration separately. A third needs clarification because the requirement doesn't settle the choice.&lt;/p&gt;

&lt;p&gt;The expected outcome has to include stopping or separating work, not just producing more code. Otherwise, the evaluation rewards the very behavior it is supposed to examine.&lt;/p&gt;

&lt;p&gt;I also wouldn't ask an agent for an elaborate account of its internal thoughts. I need inspectable grounds: which requirement it relied on, what it inferred, what it changed, and what the checks actually support.&lt;/p&gt;

&lt;p&gt;My colleague didn't uncover bad code. He uncovered work that had crossed a task boundary while still looking like sensible engineering. I had participated in that decision. The part I want to improve is how such a decision becomes visible before someone else discovers their task inside my PR.&lt;/p&gt;

&lt;p&gt;If you work on agent review, verification or workflow controls, how do you distinguish a necessary supporting change from an expansion that needs a separate decision? What evidence would you need to trust that the agent did the requested job, rather than a well-implemented neighboring one? I'd like to compare approaches, including where they fail.&lt;/p&gt;

</description>
      <category>aiagents</category>
      <category>codereview</category>
      <category>engineeringworkflow</category>
      <category>verification</category>
    </item>
    <item>
      <title>TanStack Start or Next.js: Follow One Mutation Through Production</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Tue, 20 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/tanstack-start-or-nextjs-follow-one-mutation-through-production-472a</link>
      <guid>https://dev.to/maximusft/tanstack-start-or-nextjs-follow-one-mutation-through-production-472a</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F79kvle9ocg59gamg013g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F79kvle9ocg59gamg013g.png" alt="TanStack Start or Next.js: Follow One Mutation Through Production" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A dashboard loads correctly in both frameworks. That part of the comparison is already fairly well understood.&lt;/p&gt;

&lt;p&gt;Now change an order, switch accounts, keep an old tab open through a deployment, and make the request through the production CDN.&lt;/p&gt;

&lt;p&gt;That is the comparison I would spend time on. The first screen tells us whether the framework can render. The later operations tell us whether the team understands the state and deployment model it has chosen.&lt;/p&gt;

&lt;p&gt;The earlier &lt;a href="https://ma-x.im/blog/react-playbook-ssr-tanstack-start" rel="noopener noreferrer"&gt;TanStack Start article&lt;/a&gt; introduces SSR and the server boundary. This one examines an authenticated, interaction-heavy application after that introduction. It is not a performance benchmark or a claim of personal production results for either framework.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version scope:&lt;/strong&gt; package metadata and official documentation were checked on October 8, 2026: &lt;code&gt;next&lt;/code&gt; 16.4.0 and &lt;code&gt;@tanstack/react-start&lt;/code&gt; 1.168.60. Features and host integrations below should be checked again against the project's pinned versions before implementation. This site itself still uses its existing Next.js version; writing the comparison does not upgrade it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare a workflow, not an API count
&lt;/h2&gt;

&lt;p&gt;Use one representative flow: load a private order, edit its delivery option, save, return to the list, and sign out.&lt;/p&gt;

&lt;p&gt;It exercises identity, server authorization, validation, durable state, multiple cached views, URL state, and browser cleanup. Add an old-client submission after a rolling deployment, and it also exercises release compatibility.&lt;/p&gt;

&lt;p&gt;I would build that slice with the deployment target intended for production. A development server is too forgiving a witness for cache behavior and runtime bindings.&lt;/p&gt;

&lt;p&gt;The result need not be a second full application. It needs enough ordinary inconvenience to reveal which model the team can explain.&lt;/p&gt;

&lt;h2&gt;
  
  
  The center of gravity is different
&lt;/h2&gt;

&lt;p&gt;Next.js App Router organizes work around route segments, layouts, Server Components, client boundaries, and its rendering and caching model. That is useful when much of the route can be composed on the server and the team wants the framework to own those conventions.&lt;/p&gt;

&lt;p&gt;TanStack Start builds around TanStack Router, loaders, server functions, and the associated client navigation model. That is useful when typed route/search state and client-rich workflows are already central to the application.&lt;/p&gt;

&lt;p&gt;Neither description is an exclusive capability boundary. Start's current documentation also describes Server Components; I would not use "Start cannot do RSC" as a timeless reason to choose Next. Nor does a Next.js application forbid TanStack Query or carefully designed client state.&lt;/p&gt;

&lt;p&gt;The question is which default model makes the particular workflow easier for this team to reason about, and which extensions create a second overlapping model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server functions still need an API boundary
&lt;/h2&gt;

&lt;p&gt;In either system, a function that runs on the server can feel like a local call from frontend code. That convenience does not make the request trusted.&lt;/p&gt;

&lt;p&gt;Validate input, authenticate the caller, check access to the specific order, and enforce idempotency where repeated writes matter. A protected page or route guard improves navigation; it does not replace checks in the separately callable mutation endpoint.&lt;/p&gt;

&lt;p&gt;For Start, the current &lt;a href="https://tanstack.com/start/latest/docs/framework/react/guide/server-functions" rel="noopener noreferrer"&gt;server-function documentation&lt;/a&gt; describes compilation to client RPC stubs, validation, middleware, and same-origin protections. Next's Server Functions also need explicit authorization in the data path.&lt;/p&gt;

&lt;p&gt;I would test both flows by calling the endpoint while signed out and as another account. The implementation syntax differs. The rejected unauthorized write should not.&lt;/p&gt;

&lt;p&gt;Keep external APIs separate from framework-private RPC assumptions. Mobile clients and third-party integrations need a deliberately supported contract, not an incidental generated function identifier.&lt;/p&gt;

&lt;h2&gt;
  
  
  A successful mutation can leave several stale views
&lt;/h2&gt;

&lt;p&gt;After saving the order, which copy changes?&lt;/p&gt;

&lt;p&gt;In a Start application using Query, there may be a query cache, router loader data, server-side data caches, and a CDN response. Invalidating one does not automatically invalidate every other layer.&lt;/p&gt;

&lt;p&gt;In a Next application, server data and route output can have their own cache behavior, while the browser retains navigation state and perhaps a separate Query cache. Adding Query is reasonable when it serves a clear purpose. Using it merely because it is familiar can create two owners for the same remote data.&lt;/p&gt;

&lt;p&gt;I would write down the expected invalidation path before selecting helper functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;save delivery option
  -&amp;gt; commit the order change
  -&amp;gt; update or invalidate the detail view
  -&amp;gt; refresh affected list representations
  -&amp;gt; preserve unrelated local form state

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Next 16, be explicit about whether the application uses Cache Components or the previous caching model. Advice copied from a different major version or mode may describe different defaults. The &lt;a href="https://nextjs.org/docs/app/guides/caching" rel="noopener noreferrer"&gt;current caching guide&lt;/a&gt; distinguishes those paths.&lt;/p&gt;

&lt;p&gt;I would not choose a framework because its cache seems invisible. Invisible is convenient until two views disagree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Request isolation matters more than friendly types
&lt;/h2&gt;

&lt;p&gt;On the server, create user-specific state in request scope. A process-wide Query client or mutable user store can accidentally carry account data between requests if used incorrectly.&lt;/p&gt;

&lt;p&gt;Test two accounts concurrently through SSR and the real CDN. Inspect returned HTML and serialized data, then switch accounts in the same browser. Sign-out should remove private client cache state as well as the cookie.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://tanstack.com/start/latest/docs/framework/react/guide/production-checklist" rel="noopener noreferrer"&gt;Start production checklist&lt;/a&gt; explicitly addresses these checks. They are useful for either framework.&lt;/p&gt;

&lt;p&gt;A type-safe cache key still needs the correct identity dimensions. If two tenants share the same key, the compiler can happily confirm that the wrong tenant's response has the expected shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hosting is part of the choice
&lt;/h2&gt;

&lt;p&gt;Start's &lt;a href="https://tanstack.com/start/latest/docs/framework/react/guide/hosting" rel="noopener noreferrer"&gt;hosting documentation&lt;/a&gt; describes provider-specific integrations and build outputs. Next's &lt;a href="https://nextjs.org/docs/app/guides/self-hosting" rel="noopener noreferrer"&gt;self-hosting documentation&lt;/a&gt; describes multi-instance caches, deployment identifiers, Server Function encryption keys, and streaming considerations.&lt;/p&gt;

&lt;p&gt;Both require attention outside the route code. Verify the adapter, runtime APIs, environment-variable timing, asset paths, and proxy buffering. A container deployment and an edge-worker deployment are not interchangeable merely because both serve HTTP.&lt;/p&gt;

&lt;p&gt;For Next across multiple instances, plan shared cache behavior and invalidation coordination where needed. For Start, verify the selected server output and host bindings rather than assuming the development runtime is the production runtime.&lt;/p&gt;

&lt;p&gt;Do not judge self-hosting by whether &lt;code&gt;npm start&lt;/code&gt; returned a page once. Judge whether the intended features behave correctly through the intended infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep an old browser alive during the test
&lt;/h2&gt;

&lt;p&gt;Server-function identifiers and client assets belong to a build. A tab can retain an older build while the server deploys a newer one.&lt;/p&gt;

&lt;p&gt;Next documents deployment skew protections, including deployment identifiers; their exact behavior matters for self-hosting. Start also generates server-function identities, so test old-client calls against the actual deployed output rather than assuming type sharing guarantees runtime compatibility.&lt;/p&gt;

&lt;p&gt;Retain required immutable assets. Decide whether an incompatible client should reload, and what happens to unsaved edits when it does. A full reload is a recovery mechanism, not a product-neutral event.&lt;/p&gt;

&lt;p&gt;This check can matter more to an internal editing application than the difference in a clean first-load demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Include maintenance in the experiment
&lt;/h2&gt;

&lt;p&gt;Ask another engineer to change the saved field, add a validation failure, and diagnose a controlled stale-view bug in each slice.&lt;/p&gt;

&lt;p&gt;How much behavior can they find locally? Which conventions are familiar to the team? Are the deployment docs and libraries they depend on compatible with the pinned versions? Can they explain the cache lifecycle without relying on the person who built the example?&lt;/p&gt;

&lt;p&gt;I would prefer this evidence to a general claim that one framework is simpler. Simplicity depends on the workflow and on what the team already understands.&lt;/p&gt;

&lt;p&gt;For server-composed routes and a team committed to the App Router model, Next is a reasonable choice. For router-driven, interaction-heavy work with a strong TanStack investment, Start is a reasonable choice. Either can be made awkward by layering on another system without deciding who owns what.&lt;/p&gt;

&lt;p&gt;The framework I would choose is the one whose unhappy production path the team can describe clearly. A nice dashboard matters too. Fortunately, both can make one.&lt;/p&gt;

&lt;p&gt;If you're weighing the two, bring one mutation and the hosting target rather than a feature matrix. I'd be interested in where the ownership of data becomes unclear in that concrete path.&lt;/p&gt;

</description>
      <category>react</category>
      <category>tanstackstart</category>
      <category>nextjs</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Freelance Architect or Agency: Who Keeps the Decisions?</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Sun, 18 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/freelance-architect-or-agency-who-keeps-the-decisions-454m</link>
      <guid>https://dev.to/maximusft/freelance-architect-or-agency-who-keeps-the-decisions-454m</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9wefu3zufkrbd89usqua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9wefu3zufkrbd89usqua.png" alt="Freelance Architect or Agency: Who Keeps the Decisions?" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A team asks for an architect, but the work waiting for them is a backlog of implementation tickets.&lt;/p&gt;

&lt;p&gt;Another asks an agency to build a feature, while every consequential decision still needs approval from an internal team that has no time to review it.&lt;/p&gt;

&lt;p&gt;Neither arrangement is necessarily wrong. They are simply describing a different purchase from the one in the proposal.&lt;/p&gt;

&lt;p&gt;When choosing between an independent engineer and an agency, I would spend less time comparing job titles and more time describing who owns the decisions while the work is happening. That tends to matter after the first few meetings, when everyone has access and the easy questions have been answered.&lt;/p&gt;

&lt;p&gt;This is a way to evaluate an engagement, not a claim about particular suppliers, prices, or a universal ranking of one model over the other.&lt;/p&gt;

&lt;h2&gt;
  
  
  First separate diagnosis from capacity
&lt;/h2&gt;

&lt;p&gt;Sometimes the team knows what it needs to build and lacks enough delivery capacity. Sometimes it has plenty of developers but cannot explain why every change crosses five modules. Sometimes a deadline exposes both problems at once.&lt;/p&gt;

&lt;p&gt;An architecture-focused independent engagement can make sense when the central work is concentrated judgement: inspect a system, identify boundaries, work with the internal team, and make a few consequential changes.&lt;/p&gt;

&lt;p&gt;An agency can make sense when the work needs a coordinated mix of implementation, testing, design, delivery management, and continuity across several people.&lt;/p&gt;

&lt;p&gt;Those are tendencies, not guarantees. An independent engineer may deliver a complete feature; an agency may provide one specialist. The actual assigned people and operating agreement matter more than the supplier category.&lt;/p&gt;

&lt;p&gt;I would write the first outcome in plain terms. "Reduce the number of modules needed to change policy validation" is more testable than "improve architecture." "Own delivery of this workflow through acceptance and handover" is clearer than "provide a frontend team."&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsibility needs corresponding authority
&lt;/h2&gt;

&lt;p&gt;If an external architect is responsible for quality but cannot change boundaries, influence sequencing, or obtain review decisions, the responsibility is mostly ceremonial.&lt;/p&gt;

&lt;p&gt;The opposite arrangement is also uncomfortable: an external team makes choices that the internal owners must maintain, without involving them until handover.&lt;/p&gt;

&lt;p&gt;For decisions with lasting consequences, agree who proposes, who approves, and who maintains. This does not need an elaborate governance document. A small record can be enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Decision: separate payment validation from page orchestration
Proposed by: external engineer
Approved by: internal payments owner
Maintained by: payments team
Evidence: two representative flows and regression tests
Fallback: keep the old adapter during migration

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example is hypothetical. Its useful property is that someone still owns the result after the external person's last invoice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Review availability limits delivery
&lt;/h2&gt;

&lt;p&gt;Adding implementation capacity does not increase the internal team's review or decision capacity automatically.&lt;/p&gt;

&lt;p&gt;If an agency submits ten pull requests a week and the internal team can carefully review three, work accumulates at the boundary. More developers may increase that queue rather than shorten the release.&lt;/p&gt;

&lt;p&gt;An independent engineer working on a difficult architectural change can encounter the same problem. One large refactor waiting for a busy owner is not inherently easier to absorb than several ordinary features.&lt;/p&gt;

&lt;p&gt;I would include reviewer availability in the plan: expected turnaround, who can make product decisions, when integration questions get resolved, and how work is split into changes the team can evaluate.&lt;/p&gt;

&lt;p&gt;This is particularly important when acceptance depends on integrations the supplier cannot access or change. A delivery date that assumes immediate internal answers is a date with an unstated dependency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prefer demonstrated uncertainty over polished certainty
&lt;/h2&gt;

&lt;p&gt;Before a substantial commitment, a small paid diagnostic or bounded delivery slice can reveal the working relationship.&lt;/p&gt;

&lt;p&gt;Choose something representative rather than conveniently isolated: a flow with an awkward API contract, an existing shared component, a realistic test requirement, and an internal reviewer.&lt;/p&gt;

&lt;p&gt;The useful output includes what was discovered, what changed, what remains uncertain, and which assumptions affect the next estimate. An apparently slower answer that identifies a dependency may be worth more than a confident schedule built without examining it.&lt;/p&gt;

&lt;p&gt;I would also distinguish an estimate for implementation from the time waiting on decisions, environments, and approvals. They belong in the same delivery discussion, but they are not the same kind of work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuity is a mechanism, not a headcount
&lt;/h2&gt;

&lt;p&gt;An independent engineer has a clear availability risk: one person may be absent or the engagement may end.&lt;/p&gt;

&lt;p&gt;An agency may offer replacement capacity. That does not guarantee the replacement already understands the system. A named specialist can leave; an account can be reassigned; context still has to transfer.&lt;/p&gt;

&lt;p&gt;Ask how continuity actually works. Which people have read the critical code? Where are decisions stored? Can another engineer deploy, reproduce an issue, and explain the outstanding risks without a private conversation with the original author?&lt;/p&gt;

&lt;p&gt;For both models, I would favor shared context in the client's systems, small decisions recorded near the code, and at least one internal engineer involved in consequential changes.&lt;/p&gt;

&lt;p&gt;Continuity becomes less fragile when it is exercised during delivery rather than promised in a final document.&lt;/p&gt;

&lt;h2&gt;
  
  
  The work should remain inside the client's control
&lt;/h2&gt;

&lt;p&gt;Source repositories, deployment accounts, domains, package ownership, and design assets need deliberate ownership. An engagement can finish with working software and still leave the client dependent on credentials or infrastructure controlled by the supplier.&lt;/p&gt;

&lt;p&gt;Use client-controlled repositories and appropriately scoped access where possible. Name any exception and the transfer procedure before it becomes necessary.&lt;/p&gt;

&lt;p&gt;The same applies to automation. If a supplier uses AI-assisted tooling, clarify permitted data handling, review expectations, generated-code responsibility, and what configuration belongs to the client. Faster implementation does not change who must verify the result or who may access private source and customer information.&lt;/p&gt;

&lt;p&gt;I would not equate a supplier's preferred toolchain with a requirement for the client to adopt it permanently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid a handover that only describes files
&lt;/h2&gt;

&lt;p&gt;A directory tour helps. It does not answer why a boundary exists, which alternatives were rejected, or what would break if the API changes.&lt;/p&gt;

&lt;p&gt;A useful handover includes the important decisions, reproducible checks, release and rollback steps, known limitations, and the first likely maintenance changes. Keep it proportionate; six understandable notes are better than a large template nobody can navigate.&lt;/p&gt;

&lt;p&gt;Have an internal engineer perform one change and one deployment before the engagement ends. The external person can assist, but should not quietly do every step that the exercise is intended to transfer.&lt;/p&gt;

&lt;p&gt;That is a more convincing ownership test than asking whether everyone has read the documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture needs an implementation consequence
&lt;/h2&gt;

&lt;p&gt;If the engagement is mostly architecture, the deliverables should still meet the code at some point.&lt;/p&gt;

&lt;p&gt;A dependency diagram can identify a problem. A bounded migration, representative slice, or working contract test shows whether the proposed boundary is usable. Without that contact, the design may be elegant while the team's practical cost remains unknown.&lt;/p&gt;

&lt;p&gt;Conversely, measuring only shipped tickets can discourage the diagnostic work needed to prevent the next expensive change. Agree which technical outcomes matter: fewer coupled changes, faster verification, clearer ownership, or an integration that no longer needs several teams to coordinate every edit.&lt;/p&gt;

&lt;p&gt;I would avoid treating diagrams and implementation as competing definitions of productive work. They should inform each other, with evidence appropriate to the risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose the arrangement that can leave well
&lt;/h2&gt;

&lt;p&gt;For a focused diagnosis with a capable internal team, I would often consider an independent senior engineer or architect. For a delivery stream needing several disciplines and coordinated capacity, I would consider an agency with named people and explicit ownership.&lt;/p&gt;

&lt;p&gt;If the organization has nobody available to own decisions, review changes, or maintain the result, neither category solves that absence by itself. The operating model needs attention before more external capacity arrives.&lt;/p&gt;

&lt;p&gt;The end of the engagement is a useful design constraint from the beginning. What should the internal team be able to do without asking the supplier? Which promises must remain true when a person changes?&lt;/p&gt;

&lt;p&gt;I would rather make those questions slightly awkward during selection than leave them until the final week. By then the software may be complete, and the ownership may still be under construction.&lt;/p&gt;

&lt;p&gt;If you're deciding between these arrangements, tell me which decision or delivery responsibility is currently unowned. That detail makes the comparison much more useful than the labels on the proposals.&lt;/p&gt;

</description>
      <category>engineeringleadershi</category>
      <category>architecture</category>
      <category>delivery</category>
      <category>workingwithteams</category>
    </item>
    <item>
      <title>What a Skill Changed, and What It Didn't</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Sat, 17 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/what-a-skill-changed-and-what-it-didnt-4ehe</link>
      <guid>https://dev.to/maximusft/what-a-skill-changed-and-what-it-didnt-4ehe</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ectkwzand6jta6d4ihc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ectkwzand6jta6d4ihc.png" alt="What a Skill Changed, and What It Didn't" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A task went well with a reusable skill enabled.&lt;/p&gt;

&lt;p&gt;It also had clear requirements, repository instructions, connected tools, a useful test, and an engineer who corrected an early assumption.&lt;/p&gt;

&lt;p&gt;Which part made the result better?&lt;/p&gt;

&lt;p&gt;I would not answer that from the final diff alone. The diff can establish what changed. It cannot, by itself, tell us which part of the workflow caused the change to be correct.&lt;/p&gt;

&lt;p&gt;I participate in evaluating reusable agent skills and refining how they are applied to ordinary engineering work. The interesting question is not whether the process produced a polished artifact. It is what observable contribution the skill made, what it cost, and what remains unknown.&lt;/p&gt;

&lt;p&gt;This article describes an evaluation approach. It does not report internal programme results, measurements, or a controlled comparison that has established a productivity gain.&lt;/p&gt;

&lt;h2&gt;
  
  
  A skill is one input among several
&lt;/h2&gt;

&lt;p&gt;A reusable skill packages instructions or a workflow. It may help discover context, plan a change, validate it, or handle review. It is not a separately trained model or an autonomous employee.&lt;/p&gt;

&lt;p&gt;Its contribution depends on what was already present.&lt;/p&gt;

&lt;p&gt;If repository rules already require a focused check immediately after an edit, a skill that repeats that instruction may add consistency, but it is not evidence that the check originated with the skill. If a connected tool supplies current requirements, the tool can explain why the agent avoided a stale assumption.&lt;/p&gt;

&lt;p&gt;The engineer's domain knowledge matters too. A person may notice that two services disagree, narrow the investigation, or reject an obsolete proposal. Leaving that correction out makes the skill look more independent than it was.&lt;/p&gt;

&lt;p&gt;I want the record to include those existing controls. Otherwise we are comparing a named framework with an imaginary workflow that has no useful practices of its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observe behavior before assigning credit
&lt;/h2&gt;

&lt;p&gt;The earlier &lt;a href="https://ma-x.im/blog/agent-playbook-evaluation-is-the-missing-loop" rel="noopener noreferrer"&gt;evaluation article&lt;/a&gt; discusses what to measure. Here the narrower question is which explanation the observations support.&lt;/p&gt;

&lt;p&gt;Use a deliberately illustrative record, not a real reporting form or an internal task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;Task:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;client&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;without&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;changing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;its&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;callers&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Observed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;behavior:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;agent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;checked&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;contract&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;before&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;editing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Existing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;control:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;repository&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;instructions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;also&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;require&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;check&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Correction:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;engineer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;identified&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;one&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;stale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;source&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Verified&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;outcome:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;retained&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;passes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;relevant&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;gates&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Skill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;contribution:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;may&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;have&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;reinforced&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;discovery;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;attribution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;unresolved&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Residual&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;risk:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;deployment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;compatibility&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;needs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;separate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;decision&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The conclusion is modest because the evidence is modest. That is not a failed evaluation. It is an evaluation that did not replace uncertainty with enthusiasm.&lt;/p&gt;

&lt;p&gt;If the skill visibly introduced a previously missing check, say so. If the task does not distinguish its effect from existing instructions, say that instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  A useful outcome is not always delivered code
&lt;/h2&gt;

&lt;p&gt;A cross-repository investigation can end with an obsolete PR being closed. An architecture task can produce a proposal with explicit assumptions for discussion. A session-handoff change can produce a clearer continuation scheme.&lt;/p&gt;

&lt;p&gt;Those outcomes have value. They are not interchangeable with a merged feature, an approved architecture, or guaranteed reproducibility.&lt;/p&gt;

&lt;p&gt;Describe the actual artifact and its decision state. A reviewable proposal is ready to evaluate; it is not production rollout. A documented handoff reduces reliance on conversation history; it does not establish identical behavior across models and people.&lt;/p&gt;

&lt;p&gt;In the supplied generalized experiences behind this series, recovery and refinement are part of the work. I would not remove the initial incomplete diagnosis simply because the final action was sensible.&lt;/p&gt;

&lt;p&gt;The sequence explains what the process learned. A cleaned-up success story explains much less.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate work from overhead without pretending overhead is worthless
&lt;/h2&gt;

&lt;p&gt;Implementation, framework setup, planning, repeated approvals, and reporting take different kinds of effort.&lt;/p&gt;

&lt;p&gt;A specification can prevent an expensive mistake. It can also repeat a small task's already clear requirements. Reporting can support honest evaluation. It can also consume time that should be counted rather than hidden.&lt;/p&gt;

&lt;p&gt;Keep normal engineering effort, framework overhead, and reporting effort distinguishable. Do not turn them into a single impressive number before understanding what each category contains.&lt;/p&gt;

&lt;p&gt;The classification will sometimes require judgement. A discussion that clarifies an ambiguous requirement is engineering work even if a framework prompted it. A template completed only to satisfy the framework is a different contribution.&lt;/p&gt;

&lt;p&gt;I would make that distinction visible rather than use it to prejudge whether the framework is good or bad.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tiny tasks do not need a retrospective specification
&lt;/h2&gt;

&lt;p&gt;For a small, clear change, the ticket and nearby contract may already be an adequate written requirement. A long specification can create another artifact to review without resolving a real uncertainty.&lt;/p&gt;

&lt;p&gt;For ambiguous, risky, or multi-session work, a plan and checkpoints before implementation can be useful. They capture assumptions while there is still time for them to guide the work.&lt;/p&gt;

&lt;p&gt;Do not write a specification afterwards and present it as evidence that the task followed specification-driven development. A retrospective note can explain the result, but it did not shape decisions that happened before it existed.&lt;/p&gt;

&lt;p&gt;This is a simple chronology rule. It prevents polished documentation from making the process look more formal than it actually was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not using a skill can be the proportionate choice
&lt;/h2&gt;

&lt;p&gt;An evaluation can tempt people to apply every available skill to every task so the record has plenty to discuss.&lt;/p&gt;

&lt;p&gt;That changes the thing being evaluated. We are no longer observing useful selection; we are imposing ceremony for evidence collection.&lt;/p&gt;

&lt;p&gt;Use a skill when it helps the task's current stage and risk. Record when a tiny or non-coding task offers limited evidence. Do not manufacture a repository-wide plan or another planning file after the fact to fill a reporting category.&lt;/p&gt;

&lt;p&gt;A good workflow should be able to say "not needed here" without that becoming an admission that the whole framework failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repeated success still has confounders
&lt;/h2&gt;

&lt;p&gt;Several tasks going well can suggest a useful pattern. It does not automatically establish a causal productivity improvement.&lt;/p&gt;

&lt;p&gt;Tasks differ in difficulty, familiarity, requirements, code quality, tools, models, and human involvement. An experienced engineer may become better at the domain during the same period the skills are introduced.&lt;/p&gt;

&lt;p&gt;Without an appropriate baseline and comparison, avoid percentages, cost savings, or defect-rate reductions. Task counts and green checks are observations, not impact metrics by themselves.&lt;/p&gt;

&lt;p&gt;Qualitative findings remain worthwhile: a missing boundary became explicit, a handoff had a clearer source of current decisions, or the process detected an unrelated generated change before review.&lt;/p&gt;

&lt;p&gt;Name them as observations. They do not need a fabricated multiplier to be interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the evaluation record separate from public storytelling
&lt;/h2&gt;

&lt;p&gt;An internal assessment may need task-level evidence, correction history, and reporting detail. A public article does not need to reproduce those artifacts.&lt;/p&gt;

&lt;p&gt;Use generalized, explicitly labelled composite examples. Remove internal identities, programme details, source snippets, links, counts and model policy. Do not attach an employer's name to an anonymized case merely because the employment record is already public.&lt;/p&gt;

&lt;p&gt;Even a collection of individually harmless details can make an episode identifiable. Preserve the engineering mechanism while changing or omitting unnecessary specifics.&lt;/p&gt;

&lt;p&gt;The public claim should be something the available evidence can support without inviting the reader to inspect a closed system. "I evaluated and refined workflows" is a different claim from "this programme improved company delivery."&lt;/p&gt;

&lt;h2&gt;
  
  
  Feed the result back into the right layer
&lt;/h2&gt;

&lt;p&gt;When an error repeats, decide which control should change.&lt;/p&gt;

&lt;p&gt;An outdated repository convention belongs in repository context. A general validation habit may belong in a reusable workflow. A missing permission boundary may require tool access to change, not another paragraph in the prompt.&lt;/p&gt;

&lt;p&gt;If the failure came from stale task evidence, repair the handoff or current-state check. If the skill added unnecessary steps, narrow when it applies. If the result remains ambiguous, keep the ambiguity in the record rather than forcing a favorable or unfavorable rating.&lt;/p&gt;

&lt;p&gt;This is where evaluation becomes engineering work. The record is not the final product; the corrected operating arrangement is.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Useful attribution is specific enough to change the next task and modest enough not to invent a cause.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A smaller conclusion can be more reusable
&lt;/h2&gt;

&lt;p&gt;I do not need every evaluation to end with a winner. I need to know which practice helped under which conditions, what required correction, and what the evidence could not distinguish.&lt;/p&gt;

&lt;p&gt;That lets the next task inherit a more useful check or a simpler process instead of a larger claim.&lt;/p&gt;

&lt;p&gt;The five articles in this wave share that approach. Context needs freshness. Green checks need scope. Tool output needs inspection. Reviews need a revision. Skills need honest attribution. None of those mechanisms removes the need for engineering judgement; they give it better material to work with.&lt;/p&gt;

&lt;p&gt;That is the agentic engineering I want to describe: an environment that can learn from ordinary failures without pretending the agent was correct all along.&lt;/p&gt;

&lt;p&gt;If a skill helped your work, what changed in the actual sequence of decisions? I'd be interested in that observation, including what your existing tools or judgement contributed alongside it.&lt;/p&gt;

</description>
      <category>aiagents</category>
      <category>agenticengineering</category>
      <category>evaluation</category>
      <category>engineeringworkflow</category>
    </item>
    <item>
      <title>The Backup Exists. The Restore Still Needs Work.</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Fri, 16 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/the-backup-exists-the-restore-still-needs-work-5hmf</link>
      <guid>https://dev.to/maximusft/the-backup-exists-the-restore-still-needs-work-5hmf</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fonm1ngav648k3xgeanzw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fonm1ngav648k3xgeanzw.png" alt="The Backup Exists. The Restore Still Needs Work." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The database restores successfully to 10:42.&lt;/p&gt;

&lt;p&gt;The payment provider has transactions through 11:07. Object storage contains invoices created after the restore point. The queue still holds jobs referring to orders the restored database does not remember.&lt;/p&gt;

&lt;p&gt;The backup worked. We have not yet recovered the application.&lt;/p&gt;

&lt;p&gt;I think this is the useful distinction to make before an incident. Recovery is not one storage operation. It is deciding which facts remain authoritative after different parts of the system have moved to different points in time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Availability and recovery solve different failures
&lt;/h2&gt;

&lt;p&gt;A replica can keep the service available after one machine fails. It may also faithfully replicate the accidental deletion we are trying to undo.&lt;/p&gt;

&lt;p&gt;A backup preserves another state. Point-in-time recovery can reconstruct a database using a base backup and subsequent transaction-log records, within the retained recovery window. Its value depends on those records being available and the restore procedure actually working.&lt;/p&gt;

&lt;p&gt;Neither mechanism automatically restores object storage, credentials, queue state, or external services.&lt;/p&gt;

&lt;p&gt;I would define the failure being covered: infrastructure loss, accidental deletion, corruption, an incompatible migration, or compromised access. A design that handles the first can still be inadequate for the others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put a business meaning behind RPO and RTO
&lt;/h2&gt;

&lt;p&gt;Recovery point objective describes acceptable data loss. Recovery time objective describes acceptable time to restore the required service.&lt;/p&gt;

&lt;p&gt;"Fifteen minutes" sounds specific. It still needs a meaning. Can fifteen minutes of submitted support forms disappear? Of inventory reservations? Of charged orders? Those are different promises.&lt;/p&gt;

&lt;p&gt;Some operations need reconciliation from another authoritative system even when the database recovery point is acceptable. A payment provider may tell us about a charge the restored database lost. We need a stable reference linking it back to the business operation.&lt;/p&gt;

&lt;p&gt;For recovery time, include more than restoring bytes: provisioning, access approval, decryption keys, application startup, verification, reconciliation, traffic switching, and safe resumption of workers.&lt;/p&gt;

&lt;p&gt;I would measure the whole exercise. A ten-minute restore inside a two-hour recovery procedure is not a ten-minute RTO.&lt;/p&gt;

&lt;h2&gt;
  
  
  Restore beside production, not blindly over it
&lt;/h2&gt;

&lt;p&gt;For a logical data mistake, restoring an isolated instance gives us room to inspect the recovered state and compare it with current production. We may be able to repair a specific set of rows instead of rewinding everything.&lt;/p&gt;

&lt;p&gt;Keep the recovery environment unable to send real emails, charge payments, consume production queues, or execute live webhooks. A copied database can contain pending work that application startup eagerly resumes.&lt;/p&gt;

&lt;p&gt;Use controlled configuration and network access, not merely a promise that nobody will click the dangerous button. Preserve the original state as evidence while deciding which changes to apply.&lt;/p&gt;

&lt;p&gt;Sometimes a full cutover is necessary. Even then, the new instance should be verified before traffic moves, with a deliberate plan for connections, endpoints, and old application instances.&lt;/p&gt;

&lt;p&gt;DNS changes have the &lt;a href="https://ma-x.im/blog/full-stack-domains-and-proxies" rel="noopener noreferrer"&gt;overlap behavior&lt;/a&gt; discussed earlier. Applications may also cache connection settings or continue using old pools. Changing a database endpoint is a release step, not a universal disconnect command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Match data with code and configuration
&lt;/h2&gt;

&lt;p&gt;A database restored to yesterday may have yesterday's schema. Today's application may require a column that did not exist then.&lt;/p&gt;

&lt;p&gt;Record the schema migration state alongside artifact and configuration revisions. Retain deployable artifacts, not just source code that could theoretically be rebuilt with today's package registry.&lt;/p&gt;

&lt;p&gt;An &lt;a href="https://ma-x.im/blog/full-stack-zero-downtime-migrations" rel="noopener noreferrer"&gt;expand/contract migration&lt;/a&gt; gives recovery more options, but it does not remove the need to choose a compatible application version. Running every pending migration automatically against the restored instance may recreate the destructive change we were trying to investigate.&lt;/p&gt;

&lt;p&gt;Secrets matter too. A backup encrypted with an unavailable key is not useful. A restored application with revoked credentials cannot necessarily reach its dependencies. Back up and test the recovery of access paths without scattering secret values through documents or logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  External effects do not rewind with the database
&lt;/h2&gt;

&lt;p&gt;Consider an order that was paid at 10:55 and lost from a database restored to 10:42. Asking the customer to retry can charge them again unless the payment operation has a durable, stable identity.&lt;/p&gt;

&lt;p&gt;Reconcile against the provider using idempotency keys, merchant references, and the provider's authoritative transaction state. Do not infer a refund or charge from the absence of a local row alone.&lt;/p&gt;

&lt;p&gt;Email is another external effect. A replayed confirmation job may send a second message. An invoice number may already have been issued. A shipment may already be in transit.&lt;/p&gt;

&lt;p&gt;The recovery procedure should describe those consequences and the systems that settle them. We cannot restore the world to match a snapshot. We can reconstruct our records so they agree with the world that continued operating.&lt;/p&gt;

&lt;p&gt;This is where the identity choices from the &lt;a href="https://ma-x.im/blog/full-stack-api-contracts" rel="noopener noreferrer"&gt;API&lt;/a&gt; and &lt;a href="https://ma-x.im/blog/full-stack-background-jobs" rel="noopener noreferrer"&gt;queue&lt;/a&gt; articles become more than implementation conveniences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Queues and caches need a recovery policy
&lt;/h2&gt;

&lt;p&gt;A restored outbox may contain events already published before the incident. A current queue may contain messages for records absent from the recovered database.&lt;/p&gt;

&lt;p&gt;Pause consumers while reconciling. Decide which messages to preserve, replay, quarantine, or discard. Idempotent consumers reduce the cost of duplicates, but they still need a coherent business state to operate on.&lt;/p&gt;

&lt;p&gt;Do not delete the queue simply to make its depth look tidy. It may contain the only remaining record of accepted work.&lt;/p&gt;

&lt;p&gt;Redis also needs role-specific handling. Rebuild a disposable product cache from the recovered source. For sessions, consider whether invalidating them is safer than restoring older authorization state. For locks or scheduler metadata, old values may be actively misleading.&lt;/p&gt;

&lt;p&gt;"Restore every dependency" is not always the right instruction. Some state should be restored, some reconciled, and some deliberately recreated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify meaning, not only row counts
&lt;/h2&gt;

&lt;p&gt;A database that starts and contains the expected number of rows is encouraging. It does not prove the checkout workflow is usable.&lt;/p&gt;

&lt;p&gt;Check relationships, critical constraints, recent business operations, object references, account permissions, and one controlled end-to-end flow. Compare representative records with external authoritative systems where necessary.&lt;/p&gt;

&lt;p&gt;Keep enough telemetry to tell when corrupted or missing data first appeared. Otherwise choosing a restore point becomes a sequence of guesses, each followed by another expensive restore.&lt;/p&gt;

&lt;p&gt;Data integrity checks and recovery logs should avoid publishing private customer content. The people conducting a recovery need controlled access, not an unrestricted data export pasted into the incident channel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the access path that an incident will use
&lt;/h2&gt;

&lt;p&gt;A recovery exercise run by an administrator with every permission can conceal missing privileges in the actual emergency role. Test who can start the restore, decrypt it, deploy compatible code, change routing, and release the isolation controls.&lt;/p&gt;

&lt;p&gt;For compromise scenarios, consider independent backup protection: restricted deletion, retention controls, and appropriate account or region separation. If the same credential can destroy production and every backup, the copies share a rather important failure mode.&lt;/p&gt;

&lt;p&gt;There is no universal arrangement that makes all of this free. The choices should reflect the actual data, recovery promise, and threat model.&lt;/p&gt;

&lt;p&gt;Document who makes the cutover decision and who handles reconciliation. That is operational ownership, not an excuse to collect an impressive runbook nobody has tried.&lt;/p&gt;

&lt;h2&gt;
  
  
  A useful drill has an inconvenient detail
&lt;/h2&gt;

&lt;p&gt;Try restoring with an old schema, an unavailable primary region, a rotated credential, or a job already delivered once. Choose one complication rather than pretending the exercise must reproduce every disaster at once.&lt;/p&gt;

&lt;p&gt;Measure the result, record the steps that required undocumented knowledge, and repair those gaps. A failed rehearsal is useful when it changes the recovery path before the real incident.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A backup preserves data. A rehearsed recovery preserves the ability to use it safely.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is where I would end this field guide. The database, cache, queue, proxy, and application are not independent checkboxes. Their boundaries become visible when a request fails, a deployment overlaps, or one component returns to an earlier state.&lt;/p&gt;

&lt;p&gt;I would be satisfied with an ordinary system whose recovery procedure is unremarkable because it has been tested. That seems a more useful goal than another layer whose failure behavior we will learn later.&lt;/p&gt;

&lt;p&gt;If you've attempted a restore rehearsal, what took longer than the database restore itself? I'd be interested in the dependency or decision the backup dashboard could not account for.&lt;/p&gt;

</description>
      <category>fullstack</category>
      <category>database</category>
      <category>recovery</category>
      <category>reliability</category>
    </item>
    <item>
      <title>A Review Belongs to a Commit</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Thu, 15 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/a-review-belongs-to-a-commit-2a5b</link>
      <guid>https://dev.to/maximusft/a-review-belongs-to-a-commit-2a5b</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs41vs3ga9lkuc8m1qhtb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs41vs3ga9lkuc8m1qhtb.png" alt="A Review Belongs to a Commit" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A reviewer sees a change and raises a useful concern. The author pushes another commit.&lt;/p&gt;

&lt;p&gt;The comment is still there. The code it described may not be.&lt;/p&gt;

&lt;p&gt;Human reviewers handle this imperfectly too. An automated reviewer makes the state-management problem easier to notice because it can repeat the same concern every time it runs, or confidently act on a conclusion from the previous revision.&lt;/p&gt;

&lt;p&gt;The earlier &lt;a href="https://ma-x.im/blog/github-ai-pr-reviewer" rel="noopener noreferrer"&gt;PR-reviewer article&lt;/a&gt; focused on useful language and visibility into a personal tool. This article is about a narrower engineering problem: what a finding, check, or review decision refers to as the code changes.&lt;/p&gt;

&lt;p&gt;I have developed commit-aware tracking, duplicate-finding safeguards, dry-run checks, and guarded actions in personal review tooling with AI assistance. That describes development of mechanisms, not current continuous operation, organization-wide adoption, or a replacement for human approval.&lt;/p&gt;

&lt;h2&gt;
  
  
  A PR number is not the reviewed object
&lt;/h2&gt;

&lt;p&gt;The PR is a container for an evolving proposal. The head commit identifies one version of that proposal. The base revision and comparison mode also affect what the reviewer sees.&lt;/p&gt;

&lt;p&gt;If an automated tool records only "PR reviewed," it cannot distinguish unchanged work from a new commit. If it records only head SHA, it may miss a changed base or integration result that matters to its conclusion.&lt;/p&gt;

&lt;p&gt;A useful record identifies what was reviewed and under which assumptions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ReviewSnapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;headSha&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;baseSha&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;comparison&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pull-request-diff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;rulesRevision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;checkedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an illustrative type, not an internal implementation. The rules revision matters because the same code can be assessed differently after the checking policy changes.&lt;/p&gt;

&lt;p&gt;I would not let a convenient database row imply more history than it contains. "Reviewed" should be explainable as a particular observation, not a permanent property of the PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  CI has a revision too
&lt;/h2&gt;

&lt;p&gt;A green check from an earlier commit does not establish the state of the current one. A required integration check may run on a merge result rather than the branch head. Those are different artifacts.&lt;/p&gt;

&lt;p&gt;Before review actions, identify which checks are relevant, which revision they exercised, and whether they are finished. A skipped check or an optional success is not necessarily equivalent to every required gate passing.&lt;/p&gt;

&lt;p&gt;Even then, CI evidence has the scope limits discussed in Green Checks Only Cover What You Checked. It can support a reviewable state without proving the absence of semantic defects.&lt;/p&gt;

&lt;p&gt;I want a tool to report that distinction rather than promote "green CI" into "safe to approve."&lt;/p&gt;

&lt;h2&gt;
  
  
  A finding needs identity and evidence
&lt;/h2&gt;

&lt;p&gt;Line numbers are useful for placement. They are poor long-term finding identities.&lt;/p&gt;

&lt;p&gt;An author can move the same risky expression to another line. The finding remains relevant, but a line-based key changes and the bot may publish it again. Conversely, new code at the old line can have a different risk that a naive key suppresses.&lt;/p&gt;

&lt;p&gt;A more semantic identity can include the rule, affected symbol, risk category, and relevant normalized evidence. Keep the exact source revision alongside it.&lt;/p&gt;

&lt;p&gt;Normalization introduces its own trade-off. Strip too much context and different findings collapse into one fingerprint. Keep every character and harmless formatting changes produce duplicates.&lt;/p&gt;

&lt;p&gt;Treat a fingerprint as a useful matching mechanism, not proof that two concerns are identical. Re-evaluate the current evidence before deciding the old finding still applies or no new comment is needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Suppressed does not mean resolved
&lt;/h2&gt;

&lt;p&gt;A repeated finding can be current and intentionally not republished. A missing finding can mean it was fixed, became unobservable in the selected diff, or was skipped because the analysis failed.&lt;/p&gt;

&lt;p&gt;Those states need different names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;current:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;concern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;supported&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;latest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;evidence&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;unchanged:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;current,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;but&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;no&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;repeated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;comment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;needed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;resolved:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;evidence&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;supports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;that&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;concern&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;no&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;longer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;applies&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;not-observed:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;did&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;establish&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;either&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;outcome&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;needs-human:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;cannot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;settle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;question&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;safely&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact storage model can vary. The distinction keeps duplicate suppression from quietly becoming automatic resolution.&lt;/p&gt;

&lt;p&gt;An unresolved human thread is another state the tool should not overwrite simply because its own detector no longer sees the pattern. The thread may concern context or a decision that the detector never understood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recheck state before publication
&lt;/h2&gt;

&lt;p&gt;Analysis can take time. While it runs, the author can push new code. A comment created from the original diff may now point to invalid lines or describe a risk that has already changed.&lt;/p&gt;

&lt;p&gt;Re-read the relevant state before publishing. If it no longer matches the reviewed snapshot, stop, discard the pending action, or schedule another review. Do not silently attach the finding to a different revision because that makes the API call easier.&lt;/p&gt;

&lt;p&gt;The same applies to stronger actions. A guarded action should carry the expected revision and use a platform-supported condition where available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;GuardedReviewAction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;expectedHeadSha&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;snapshotId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;publish-review&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This type expresses the requirement; it does not implement an atomic guarantee. Reading head and then calling an API leaves a time-of-check/time-of-use interval. If the platform cannot condition the action atomically, handle that limitation explicitly and avoid unsupported claims about stale-action prevention.&lt;/p&gt;

&lt;p&gt;A fresh check reduces risk. It does not freeze another person's branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  A dry run has its own evidence boundary
&lt;/h2&gt;

&lt;p&gt;A dry run can show which findings and actions a tool would produce. It is useful for inspecting scope, tone, duplicates, and targeting without creating external effects.&lt;/p&gt;

&lt;p&gt;It does not prove that the later API call will be authorized, attach to the intended line, or observe the same PR state. Nor does a successful API call prove the review content was correct.&lt;/p&gt;

&lt;p&gt;Use the dry run to inspect proposed actions. Use publication checks to verify current state and delivery. Keep the two results separate in the control interface.&lt;/p&gt;

&lt;p&gt;If the inline attachment fails, a body-level review may preserve the concern, but should still identify the source revision. A fallback should not turn a precisely scoped observation into an unexplained general warning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Human decisions need context, not silent reassignment
&lt;/h2&gt;

&lt;p&gt;A person may approve a particular revision. New code can change the basis for that decision. The tool should make that change visible and follow the platform's review policy rather than assume an earlier approval means the new code is accepted.&lt;/p&gt;

&lt;p&gt;Whether an approval is dismissed, still valid, or requires a new decision depends on the repository's settings and accountable reviewers. The automation should not invent its own release authority.&lt;/p&gt;

&lt;p&gt;Likewise, an AI suggestion that a dependency update appears routine is evidence, not permission to merge it. Any permitted automatic action needs its own narrowly defined authorization and technical controls. It should not be inferred from the absence of findings.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A review result describes observed code. It does not transfer responsibility for whatever code arrives next.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Preserve enough history to explain the tool
&lt;/h2&gt;

&lt;p&gt;The control surface should answer ordinary questions: which revision was analyzed, what was published, what was suppressed, why a run stopped, and what remains undecided.&lt;/p&gt;

&lt;p&gt;Record identifiers and outcomes with appropriate retention. Avoid storing raw credentials, private payloads, or unnecessary code copies just to make a log feel complete.&lt;/p&gt;

&lt;p&gt;When the tool is wrong, the history should help reproduce the decision. Was the input stale? Did normalization merge two findings? Did a missing detector result get treated as resolution? Did the action target change between analysis and publication?&lt;/p&gt;

&lt;p&gt;Those are repairable mechanisms. Without the history, every correction becomes a guess about the model's intentions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The quieter reviewer is not necessarily the better reviewer
&lt;/h2&gt;

&lt;p&gt;Duplicate suppression makes the conversation less noisy. That is useful. It can also hide an unresolved issue if the lifecycle is poorly modelled.&lt;/p&gt;

&lt;p&gt;I would evaluate the tool on the relevance and traceability of its findings, not merely on how few comments it emits. Check unchanged code, moved code, corrected code, a new risk at the old location, and a head update during analysis.&lt;/p&gt;

&lt;p&gt;Keep a human in charge of interpretation and approval. A review assistant should make that person's evidence easier to find, not create a reassuring status that no one can explain.&lt;/p&gt;

&lt;p&gt;The next article, &lt;a href="https://ma-x.im/blog/agent-playbook-what-a-skill-changed" rel="noopener noreferrer"&gt;What a Skill Changed, and What It Didn't&lt;/a&gt;, examines the same attribution problem at workflow level: what a reusable skill changed, and what it did not.&lt;/p&gt;

&lt;p&gt;If your review automation remembers that it saw a PR, what exactly does it remember about the code? That is a useful place to inspect before adding another action to it.&lt;/p&gt;

</description>
      <category>aiagents</category>
      <category>codereview</category>
      <category>developertooling</category>
      <category>reliability</category>
    </item>
    <item>
      <title>The Dashboard Is Green. The Order Is Missing.</title>
      <dc:creator>Maksym Kuzmitskyi (MaximusFT)</dc:creator>
      <pubDate>Wed, 14 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/maximusft/the-dashboard-is-green-the-order-is-missing-19ag</link>
      <guid>https://dev.to/maximusft/the-dashboard-is-green-the-order-is-missing-19ag</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fig86qanpn9iexpzb5fqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fig86qanpn9iexpzb5fqw.png" alt="The Dashboard Is Green. The Order Is Missing." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The API error rate is low. The workers are running. The browser reported no uncaught exception.&lt;/p&gt;

&lt;p&gt;A user says their order never appeared.&lt;/p&gt;

&lt;p&gt;All of those observations can be true. We measured the health of individual pieces, while the user described an outcome across several pieces. The missing part is the connection between them.&lt;/p&gt;

&lt;p&gt;I do not think the answer is simply to log more. A larger pile of unrelated events gives us more to read, which is not quite the same thing as giving us more to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the outcome we need to explain
&lt;/h2&gt;

&lt;p&gt;For checkout, I would distinguish browser intent, request acceptance, order persistence, payment confirmation, and follow-up work.&lt;/p&gt;

&lt;p&gt;These are not synonyms. A click event proves that someone activated a control. A 200 response proves that an HTTP exchange returned that status. A database record proves that an order was stored. A confirmation email proves another effect entirely.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ma-x.im/blog/react-playbook-analytics-as-a-layer" rel="noopener noreferrer"&gt;analytics layer&lt;/a&gt; and an operational trace also serve different purposes. Product analytics can describe behavior; operational telemetry needs enough context to reconstruct a specific failure without assuming every recorded click became a completed purchase.&lt;/p&gt;

&lt;p&gt;I would define the business success point explicitly, then work backwards to the evidence required at each boundary. Otherwise the most available metric quietly becomes the definition of success.&lt;/p&gt;

&lt;h2&gt;
  
  
  A request id is useful, but it is not the whole identity
&lt;/h2&gt;

&lt;p&gt;A request id correlates one HTTP attempt. An idempotency key identifies one intent across retries. An order id identifies durable business state. A trace context links spans across participating services.&lt;/p&gt;

&lt;p&gt;Keeping these separate is helpful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"order.persisted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"req_9c7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"operation_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"checkout_62a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"order_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"order_18f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4bf92f3577b34da6a3ce929d0e0e4736"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"checkout-2026-10-14"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are synthetic identifiers. The record does not include a customer's name, email, address, token, or raw payment data.&lt;/p&gt;

&lt;p&gt;A retry gets a new request id but retains the operation identity. A background job can link to the operation after the original request has ended. Depending on timing and instrumentation, a span link may describe that relationship more honestly than an endlessly extended parent span.&lt;/p&gt;

&lt;p&gt;Use established trace propagation and instrumentation, such as OpenTelemetry, rather than inventing a collection of vaguely compatible headers. Still validate untrusted incoming context and keep authorization separate from any telemetry identity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Missing data has several explanations
&lt;/h2&gt;

&lt;p&gt;If a trace is absent, the request may never have happened. It may also have been sampled out, rejected by a collector, dropped from a full buffer, or generated by an uninstrumented component.&lt;/p&gt;

&lt;p&gt;Head sampling decides early which traces to retain. It keeps costs bounded, but it cannot know at the start which request will fail late. Tail sampling can select after observing more of the trace, at the cost of buffering, coordination, and its own resource limits.&lt;/p&gt;

&lt;p&gt;Neither gives perfect evidence automatically. Keep critical outcome counters and durable business records independently of a sampling decision. Record the telemetry pipeline's own drops and health so absence is less ambiguous.&lt;/p&gt;

&lt;p&gt;For frontend error reporting, the same limitation applies. Browser extensions, network conditions, consent settings, and navigation can affect delivery. No recorded exception is not proof that no exception occurred.&lt;/p&gt;

&lt;h2&gt;
  
  
  Denominators need their own definition
&lt;/h2&gt;

&lt;p&gt;"Twenty failed orders" is difficult to interpret without knowing how many attempts occurred and which attempts count.&lt;/p&gt;

&lt;p&gt;Counting API requests exaggerates user intent when retries occur. Counting clicks includes actions rejected before a request. Counting created orders excludes failures before persistence.&lt;/p&gt;

&lt;p&gt;For an outcome metric, define both numerator and denominator around the promise being measured. For example: distinct accepted checkout operations that reach a confirmed or explicit terminal state within a chosen interval.&lt;/p&gt;

&lt;p&gt;Then describe exclusions: abandoned carts, expected validation failures, test traffic, and operations still inside their allowed processing window. An illustrative target is not a universal SLO.&lt;/p&gt;

&lt;p&gt;The arithmetic is usually easy. The difficult part is resisting a reassuring percentage with a poorly chosen population.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cardinality is a modelling choice
&lt;/h2&gt;

&lt;p&gt;Metrics work well with bounded dimensions such as route templates, status categories, region, and service.&lt;/p&gt;

&lt;p&gt;Attaching &lt;code&gt;order_id&lt;/code&gt;, raw URLs, or customer email to every metric label creates huge numbers of distinct time series. It also turns the monitoring system into a rather expensive and unsuitable customer index.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;/orders/:id&lt;/code&gt;, not every concrete order URL, as a metric dimension. Put specific identities in controlled logs or traces when needed, with retention and access appropriate to their sensitivity.&lt;/p&gt;

&lt;p&gt;Histograms deserve some care too. Percentiles computed independently by instances cannot generally be averaged into the fleet's percentile. Aggregate compatible histogram observations rather than averaging whichever p95 numbers happen to be on the screen.&lt;/p&gt;

&lt;p&gt;The goal is not to avoid detail. It is to put detail into the kind of evidence that can handle it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend context can make a backend trace usable
&lt;/h2&gt;

&lt;p&gt;A server sees requests. The browser knows which route, interaction, and release led to them.&lt;/p&gt;

&lt;p&gt;For an error-reporting tool such as Sentry, a release identifier and matching source maps can turn a minified stack into something useful. Upload source maps through controlled tooling; decide whether publicly serving source files is intended. A production error should identify the bundle that actually ran, not the latest source in main.&lt;/p&gt;

&lt;p&gt;Session replay can help explain interaction sequences, but I would not enable it broadly without reviewing masking, consent, sensitive fields, retention, and access. "It is an internal admin screen" is often a reason for more care, not less.&lt;/p&gt;

&lt;p&gt;Expected cancellation should not appear beside faults as though a user navigating away is a broken system. The &lt;a href="https://ma-x.im/blog/react-playbook-abort-controller" rel="noopener noreferrer"&gt;AbortController article&lt;/a&gt; covers that distinction at the interface boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  An alert should name a response
&lt;/h2&gt;

&lt;p&gt;High CPU may deserve investigation. Missing orders deserve investigation for a more direct reason.&lt;/p&gt;

&lt;p&gt;Prefer alerts connected to user-visible impact or exhausted safety margins: sustained error-budget consumption, queue age beyond the product allowance, connection-pool waits, failure to complete accepted operations, or a recovery dependency approaching expiry.&lt;/p&gt;

&lt;p&gt;The notification needs an owner, a scope, and a useful next action. A chart link is helpful. So are a recent deployment marker and a runbook that says which evidence separates an application failure from a shared-dependency failure.&lt;/p&gt;

&lt;p&gt;I would not page someone every time one instance reports a brief spike unless that spike calls for a meaningful intervention. Noise does not stay harmless; it changes what people notice later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Telemetry is another dependency
&lt;/h2&gt;

&lt;p&gt;Exporters have buffers, network calls, timeouts, and shutdown behavior. A slow collector should not cause the checkout handler to wait indefinitely or allocate unbounded memory.&lt;/p&gt;

&lt;p&gt;Use bounded, asynchronous export appropriate to the instrumentation. Decide what can be dropped and what must be durably recorded elsewhere. Business events required for fulfilment belong in a durable mechanism such as the &lt;a href="https://ma-x.im/blog/full-stack-background-jobs" rel="noopener noreferrer"&gt;transactional outbox&lt;/a&gt;, not solely in a best-effort log stream.&lt;/p&gt;

&lt;p&gt;Also test redaction failures and collector outages. Observability should help us explain failure without becoming its next cause or a route for leaking data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A telemetry event is evidence with delivery conditions, not a second database transaction.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Reconstruct one unsuccessful operation
&lt;/h2&gt;

&lt;p&gt;I would exercise a deliberately failed checkout and try to follow it from browser intent to its final state. Can we distinguish a request that never arrived from an order that persisted but lost its response? Can we find the background job? Can we identify the release and a retry without counting them as two purchases?&lt;/p&gt;

&lt;p&gt;If those questions are difficult, another dashboard will not necessarily improve the situation. A better identity or an event at the missing boundary might.&lt;/p&gt;

&lt;p&gt;The green dashboard becomes useful when we know exactly what its green means. Until then, I would keep the user's missing order as the more interesting observation.&lt;/p&gt;

&lt;p&gt;The final part of this guide covers &lt;a href="https://ma-x.im/blog/full-stack-backups-and-recovery" rel="noopener noreferrer"&gt;backups and recovery&lt;/a&gt;: what happens when diagnosis is finished and some part of the system actually has to be rebuilt.&lt;/p&gt;

&lt;p&gt;Which production question still sends you comparing timestamps across three tools? I'd like to hear the missing connection, not just which monitoring product you use.&lt;/p&gt;

</description>
      <category>fullstack</category>
      <category>observability</category>
      <category>reliability</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
