Skip to content

Instantly share code, notes, and snippets.

@aviadr1
Created March 26, 2026 21:58
Show Gist options
  • Select an option

  • Save aviadr1/16e3ed1c787d52827d9673712a4626fb to your computer and use it in GitHub Desktop.

Select an option

Save aviadr1/16e3ed1c787d52827d9673712a4626fb to your computer and use it in GitHub Desktop.
Planning Quality Research — Round 2: Challenge (Contrarian, Staff Engineer Model, Experience Accumulation)

The Contrarian Antithesis: Round 1 Solved the Wrong Problem

Round 2 — March 2026


1. Steel-Manning Round 1, Then Burning It Down

Round 1 produced three complementary lenses on a single question: when should an agent pause before implementing? Decision Theory gave a scoring formula (DPS = R×I×S). Cognitive Ethnography gave a cognitive science grounding (RPD, tacit knowledge, Design Stance Protocol). Signal Archaeology (not completed in R1) would presumably mine git history for risk signals.

The steel-man: Round 1 correctly identified that the agent's failure mode is not bad decision-making but non-decision — proceeding through a genuine design fork as if it were an execution step. The DPS formula is honest about being a "decision instrument," not a precise formula. The Design Stance Protocol explicitly names what it is: an externalized substitute for expert anomaly detection. The cognitive ethnography is the strongest piece — it accurately models what tacit expertise actually is (compiled procedural memory, not articulable rules) and why checklists will always be incomplete.

Now the rebuttal.

Where Decision Theory fails: The DPS formula (R×I×S) is a trigger for pausing at individual decisions. But consider what it assumes: that the agent encounters a decision, applies the formula, and then either pauses or proceeds. This is instance-level thinking. It treats every decision as independent. A staff engineer doesn't operate this way. They design architectures where large categories of bad decisions become structurally impossible — the fork doesn't appear in the first place. DPS can score "should I store state in the orchestrator or in the subagents?" But it cannot tell you "design the system so that state ownership is never ambiguous at the protocol level." That's a different level of thinking entirely. The formula addresses symptoms. The staff engineer addresses categories.

Where Cognitive Ethnography fails: The Design Stance Protocol is five steps that mimic what an expert does after their anomaly detector fires. But the document is honest about a deeper problem it then sidesteps: "AI agents, currently, have no persistent episodic memory across sessions. Each session begins at the same baseline." The protocol doesn't solve this — it works around it by providing an explicit procedure to substitute for pattern-matching that doesn't exist. That substitution is useful but it's not the same thing. A protocol that says "name two alternative designs" doesn't know which alternatives are worth naming. An expert names the right two alternatives because they've seen this class of problem fail before. The agent names whatever comes to mind. The gap between those two is the gap between a checklist and a decade of experience, and Round 1 does not close that gap.

The shared failure across all Round 1 approaches: Every one of them is about the trigger — when to pause. None of them address the question Aviad actually asked: how does an agent acquire the equivalent of engineering experience? How does it form and test hypotheses? How does it explore design space efficiently? How does it get better over time? Round 1 built better brakes. The question was: how do you build a driver?


2. The Real Problem Reframed

Aviad's clarification reveals this is not a "design pause" problem at all. It is a problem about engineering intelligence as a learnable, accumulating capability.

The actual problem: AI agents currently operate like very capable but permanently junior engineers. They can execute competently within a session. They can reason about designs when prompted. But they don't accumulate experience, don't form and test hypotheses about categories of problems, don't build intuitions that transfer across sessions, and don't develop the architectural instincts that distinguish a staff engineer from a senior engineer. Every session is day one.

The question is: can this be changed? And if so, how?

This is a fundamentally different problem from "when should the agent pause." It has three distinct sub-problems:

Sub-problem A — Experience accumulation: How does an agent build something analogous to a failure library and design pattern library that persists and grows across sessions?

Sub-problem B — Hypothesis formation and testing: When an agent encounters a design question, how does it form architectural hypotheses and validate them before committing — not by gut feel, not by checklist, but by something resembling the scientific method applied to software architecture?

Sub-problem C — Category-level prevention: How does an agent design systems where entire categories of mistakes become impossible, rather than detecting individual instances of those mistakes?

Round 1 addressed none of these. It addressed a fourth problem — instance-level decision triggers — which is useful but downstream of the real problem.


3. What a Staff Engineer Actually Does

The cognitive ethnography cites Klein's RPD model but draws from it only the trigger mechanism. The fuller model is more useful.

When a staff engineer encounters a new codebase or problem, they don't immediately evaluate design alternatives. They do something prior to that: they build a mental model of the problem's category. Before asking "which design?", they ask "what kind of problem is this?" and "what category does this belong to?" That categorization triggers retrieval from a library of category-specific failure modes, known solutions, and known traps.

The sequence is roughly:

  1. Categorize — "This is a distributed state ownership problem. I've seen three variants of this: the write-through pattern, the CRDT pattern, and the saga pattern. Each has a failure topology." The categorization happens fast, often before the agent has even described the problem fully.

  2. Load failure topology — Not "what could go wrong?" generically, but "what specifically goes wrong with each known design in this category?" The failure topology is specific to the category. For distributed state ownership: partial write failure, split-brain, read-your-writes violations. These aren't hypothetical — they're patterns extracted from past incidents across many projects.

  3. Form hypotheses — "Given this specific context (session-scoped agents, no external queue, crash-recovery requirements), hypothesis: the write-through pattern will fail on mid-session crash. Hypothesis: the saga pattern is overkill for this scale. Hypothesis: agent-local writes with late aggregation violates the read-your-writes requirement in the review workflow." These are falsifiable predictions, not gut feelings.

  4. Test hypotheses cheaply — Before building anything: "If I use the orchestrator-batch pattern, what happens when the process dies at step 7 of 10?" Walk the failure path explicitly. This is hypothesis testing — you're running a mental simulation designed to falsify your preferred design.

  5. Eliminate dominated options — Options that fail more failure modes than alternatives, without compensating advantages, are eliminated. Not ranked. Eliminated. The design space shrinks fast.

  6. Make the residual tradeoff explicit — After elimination, often one or two options remain. The staff engineer makes the tradeoff explicit: "Option A is simpler but loses idempotency. Option B is complex but survives partial failure. Given that this workflow runs once per session and partial failure is the common case, B." This is a decision — but it's a decision between a small residual set after most candidates have been eliminated by hypothesis testing.

