A defect class is a recurring category of bug that shows up across independent products, not a one-off fix in a single release. Reading competitor changelogs this way turns each vendor fix into a test obligation: if Claude Code, Codex CLI, and Cursor CLI each shipped a correction for the same kind of failure, that kind is a class worth auditing in our own tool (yoyo), even though our code shares nothing with theirs.
This page records the defect classes identified from the Claude Code 2.1.318, Codex CLI 0.165/0.166, and Cursor CLI v2026.10.22 releases, mapped to the yoyo issues they touch.
Key Points
False success is the dominant class. Tools report success (exit 0, "logged out", "removed") when the underlying write or request failed, so the change is silently dropped.
All-or-nothing validation is the second major class. One malformed record (a damaged cert, one invalid MCP tool schema) disables every valid sibling rather than the bad one.
Non-interactive mode (-p) is a blind spot for error surfacing: failing custom slash commands printed nothing, and an API error that truncated a reply was reported as success.
The agent's model of the world must be corrected, not just the program's state: an unavailable connector, missing tool schema, or failed subagent has to be told to the agent.
Transient-vs-permanent errors must be distinguished — retrying a "model not found" wastes turns and obscures the provider's own message.
Degradation must be disclosed: falling back to a parent model, or stopping a subagent, has to be visible in the result rather than looking like normal completion.
All-or-nothing validation — a single invalid element poisons the whole set instead of being skipped with a warning.
Agent-facing error state — error/status information the model itself consumes, distinct from what a human sees.
Permanent vs. transient error — whether retrying can ever succeed.
Partial state — artifacts left behind by an interrupted operation.
Disclosed fallback — a degraded path taken but explicitly announced.
Config lock — mutual exclusion around read-modify-write of shared config.
Startup probe — the version/handshake check performed against stdio MCP servers.
Details
Class 1 — False success on failed persistence
Claude Code's /logout, auth logout, and mcp remove all reported success when the config file could not be written, so the changes were dropped silently. The same class is yoyo #1137: writer verbs exiting 0 on a failed write.
The general obligation: any verb that mutates durable state must either persist it or exit non-zero with a message. "Printed a success line" and "returned 0" are both claims that need to be earned.
Class 2 — All-or-nothing input validation
When NODE_EXTRA_CA_CERTS was empty, not PEM, or began with a damaged cert, every connection failed. The fix was to use the readable certificates and warn on stderr — i.e. degrade to the valid subset instead of rejecting the whole input.
This is the class behind yoyo #1138 (refusing a CA env that loads zero certs at startup); the partially-damaged-file case — some certs parse, some don't — is a separate row and needs its own handling.
Cursor shows the same pattern from the other direction: one invalid MCP tool schema no longer hides the server's other tools. A server that cannot list its tools at all should report an error to the agent rather than appearing to have none.
Class 3 — Errors swallowed in non-interactive output
Two Claude Code rows belong here:
Custom slash commands that failed printed nothing in -p mode.
-p reported success when an API error cut off a reply while a hook was running.
Machine-readable modes are where silence is most costly, because the caller has no TUI to glance at and will treat the empty-but-clean result as truth. Any -p path needs an explicit terminal status: truncation, hook failure, and command failure must all surface.
Class 4 — Correcting the agent's world model
Rather than only fixing program state, several fixes exist to tell the model what happened:
A tool call made before the tool is loaded now returns the tool's input schema, so the agent can proceed or adapt instead of guessing.
Claude is told when an approved MCP connector was unavailable after a restart.
A failed or stopped subagent is presented to the agent as failed, not as finished.
A pinned subagent model that cannot run falls back to the parent model — and the result says so.
The underlying principle: silent substitution is a defect. If the runtime took a different path than requested, the agent's next decision depends on knowing that.
Class 5 — Retry policy
Codex CLI stopped retrying when the provider says the model is not found, and preserves the provider's message instead of replacing it with a generic retry-exhausted error. Permanent errors should terminate immediately and carry their original cause; retrying them burns budget and hides the real reason.
Class 6 — Partial and ambiguous state
Failed compaction in Codex no longer leaves partial summaries behind. Interrupted operations should either roll back or mark their output as incomplete; the same reasoning motivates Claude Code taking the config lock on mcp add/remove or exiting 1 — concurrent read-modify-write of shared config otherwise loses updates with no error at all.
Class 7 — Unsafe diagnostics and scope gaps
Codex added codex doctor --network-only (a narrow, targeted diagnostic) and masks credentials in remote bash — diagnostics must not leak secrets.
stdio MCP servers that exit on the version probe are no longer re-probed on every start: a known-dead endpoint should be remembered as dead rather than paid for repeatedly.
Cursor applies nested AGENTS.md rules when editing a file in that subdirectory even if the file was never read — configuration discovery must be scoped by the target of the operation, not by what happened to be loaded.
Triage flowchart
Rendering diagram…
Applying these to yoyo
Treat each class as a test dimension, not a single test: for every writer verb, ask what does it exit on failed persistence; for every batch input, ask what happens to the valid members; for every -p path, ask is there an explicit terminal status; for every agent-visible outcome, ask does the model learn the truth; for every retry, ask is this error permanent; for every concurrent config mutation, ask is there a lock.