Notice what is not in this sequence: a formula. Not a scoring rubric. Not a checklist. What is present: a category library that gets loaded before evaluation starts, a hypothesis formation step that is explicit, and a falsification discipline that eliminates options based on which failure modes they can't survive.

The DPS formula skips to step 6 without doing steps 1-5. That's why it's insufficient.


4. Category-Level Architecture vs. Instance-Level Detection

This is the central distinction Round 1 missed.

Instance-level detection: The DPS formula fires when the agent is about to make a decision that scores high on recurrence, irreversibility, and survival divergence. The agent pauses. It considers alternatives. It makes a better decision. One decision at a time.

Category-level prevention: The agent designs a system where the bad decision cannot arise. Instead of "detect when state ownership is ambiguous and pause," the answer is: "enforce a protocol that makes state ownership structurally unambiguous." If agents are required to register state claims with a coordinator before writing, the orchestrator-batch vs. agent-stores fork never appears — the protocol makes one answer mandatory.

Category-level prevention operates at the architecture layer, not the decision layer. It changes the decision space itself rather than improving decision-making within the current decision space. This is the difference between designing a road with guardrails (category-level) and training better drivers (instance-level).

Concrete examples of the difference:

  • Instance-level (DPS): "When you're about to store state, check if this is session-scoped and if there's a survival divergence between design options."

  • Category-level: "All state that must survive session death is persisted atomically by the writing agent before any coordination signal is sent. This is an invariant, not a decision."

  • Instance-level (Design Stance Protocol): "Before implementing, name two alternative designs."

  • Category-level: "The system uses an append-only event log. All agents append. No agent reads from another's mutable state. The category of 'which agent owns this state' is structurally eliminated."

Category-level prevention is more powerful for two reasons. First, it works when the agent doesn't notice the decision — the architecture makes the bad option impossible, so the agent doesn't need to detect that it's at a decision point. Second, it's O(1) overhead at decision time — the rule applies everywhere without a scoring step.

The cost: category-level prevention requires more upfront thinking. You have to identify the category before you can prevent it. You need the experience to recognize that "state ownership ambiguity" is a category worth preventing, not just a case worth detecting. This is where the experience accumulation problem re-enters.


5. The Hypothesis Testing Gap

Aviad explicitly named "how to form and test hypotheses" as a core requirement. Round 1 ignored this entirely. This is the biggest omission.

The scientific method, applied to software architecture, looks like this:

Step 1 — Observation: Identify the phenomenon you're trying to explain or the requirement you're trying to satisfy. "The review workflow must survive mid-session crashes."

Step 2 — Hypothesis: State a falsifiable prediction. "Hypothesis: if each agent persists its findings before signaling completion, the orchestrator can safely crash and restart without data loss." Crucially: this is falsifiable. You can construct a scenario that would prove it wrong.

Step 3 — Experiment design: What is the cheapest way to falsify this hypothesis? Not "build it and see," but "what is the minimal test?" For architecture hypotheses, the cheapest test is usually a failure scenario walkthrough: "assume the orchestrator crashes at point X. What state has been written? What is lost? What can be reconstructed?"

Step 4 — Falsification attempt: Execute the failure scenario. Try to break the hypothesis. If the hypothesis survives — if you cannot find a scenario where it fails — it becomes a design choice with documented failure modes.

Step 5 — Rival hypothesis comparison: If hypothesis A survives falsification, compare it to the best rival hypothesis. "Rival: orchestrator writes findings in a single batch at the end. Falsification: orchestrator crashes before the batch write. Outcome: all data lost." Rival hypothesis is falsified. Original hypothesis survives. Choose original.

This is what Round 1 doesn't describe. The Design Stance Protocol's "failure-first simulation" is in the neighborhood — but it stops short of being a hypothesis-testing methodology. It's a checklist step, not a scientific discipline. The difference: in hypothesis testing, you are explicitly trying to prove yourself wrong. You seek the failure mode that kills your design. If you can't find it despite genuine effort, the design is provisionally validated. The Design Stance Protocol asks you to "name failure modes" — but doesn't require you to construct the minimum scenario that falsifies each design candidate.

The practical mechanism for agents: before any non-trivial design choice, the agent must state at least one falsifiable hypothesis per candidate design, then explicitly attempt to falsify each hypothesis by constructing the simplest possible failure scenario. Only designs that survive falsification attempts are eligible for selection.

This is not expensive. A well-formed falsification attempt takes two to three minutes. It is also fast to recognize when a hypothesis is obviously non-falsifiable (trivially correct) vs. genuinely surviving pressure.


6. The Proportionality Principle

Aviad said: "small issues don't start taking huge resources." Round 1 acknowledges this in the DPS formula's meta-paradox section: "if the agent applies DPS to every sub-decision recursively, the overhead explodes." The proposed fix is to scope DPS to structural decisions only.

But that fix is still instance-level. It reduces the frequency of the overhead, not the nature of it. The DPS formula is a uniform mechanism applied selectively. What's needed is a mechanism that is inherently proportional — where the cost scales with the actual complexity of the decision.

What does proportional look like?

Near-zero cost (simple decisions): Pattern match to a known solution in the category library. "This is a simple state storage problem where the state is bounded and session-local. Known pattern: in-memory dict. No hypothesis testing needed — failure mode is trivial and recovery is trivially cheap." Total overhead: 2 seconds to recognize the category and match the pattern. Proceeds immediately.

Low cost (moderate decisions): Category recognized but multiple viable options exist. "This is a state persistence problem with cross-session requirements. Known patterns: file write, external queue, event log. Run one failure scenario per candidate, eliminate dominated options." Total overhead: 3-5 minutes. One falsification cycle per candidate.

High cost (novel decisions): Category not in library, or multiple categories apply simultaneously, or the failure modes are coupled in non-obvious ways. "This is simultaneously a distributed state problem and a protocol ordering problem. Unknown interaction." Full hypothesis testing with multiple failure scenarios, explicit documentation of the new category for future retrieval. Total overhead: 20-30 minutes — but this is rare by definition, because most decisions fall into known categories as the library grows.

The key insight: the cost scales with how novel the decision is relative to the accumulated category library. The more experience (the richer the category library), the faster the categorization step, and the more decisions fall into the near-zero cost tier. This is exactly how expert engineers get faster over time: not by running faster checklists, but by recognizing categories that previously required explicit analysis.

This is fundamentally different from a formula with a threshold. A formula applies uniform processing to every decision that clears the threshold. A category library gets cheaper to use as it grows, and the cheapest outcomes are the most common outcomes (because familiar problems are common).


7. The Alternative Proposal: Architectural Intelligence as an Accumulating Asset

Given the critique above, the right mechanism is not a formula, not a checklist, and not a trigger. It is a growing architectural intelligence layer — a system that accumulates experience, improves its own category library, and applies that library proportionally.

The components:

Component 1 — Category Library (persistent, growing): A structured knowledge base of problem categories, each with: (a) recognition features — how to identify this category when you see it, (b) known design patterns — the viable options for this category, (c) failure topology — what goes wrong with each pattern, (d) category-level invariants — architectural rules that prevent entire failure classes, (e) incident links — real kaizen incidents that belong to this category. This is not a checklist. It is a retrieval-augmented reasoning substrate. When the agent encounters a problem, it retrieves the relevant category and loads the failure topology before any evaluation begins.

Component 2 — Hypothesis Formation Protocol (session-specific): Before any non-trivial design commitment, the agent states one falsifiable hypothesis per candidate design, then runs the cheapest possible falsification attempt. Designs that are falsified are eliminated. Designs that survive are compared on their residual tradeoffs. This is one protocol, not a 5-step procedure. "State your hypothesis. Try to break it. If you can't break it, it survives."

Component 3 — Category-Level Architecture Review (upfront, rare): When starting a new system or major component, do a category audit: "What categories of problems does this system create? Which categories are already prevented by the architecture? Which are still open?" This is the staff engineer's "architecture review" translated into the agent's terms. The output is not a design decision — it is a set of invariants: rules that make whole categories structurally impossible. These invariants are added to the system design document and enforced by hooks or conventions.

Component 4 — Incident-to-Category Feedback Loop (after every failure): When a design choice fails, the failure is not just filed as an incident. It is classified into a category. If the category exists in the library, the failure topology is updated. If the category doesn't exist, a new category is created. This is how the library grows. The feedback loop converts incidents into category-level intelligence that benefits all future sessions — not just the one that made the mistake.

Component 5 — Proportional Cost by Category Match (automatic): If the problem matches a category cleanly and one option is clearly non-dominated in that category, proceed immediately with a one-sentence log entry. If the problem matches a category but multiple options survive the failure topology, run a focused falsification cycle (5 minutes). If the problem doesn't match any category, treat it as a novel problem and run full hypothesis testing (20 minutes) and create a new category entry. Cost is proportional to novelty.

This proposal addresses what Round 1 missed:

  • It accumulates experience (Category Library grows from incidents).
  • It operates at the category level, not the instance level.
  • It includes genuine hypothesis testing with falsification.
  • It is proportional — familiar problems cost near-zero.
  • It gets better over time, because the library grows and more decisions fall into the cheap tier.
  • It is adaptive — when a novel failure mode appears, it expands the library rather than failing silently.

The DPS formula can exist inside this as one heuristic for scoping which decisions need a focused falsification cycle. The Design Stance Protocol's steps become the falsification protocol. But both are subordinate to the category-level architecture review that happens upfront and converts instance-level decisions into category-level invariants wherever possible.


8. The Core Objection to This Proposal

Before Round 3 rebuts this, let me name the strongest objection to the proposal above: who builds the category library?

The library starts empty. The first session has nothing to retrieve. The first few incidents create categories, but those categories are only as good as the incident-to-category mapping. And mapping incidents to categories requires the judgment that the agent doesn't yet have. There's a bootstrapping problem: the thing that would make the agent competent requires the competence to build it.

The honest answer: this is a seeded knowledge problem. The initial category library is not built from agent experience. It is built from Aviad's experience — extracted through the critical incident debriefing technique the cognitive ethnography describes. The first version of the library is a compiled artifact of human expertise, structured for machine retrieval. Subsequent sessions grow it from incidents.

This is uncomfortable because it means the quality of the initial library determines the quality of the agent's architectural intelligence for many sessions. But it is not more uncomfortable than the alternative — the DPS formula, which is also seeded from Aviad's experience (the five risk categories), also starts with zero coverage of novel failure modes, and also doesn't improve itself from incidents in any structured way.

The category library at least has a growth mechanism. The DPS formula doesn't.


This document is a second-round contrarian antithesis. It is designed to be wrong in interesting ways. The synthesis is not yet visible. Round 3 should not simply average this with Round 1 — it should find the resolution that neither round reached.

Experience Accumulation Systems: An Information Architecture for Stateless Agents

Round 2 — March 2026


1. The Experience Gap, Precisely Stated

The gap is not "no memory." It is more specific: at design time, the agent lacks calibrated failure-mode priors indexed to this codebase's specific failure history.

An experienced engineer starting a session on kaizen already knows three things the agent does not:

A. Which abstract design categories have already failed here. Not "state resilience is a known problem class" in the abstract, but "specifically in this repo, late-binding of review findings to session lifecycle has caused data loss twice." This is episodic, indexed, and failure-weighted.

B. That certain surface-plausible designs are traps. The orchestrator-batch pattern looks correct. It is correct in the general case. It fails in the specific context of session-bounded agents. The experienced engineer has the negative exemplar: a prototype that looks right but fails in this system's specific operating conditions. The agent has the abstract principle but not the indexed negative exemplar.

C. Which of the current system's seams are fragile. Experienced engineers accumulate a mental model of where the cracks are — not derived from first-principles reasoning, but from direct observation of where things broke before. In kaizen's case: worktree state isolation, stop-gate enforcement, hook weight under Stop events. These are the seams that have cracked. Each new design decision that touches these seams should activate heightened scrutiny.

The concrete reference case (store-review-findings failure): the agent knew that state resilience matters. It did not know that this specific pattern — findings accumulated in orchestrator memory, flushed at end of session — had failed before in this codebase. The missing link was not the principle. It was the indexed negative exemplar: "review findings stored by orchestrator → lost on crash" is a documented failure, labeled type:state-resilience, filed in the kaizen issue archive. But there was no retrieval path from design-time context to that entry.

This is the experience gap: the absence of indexed, retrieval-ready negative exemplars specific to this codebase.


2. What Currently Exists in Kaizen

Memory files at /home/aviadr1/.claude/projects/-home-aviadr1-projects-kaizen/memory/: 18 files, each a standalone feedback or project note with YAML frontmatter (name, description, type) plus prose. They cover debugging heuristics, infra decisions, environment-specific traps. What they capture: lessons that were worth preserving manually. What they miss: automatic capture — every file was written by an agent or human explicitly choosing to write it. There is no systematic coverage guarantee. The MEMORY.md index is updated manually. Failures that went unreflected produce no memory entry.

The reflection system (/kaizen-reflect): runs post-work, classifies impediments, files GitHub issues, and can write reflection attachments to PRs/issues via cli-section-editor.ts. What it captures: classified impediments with escalation levels (L1/L2/L3). What it misses: structured failure signatures in machine-readable form. The current output is prose in GitHub issue bodies — discoverable by humans browsing issues, not by an agent executing a design query at the start of a session.

GitHub issues archive: labeled, with taxonomy in docs/issue-taxonomy.md. Labels include type:state-resilience, type:regression, type:pattern. What it captures: a comprehensive incident record. What it misses: a retrieval path. At design time, no existing mechanism says "search these issues for failure signatures matching this design."

CLAUDE.md policies (.claude/kaizen/policies.md): 10 explicit rules, each derived from a past failure. These are the highest-signal distillations — failures that recurred enough to earn categorical rules. What they miss: the intermediate layer — failures that have happened 1-2 times but haven't yet earned a policy, plus the specific design anti-patterns rather than the general rules.

The DPS formula (from r1-decision-theory.md): the Recurrence weight R explicitly calls for "has this category failed in recent history?" — but provides no mechanism to answer that question. The formula assumes the agent can query the incident archive. Currently it cannot.

The gap: a retrieval path from design-time context to relevant past incidents, structured for agent consumption.


3. The Experience Architecture

The core design: a Failure Signature Index (FSI) — a structured, machine-readable catalog of past failures indexed by the design properties that caused them.

Schema per entry:

{
  "id": "fsi-042",
  "github_issue": 713,
  "date": "2026-02-14",
  "title": "Review findings lost on orchestrator crash",
  "failure_category": "state-resilience",
  "surface_trigger_keywords": ["store", "findings", "session", "orchestrator", "flush"],
  "design_anti_pattern": {
    "shape": "accumulate-then-flush",
    "description": "State accumulated in orchestrator memory, written only at task completion",
    "trap_condition": "session boundary or crash before flush"
  },
  "preferred_pattern": {
    "shape": "write-through",
    "description": "Each sub-agent writes its findings immediately on completion"
  },
  "seams_involved": ["orchestrator-subagent-boundary", "session-lifecycle", "review-gate"],
  "irreversibility": 3,
  "confirmed_recurrences": 1,
  "confidence": 0.8,
  "last_confirmed": "2026-03-10",
  "status": "active"
}

Storage location: .claude/kaizen/failure-signatures/ in the kaizen repo — one JSON file per entry named fsi-{id}.json, plus index.json with flattened keyword, category, and shape fields for all entries. This is a flat file store, no database.

Trigger for capture: After reflection files a GitHub issue with an FSI-eligible label (type:state-resilience, type:regression, type:pattern), the /kaizen-reflect skill runs a structured extraction: "Given this incident, fill out the FSI schema." Output is committed as a new FSI entry. This is mandatory when the label condition is met — not optional.

Bootstrap entries: 5 entries from existing incidents to establish the store: the review-findings loss incident, the OOM verify-hook incident (stop hooks must be lightweight), the WSL2 /proc hang, the cross-worktree state contamination issue, and the hook false-positive KAIZEN_UNFINISHED grep pattern. These cover three of the known risk categories with real data.


4. The Retrieval Problem

At design time — when the agent has the task description and is about to begin implementation — it needs to surface relevant FSI entries before committing to a design.

Three retrieval approaches and their failure modes:

Keyword matching against surface_trigger_keywords: Fast, zero-infrastructure, works in a shell command. Failure modes: vocabulary mismatch ("buffer" vs. "accumulate"), false positives ("store" appears in most tasks), misses structural similarities with different vocabulary. Verdict: use as pre-filter, not primary retrieval.

Category matching: When DPS has already classified the decision into a risk category, FSI_ENTRIES WHERE failure_category IN (active_categories) retrieves all relevant entries directly. This is the right primary path for decisions that have already triggered DPS evaluation.

Shape matching: The design_anti_pattern.shape field encodes design topology: "accumulate-then-flush," "shared-state-no-contract," "late-bind-to-session." A fixed vocabulary of ~20 shapes covers most recurring design structures. The agent labels its proposed design shape and retrieves FSI entries with the same shape. More robust than keywords; doesn't require prior category classification. Failure mode: the shape vocabulary must be maintained as new failure modes produce new shapes.

Practical retrieval pipeline:

1. Compute DPS score.
2. If DPS < 1: skip retrieval, proceed.
3. If DPS >= 1: run category lookup via index.json (sub-second).
4. If proposed design shape is determinable: add shape-match results.
5. De-duplicate, sort by recurrence count descending.
6. Inject top 3 results into agent context before implementation.

Shell command: npx tsx src/cli-experience.ts query --category state-resilience --shape accumulate-then-flush

The entire pipeline completes in under 5 seconds on a local filesystem with 500 FSI entries. If retrieval is slow, agents skip it. Speed is the adoption condition.


5. Category Extraction

After N >= 3 FSI entries share a design_anti_pattern.shape, a promotion pass clusters them into named canonical patterns.

Pipeline (runnable as npx tsx src/cli-experience.ts promote-patterns):

  1. Group FSI entries by failure_category x design_anti_pattern.shape.
  2. For groups with count >= 3: generate a canonical pattern description.
  3. Write to .claude/kaizen/design-patterns/antipattern-{shape}.md.
  4. Add the pattern name to the DPS formula's risk categories if not already covered.

The key difference from classic expert system rule extraction: patterns are extracted from empirical incidents, not from expert introspection. The pattern is valid because failures confirm it, not because Aviad articulated it. This survives the "residue that cannot be articulated" problem from r1-cognitive-ethnography.md — the features that triggered the expert's anomaly detector but couldn't be verbalized are now reconstructed from failure evidence, not recovered from memory.

The loop: incidents → FSI entries → clustering → named patterns → updated risk categories. The loop requires a trigger (a periodic auto-dent run or manual invocation) but is otherwise automatic. Promotion frequency: whenever FSI count grows by 10 or more entries.


6. Adaptive Calibration

Experience stores go stale in two ways: false positives (FSI entries that flag a safe design as dangerous) and atrophied entries (one-off incidents whose lessons no longer apply).

Positive signal: When an FSI entry is retrieved during a design pause and the agent selects the preferred pattern, record this:

{"date": "2026-03-15", "outcome": "preferred_pattern_selected"}

After 3+ retrievals with consistent preferred-pattern selection, confidence increases. High-confidence entries are surfaced first.

False-positive correction: The /kaizen-reflect skill can flag an entry: npx tsx src/cli-experience.ts flag-entry --id fsi-042 --reason "codebase changed". Flagged entries are deprioritized but not deleted — the historical record remains for audit.

Staleness detection: Each entry has a last_confirmed date, updated whenever retrieval results in a confirmed useful warning. Entries older than 90 days without confirmation are marked status: stale and excluded from retrieval by default. The threshold is configurable in kaizen.config.json:

"experience": { "fsi_stale_days": 90, "retrieval_top_n": 3 }

Anti-accumulation guard: The most dangerous failure mode of an experience store is false authority — an old entry retrieved with high confidence leading the agent to avoid a design that is now correct. When an agent selects the anti-pattern despite an FSI warning, a one-sentence justification is required and stored in the retrieval log for Aviad to review. This makes the store's influence auditable.


7. The Proportionality Constraint

Target latency: < 3 seconds for a full retrieval pipeline on 500 entries. Achievable with a flat index.json — the agent reads one file, filters in memory, then reads 1-3 matching full entries by ID. No database, no vector index, no network call.

Cost gating by DPS score:

  • DPS < 1: No retrieval. Proceed immediately.
  • DPS 1-2: Category matches only. Read index.json, filter, surface titles. 3-5 seconds total.
  • DPS > 2: Full retrieval including shape-match and top-3 detailed entry reads. 10-20 seconds. Acceptable: a DPS > 2 decision already triggers a 5-10 minute design pause; 20 seconds of retrieval is invisible overhead.

When to skip entirely: If the FSI store has fewer than 5 entries, skip retrieval and note the store is immature. Don't create a retrieval ceremony around an empty catalog.

The no-embedding rule: No vector database, no semantic search, no embedding infrastructure. The FSI is a flat JSON catalog indexed by controlled vocabulary. For a catalog of 50-500 entries, categorical and shape-based lookup is faster, more debuggable, and more auditable than vector similarity. Vector search fails in non-obvious ways (embeddings that are semantically close but structurally different). If the FSI exceeds 1000 entries and keyword recall degrades, revisit.


8. Concrete Implementation Proposal for Kaizen

Add:

src/cli-experience.ts — TypeScript CLI with subcommands:

  • add-entry — takes incident description or issue number, fills schema, writes file, updates index.json
  • query --category X --shape Y — outputs matching entries as markdown for injection into agent context
  • flag-entry --id X --reason Y — marks an entry for review
  • promote-patterns — clusters entries, generates canonical pattern docs

.claude/kaizen/failure-signatures/ — flat directory: index.json + individual fsi-{id}.json files. Bootstrap with 5 entries from existing incidents.

Change:

/kaizen-reflect SKILL.md — after gh issue create succeeds with an FSI-eligible label: npx tsx src/cli-experience.ts add-entry --from-issue {N}. One additional step, mandatory on label match. This makes FSI capture automatic.

The DPS formula's Recurrence weight R — compute empirically: npx tsx src/cli-experience.ts query --category {category} --count. R = 0 if count is 0, R = 1 if count >= 1, R = 3 if count >= 3. This converts R from a self-assessed variable to an evidence-grounded one.

The Design Stance Protocol Step 4 (r1-cognitive-ethnography.md) — "Archive retrieval" step now has a concrete command: npx tsx src/cli-experience.ts query --category {active_category} --shape {proposed_shape}.

Do not change:

Memory files — they serve session-initialization context (injected at conversation start). The FSI serves design-time retrieval (queried mid-session). These are complementary, not redundant. Memory files answer "what general heuristics apply?"; FSI entries answer "which specific designs have failed here before?"

CLAUDE.md policies — they are the promoted, high-confidence layer. FSI entries are the intermediate layer: failures that have happened 1-2 times and whose lessons are documented but not yet categorical. When an FSI entry's confirmed_recurrences reaches 3+, a human review determines whether it earns promotion to a CLAUDE.md policy.


Synthesis

The experience gap is a retrieval gap, not a storage gap. Kaizen already accumulates experience in GitHub issues, memory files, and PR reflections. The missing piece is a structured, fast retrieval path from design-time context to relevant past failures.

The FSI is that retrieval path. It is not new knowledge — it is the same knowledge that already exists in GitHub issues, re-encoded in a schema optimized for agent consumption at design time. The encoding work is the cost; the return is that every future design session can query "which designs like this one have failed here before?" and get an answer in under 5 seconds.

The r1-cognitive-ethnography identified case-based reasoning as the cognitive mechanism most analogous to expert episodic memory. The FSI is case-based reasoning made concrete: a case library, a retrieval function, and an adaptation step (the preferred pattern). The cases are Aviad's actual incidents, promoted from GitHub issues into a schema that agents can query.

The r1-decision-theory identified that the Recurrence weight R in the DPS formula is the variable most likely to catch known failure modes. The FSI makes R empirical. That is the practical payoff: one variable in one formula becomes grounded in evidence instead of agent self-assessment. An agent that computes R by querying the FSI is, in a narrow but real sense, learning from past sessions.

The improvement system improves itself: incidents → FSI entries → empirical R scores → better DPS decisions → fewer incidents.

Kaizen principle: the horizon you can name, you can climb. The FSI names the craters.


This is a second-round design exploration. Claims are hypotheses. Test against real usage. When the FSI produces a false positive that wastes a design pause, update the staleness model. When it misses a failure it should have caught, add the missing entry.

The Staff Engineer's Mind: A Behavioral Model

Round 2 — Staff engineer cognition as empirical subject March 2026


1. The Mental Model in Motion: A Walk-Through

A staff engineer at a mid-sized company is handed a ticket: "Add support for webhook retry with exponential backoff." A junior engineer reads this and starts writing a retry loop. The staff engineer reads it and does something different. Watch the sequence.

First 30 seconds: Category recognition before implementation. The staff engineer doesn't think "how do I implement retry?" They think "what category is this?" The answer arrives fast: distributed systems reliability — the category of "systems where partial failure leaves state inconsistent." This isn't a conscious search. It fires the way "that's a dog" fires when you see a dog. The category classification is nearly instantaneous.

Next 2 minutes: Known failure topology for this category. With the category named, associated failure signatures surface automatically. For webhook retry: idempotency problems (re-delivering a request changes customer state twice), thundering herd (all retries fire at the same wall-clock time), missing jitter (backoff collides under load), unbounded retry depth (fills a queue until OOM), no dead-letter path (lost events are invisible), cross-service state divergence (receiver processed it; sender thinks it failed). The staff engineer isn't generating this list by reasoning — they're reading it out of something resembling a lookup table built from prior incidents.

Next 3 minutes: Option space sketch. Three designs surface: (A) synchronous retry in-process, (B) async retry queue with worker, (C) caller-side retry with a webhook signature for idempotency. For each, the failure mode that defeats it: A fails under long receiver latency and process crashes mid-retry; B solves durability but requires queue infrastructure and introduces ordering ambiguity; C shifts retry logic to the client, which may not be in our control. This sketch takes three minutes. Not thirty.

Decision and proportionality check. The staff engineer looks at ticket scope. Is this a new product feature or a wrapper on an existing system? If the existing system already has a queue, B is obvious — it reuses infrastructure. If this is a small service with no queue, A with jitter and bounded retries might be right-sized. C is appropriate for webhook ecosystems with stable, controllable clients. The choice is driven by fit to existing architecture, not abstract correctness.

What they don't do. They don't write a design doc for a two-day ticket. They don't spike all three options. They don't convene a review meeting. They spend five minutes in their head, pick B with a note in the ticket about the idempotency requirement, and start implementing. If they're wrong — if the existing system has no queue — they'll know in ten minutes when they look at the infrastructure, and they'll re-route.

The pattern: category recognition → failure topology lookup → option space sketch → proportional commitment. Under ten minutes before a line of code is written.


2. The Category Library: What It Is and How It's Built

"Category thinking" is not a metaphor. It is a specific cognitive structure: a library of situation types, each with an attached failure signature, a set of known solutions, and markers for where standard solutions fail.

Here are ten real engineering categories, stated the way they live in an expert's head:

"Shared mutable state across async boundaries." Two things write to the same thing without synchronization. Every design in this category has a race condition somewhere. The question is not whether there is a race; it is whether the race matters and whether you can tolerate the outcome when it fires.

"Consistency at the seam between sync and async components." A sync caller hands off to an async system. The sync caller gets a 200 but the async system hasn't committed yet. Someone observes the inconsistency in the window. The standard failure: the UI shows success but the background job fails silently.

"Implicit ordering assumptions in distributed systems." Two services produce events consumed by a third. The consumer assumes ordering the producers don't guarantee. Works in the happy path because latency is low. Breaks under network partition or queue backup.

"Schema coupling between producer and consumer." A producer serializes a struct; a consumer deserializes it. They are implicitly coupled on the schema. Adding a required field in the producer breaks all existing consumers. The category failure: "we changed the API and didn't know there were twelve consumers."

"Late binding of critical state to session lifecycle." A process accumulates state representing real-world progress, and that state only becomes durable at the end of the session. Process death before the end = everything lost. Invisible in the happy path; catastrophic on crash.

"Authorization boundary at the wrong layer." Auth checks happen at the API layer but not at the data layer. Direct database access bypasses them. Works until something other than the API touches the database — a script, a migration, a background job.

"Cache invalidation with distributed writers." Multiple services write to a shared resource. A cache sits in front. Writer A invalidates the cache after its write. Writer B's write happens before A's invalidation reaches all nodes. The failure: reads return data that appears consistent but precedes a committed write.

"Retry without idempotency." A caller retries a failed request. The request is not idempotent. The retry triggers the side effect twice: the charge is billed twice, the email is sent twice, the record is inserted twice. Works perfectly in tests because tests don't fail the first call.

"Configuration drift between environments." A service is configured differently in staging and production. Staging tests pass. Production behaves differently because the config controls a behavior staging never triggered. The failure: works in staging, breaks in prod, the diff is invisible until someone reads env vars.

"Observability gaps at high-value failure boundaries." A system has no logs, metrics, or traces at the boundary where the most expensive failures occur. Works fine. Then something breaks and there is no data to diagnose it. The cost of the failure is multiplied by the cost of diagnosis without instruments.

These categories are not invented — they are distilled from real incidents. The staff engineer who has seen schema coupling bite them three times across two companies carries this category with full texture: which teams were surprised, how long diagnosis took, what the mitigation looked like, what actually fixed it versus what masked the problem.

How the library is built. Categories are not learned from textbooks. They are crystallized from incidents. Something breaks, you spend three days debugging, you understand the root cause, you generalize it slightly, and a new entry is added. The generalization step is what matters — it determines whether you learned "this specific Redis instance at this specific company had this specific bug" (useless forward) or "async systems that persist state late in the session lose data on crash" (transfers everywhere).

Engineers who grow fast make the generalization step aggressively. Engineers who plateau learn the specific incident and not the category.


3. Hypothesis Formation and Testing in Practice

A staff engineer approaching an unfamiliar system does not start with solutions. They start with hypotheses about where the system will fail.

The format is specific: "My hypothesis is that X will happen when Y, because of Z." Not "I think there might be a problem with caching." But: "My hypothesis is that this cache will serve stale data under high write load because the invalidation callback is synchronous and blocks the writer, creating a window where other nodes read before the invalidation propagates."

The specificity matters for two reasons. First, a specific hypothesis generates a specific experiment. "There might be a caching problem" requires a fishing expedition. "The invalidation callback blocks the writer" requires a single targeted test: add instrumentation to the callback, run a write-heavy load scenario, observe block duration and window size.

Second, a specific hypothesis is falsifiable. If you run the experiment and the callback is non-blocking, you learn something and update the hypothesis. Vague hypotheses absorb contradicting evidence without updating — you can always say "maybe it's a different kind of caching problem."

Minimum valid experiment. Staff engineers are ruthless about the size of the experiment required to test a hypothesis. The question is always: "what is the smallest signal that confirms or disconfirms this?" For architectural hypotheses, valid experiments include:

  • A spike implementation of the riskiest component, discarded after validation
  • A paper walk-through with a peer who has seen the category before ("does this remind you of anything?")
  • An adversarial simulation: trace the system state after a crash at each step
  • A load test at 10x expected volume on the one bottleneck the hypothesis predicts
  • An instrumentation pass that surfaces the metric the hypothesis predicts will be anomalous

What is never a minimum valid experiment: building the full system and seeing if it breaks in production. The cost of that experiment is the cost of the full implementation plus the cost of the failure.

Staff engineers do not test hypotheses by shipping. They test by minimizing the delta between "what I need to know" and "what the experiment can tell me."


4. Design Space Navigation: Efficient Without Getting Lost

The pathology exists in both directions: junior engineers pick the first solution; over-thinkers enumerate forty-seven alternatives and build a matrix. Staff engineers do neither.

The heuristic for good-enough exploration: you need at least two alternative designs, explicitly articulated, before you commit to one. This is not arbitrary. With one design, you're executing. With two, you're choosing. The act of naming a second design changes your epistemic relationship to the first — you see it as a choice rather than a fact.

Three or four alternatives is usually enough. Beyond that, you're generating marginal variants and the exploration cost exceeds the expected benefit of finding a better design.

The efficient sketch. Each alternative gets: one sentence for what it is, one sentence for what it optimizes, one sentence for where it breaks. That's the whole sketch. Not a detailed design. Coordinates in design space. "Option B: async queue. Optimizes durability and retry decoupling. Breaks when queue consumer falls behind and memory fills, or when ordering is assumed."

When to stop exploring. Two signals. First: you've found an option that dominates the others on the dimensions you care about. Second: you've run out of genuinely different points in the design space — the remaining options are variations on existing ones, not new coordinates. Forty-seven options are really four clusters. Stop at the clusters.

The commitment heuristic: if you cannot articulate what evidence would change your choice, you're not exploring — you've already decided and you're rationalizing. The staff engineer who is genuinely exploring can state: "I'll go with B unless the infrastructure audit shows we don't have a queue, in which case A."


5. The Experience Accumulation Mechanism

The mechanism is not years of service. It is not seniority. It is the density and quality of the feedback loop.

An engineer who spends three years maintaining a stable system with no failures learns almost nothing about failure categories. An engineer who spends one year on-calling a system with frequent failures learns fast. The variable is not time; it is the number of incidents encountered plus the quality of the post-incident analysis.

What builds the category library fast:

  • On-call rotation in a high-incident system (direct exposure to failure signatures)
  • Post-mortems with rigorous root-cause analysis (forced generalization, not just mitigation)
  • Code review across many systems (pattern exposure without paying the incident cost)
  • Reading postmortems from other companies (Google, Amazon, Netflix SRE blogs are category libraries written down)
  • Debugging other people's systems under time pressure (your mental model is tested against reality)

What does not build it:

  • Greenfield development with no production incidents
  • Systems with extensive guardrails that prevent failure
  • Working on only one technology stack for years
  • Never being on the debugging end of a production issue

The differentiating factor between engineers who grow fast and those who plateau: the fast growers aggressively generalize. After every incident, they ask "what is the category of this failure?" and update a mental model. The slow growers learn "this specific Redis instance had this specific problem on this specific date" and do not update a model.

The second differentiating factor: willingness to be wrong publicly. Engineers who never propose designs publicly never get feedback that challenges their categories. Their library grows from their own incidents only, which is a small and biased sample.


6. Proportionality in Practice

The calibration question: how much design thinking does this problem warrant?

The signals staff engineers use, in rough priority order:

Irreversibility. If the design decision creates state that will be hard to migrate — a database schema, an external API contract, a wire format — it warrants more upfront thinking. If the decision is trivially reversible (a function signature within a single service), it warrants less.

Blast radius. How many things break if this design is wrong? A decision that affects one service's internal logic has small blast radius. A decision that sets an interface used by twelve callers has large blast radius.

Novelty. Am I in known or unknown territory? Known territory means the category is familiar and the failure topology is understood. Unknown territory means the category is new. In unknown territory, you slow down and form explicit hypotheses.

Cost of the pause relative to cost of the task. A 30-minute feature gets 5 minutes of design thinking. A 3-week feature gets 2 days. The ratio is roughly 15% of implementation time, scaled by irreversibility. A 30-minute feature with an irreversible schema change might get 30 minutes of design thinking.

The "5 minutes then decide" rule. For most decisions, staff engineers will spend five minutes thinking about design and then commit. Not because five minutes is always enough. But because the expected value of additional thinking past the point where you've identified the key failure modes and considered two alternatives is low. The information from actually implementing is usually more valuable than continued design exploration.

The anti-pattern to avoid: spending two days on design for a feature with a reversible implementation and small blast radius. The cost of over-thinking is real — it consumes resources that could go to implementation feedback, and it produces documents that are stale before they're finished.


7. Translating to AI Agents: The Minimum Viable Scaffold

The goal is not to give an AI agent the subjective experience of being a staff engineer. The goal is output behavior that is functionally equivalent. What does that mean concretely?

The agent behaves like a staff engineer if:

  • Before implementing, it names the category of the problem and the associated failure topology
  • It generates at least two alternative designs, with one-sentence failure modes for each
  • It applies a proportionality check and either proceeds or explicitly notes the design choice
  • When it encounters unknown territory (no category match), it slows down and forms explicit hypotheses
  • It runs an adversarial simulation ("what happens if this process dies at step N?") before committing to designs with late state persistence

The minimum scaffolding to produce this behavior:

Category injection. Provide the agent with a curated category library at task initialization. Not a checklist — a category library. Each entry: situation signature, failure topology, known-good mitigations, where those mitigations fail. Ten to twenty entries cover the most common categories. The agent uses this as a lookup: does this problem match a known category? What does the failure topology say?

Option forcing at task start. A structural prompt that fires before implementation begins: "Name two alternative designs for this task. For each, state what it optimizes and where it breaks. Then state your choice and why." This is the mechanical equivalent of the expert's option-space awareness — it forces the agent into choosing-mode rather than executing-mode before a line of code is written.

Adversarial simulation trigger. For tasks that touch state persistence, session boundaries, or shared mutable state: "Trace the system state after a crash at each step. What is lost? Is the loss acceptable?" This encodes the expert's learned reflex to simulate crash scenarios for this class of decision.

Proportionality gate. A quick self-assessment: "Is this decision reversible? What is the blast radius if it's wrong?" If reversible and small blast radius, proceed. If irreversible or large blast radius, surface the design choice explicitly before implementing.

The category library is maintained recursively. When a design choice fails, the incident is analyzed for what category it falls into. If the category exists, the entry is updated. If it doesn't, a new entry is added. This is the mechanism for accumulation over time — the equivalent of the senior engineer's growing failure-library.


8. What's Trainable Versus Irreducibly Experiential

Trainable (encodable in prompts and tools):

  • Category recognition, given a curated category library
  • Option generation and comparison (mechanical steps that don't require intuition)
  • Adversarial simulation (can be prompted explicitly)
  • Proportionality calculation, given explicit signals (irreversibility, blast radius)
  • The format of design thinking: name the category, sketch options, state failure modes, choose

These can be encoded. An agent given a good category library and structural prompts will exhibit behavior that approximates staff engineer judgment on known categories.

Requires genuine experience (or a functional substitute):

  • Knowing when something "doesn't fit the prototype" — the anomaly detection that fires before articulation. This requires a baseline of expected patterns built over time. An agent without persistent episodic memory cannot build this the same way a human does.
  • Calibrating confidence in novel territory. Staff engineers know when they're in unknown territory because they've felt the texture of known territory and can notice the difference. An agent cannot feel this contrast.
  • The weighting inside categories — which failure signatures are most dangerous in which context. This is tacit knowledge: built by exposure, not fully articulable as rules.
  • Cross-context transfer with emotional salience. A human engineer who burned on schema coupling in a payment system immediately recognizes schema coupling risk in an analytics pipeline, because the episodic memory carries the weight of the failure. An agent without persistent episodic memory requires the schema coupling category to be explicitly present in its injected library to trigger recognition.

The realistic ceiling. An agent with a good category library and structural scaffolding will match staff engineer judgment on known categories. It will miss novel failure modes that don't pattern-match to any library entry. It will also miss the calibration that comes from feeling the contrast between known and unknown — it will not automatically slow down in unknown territory the same way a human does, because it lacks the felt sense that marks the boundary.

The gap is not unbridgeable. It is bridgeable through accumulation: the kaizen incident archive is a functional substitute for episodic memory if it is retrieved at design time, indexed by failure signature, and actively updated when new categories are discovered. The question is whether the retrieval and indexing mechanism is good enough to simulate the human's spontaneous pattern-matching.

This is the bet: structured category injection plus option forcing plus adversarial simulation covers roughly 80% of the cases where staff engineer judgment diverges from junior engineer execution. The remaining 20% requires either genuine episodic memory or a sufficiently dense and well-indexed incident archive to serve as its substitute.

The 80% is worth building for. The 20% gap is worth naming honestly and not pretending the scaffolding closes it.


This document is a second-round behavioral model. Claims about trainability are hypotheses. The kaizen principle applies: when an agent with this scaffold fails in a way the model predicts shouldn't happen, update the model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment