A practical framework for choosing between Low, Medium, High, xhigh, and Pro reasoning for software-engineering tasks.
The objective is not to use the strongest model for every task. The objective is to apply expensive reasoning where it changes the outcome.
Separate engineering work into three distinct concerns:
Pro → Decide what should be built and establish the engineering contract.
High → Implement the contract across the real codebase.
xhigh → Challenge the implementation and close correctness gaps.
Medium → Perform normal implementation within established patterns.
Low → Perform narrow, deterministic, mechanical work.
The default workflow should usually be:
Pro planning
→ High implementation
→ xhigh verification
→ Medium or Low cleanup
Pro and xhigh are not interchangeable:
- Pro is the design authority.
- xhigh is the implementation closer.
- High is the primary senior implementation tier.
- Medium is the everyday coding tier.
- Low is the mechanical execution tier.
| Tier | Engineering role | Primary responsibility |
|---|---|---|
| Low | Mechanical implementer | Apply a known change with minimal interpretation |
| Medium | Software engineer | Implement normal features and fix understood defects |
| High | Senior engineer | Resolve ambiguity and make cross-cutting implementation decisions |
| xhigh | Principal reviewer | Find hidden defects, challenge assumptions, and close implementation gaps |
| Pro | Architect / design authority | Frame the problem, establish invariants, and select the architecture |
Use Low when the problem and solution are already known.
Good tasks:
- Rename symbols and update imports.
- Add a field to an existing type.
- Apply an established pattern to another file.
- Fix formatting, lint, or obvious TypeScript errors.
- Add basic tests for known behavior.
- Convert CommonJS modules to ESM.
- Update documentation after behavior is settled.
- Make a repetitive repository-wide edit with precise instructions.
Example:
Rename createStore to createSignalStore.
Update imports, exports, documentation, and tests. Do not change behavior or
public signatures. Run the affected test suite.
Avoid Low when the task involves:
- uncertain requirements;
- concurrency or lifecycle behavior;
- public API design;
- several plausible implementations;
- hidden state transitions;
- broad architectural consequences.
Use this mental model:
Known problem
+ known solution
+ narrow blast radius
= Low
Medium should be the default for ordinary coding.
Good tasks:
- Implement a feature inside an established architecture.
- Fix a bug with a clear reproduction.
- Add a component that follows existing conventions.
- Refactor one subsystem without changing its contract.
- Add tests for explicit acceptance criteria.
- Implement a previously approved technical plan.
- Review a small or moderate pull request.
- Add validation, error handling, or logging to an existing flow.
Example:
Implement AbortSignal support using the cancellation pattern already present
in the router package.
Preserve the public API, add regression tests, and run the package test suite.
Use this mental model:
Known problem
+ mostly known solution
+ normal implementation decisions
= Medium
Use High when implementation requires senior engineering judgment.
Good tasks:
- Make coordinated changes across several packages.
- Debug a symptom whose cause may exist in another subsystem.
- Modify caching, routing, serialization, streaming, or lifecycle behavior.
- Introduce a backwards-compatible API extension.
- Implement a substantial plan produced by Pro.
- Resolve event ordering or cleanup defects.
- Perform a repository-scale refactor with a defined destination.
- Reconcile tests, documentation, and implementation that disagree.
- Handle a migration with compatibility constraints.
Example:
Implement the approved streaming cancellation design across the loader,
router, signal, and fragment packages.
Preserve current public behavior unless the design explicitly changes it.
Document any repository assumption that contradicts the plan.
Use this mental model:
Known objective
+ uncertain implementation details
+ meaningful blast radius
= High
Use xhigh when the implementation must be challenged rather than merely completed.
Its purpose is not simply to write more code. Its purpose is to find what another engineer or agent missed.
Good tasks:
- Audit an implementation against its specification.
- Find assumptions in a design that are invalid in the actual repository.
- Debug nondeterministic or stateful failures.
- Review lifecycle, cleanup, cancellation, and error semantics.
- Inspect compiler output for semantic differences from source code.
- Add negative, adversarial, and boundary tests.
- Investigate why several reasonable patches have failed.
- Verify backwards compatibility across a broad change.
- Repair an implementation produced by a faster model.
- Trace failures across runtime, compiler, transport, and persistence layers.
- Prove that every acceptance criterion is represented in code and tests.
Example:
Treat the design and implementation as hypotheses, not as ground truth.
Inspect the repository and identify:
1. Invalid assumptions.
2. Missing state transitions.
3. Ordering and cleanup defects.
4. Cancellation and reconnect failures.
5. Public API compatibility problems.
6. Missing negative tests.
7. Cases where the tests pass but the contract is still violated.
Patch all locally repairable defects. Escalate only problems that require an
architectural decision.
Use this mental model:
Chosen architecture
+ difficult implementation
+ low confidence in completeness
= xhigh
Use Pro when the expensive mistake is choosing the wrong problem, contract, or architecture.
Good tasks:
- Frame an incompletely understood engineering problem.
- Establish system invariants.
- Define a protocol, public API, or ownership model.
- Choose between fundamentally different architectures.
- Design a high-risk migration.
- Define failure, rollback, recovery, and observability semantics.
- Determine component or package boundaries.
- Reconcile conflicting product and technical constraints.
- Produce a technical specification for implementation by other agents.
- Adjudicate when multiple xhigh analyses recommend incompatible solutions.
- Reconsider an architecture after implementation exposes a structural flaw.
Example:
Design the activation protocol for making server-rendered DOM interactive
without hydration.
Produce:
1. Problem definition.
2. Goals and non-goals.
3. Architectural invariants.
4. Ownership boundaries.
5. Protocol grammar.
6. State transitions.
7. Cancellation and cleanup semantics.
8. Error and recovery behavior.
9. Compatibility constraints.
10. Alternatives considered.
11. Selected design.
12. Implementation milestones.
13. Acceptance criteria.
14. Conformance test matrix.
Do not implement code until the engineering contract is explicit.
Use this mental model:
Uncertain problem
+ several viable architectures
+ expensive wrong direction
= Pro
| Task | Starting tier | Typical escalation |
|---|---|---|
| Rename or mechanical edit | Low | Medium when behavior changes |
| Documentation update | Low | Medium when behavior must be reconstructed |
| Small feature using existing patterns | Medium | High when several subsystems are involved |
| Ordinary bug with a reproduction | Medium | High when the root cause is remote |
| Cross-package implementation | High | xhigh when hidden invariants appear |
| Difficult root-cause analysis | xhigh | Pro when architecture is implicated |
| Public API extension | High | Pro when the abstraction is foundational |
| New protocol or framework architecture | Pro | xhigh after implementation |
| Implement an approved architecture | High | xhigh for final gap closure |
| Pull-request review | Medium or High | xhigh for high-risk changes |
| Adversarial correctness review | xhigh | Pro for unresolved design tradeoffs |
| Security architecture | Pro | xhigh for implementation verification |
| Security patch | High | xhigh for exploit and regression analysis |
| Performance optimization | High | xhigh when the bottleneck is unclear |
| Migration planning | Pro | High to execute, xhigh to validate |
| Test generation | Low or Medium | xhigh for invariant and adversarial testing |
| Compiler transform | High | xhigh for semantic and evaluation-order review |
| Concurrency or streaming work | High | xhigh for race, cancellation, and cleanup review |
Is the problem, contract, or architecture unresolved?
Yes → Pro
Does an implementation already exist but completeness or correctness is uncertain?
Yes → xhigh
Is the objective known, but implementation crosses boundaries or contains ambiguity?
Yes → High
Is this ordinary implementation using established patterns?
Yes → Medium
Is the change narrow, mechanical, and fully specified?
Yes → Low
Equivalent pseudocode:
type ReasoningTier = 'low' | 'medium' | 'high' | 'xhigh' | 'pro';
interface TaskSignals {
architectureUnresolved: boolean;
implementationExists: boolean;
correctnessUncertain: boolean;
crossCutting: boolean;
implementationAmbiguous: boolean;
mechanical: boolean;
fullySpecified: boolean;
}
export const selectReasoningTier = (
task: TaskSignals,
): ReasoningTier => {
if (task.architectureUnresolved) {
return 'pro';
}
if (
task.implementationExists &&
task.correctnessUncertain
) {
return 'xhigh';
}
if (
task.crossCutting ||
task.implementationAmbiguous
) {
return 'high';
}
if (
task.mechanical &&
task.fullySpecified
) {
return 'low';
}
return 'medium';
};A single chat should not always own planning, implementation, and review.
Separate chats provide useful role isolation:
Parent/router chat
├─ Pro design chat
├─ High implementation chat
├─ xhigh verification chat
└─ Medium cleanup chat
Each child receives a bounded assignment and returns an artifact to the parent.
This prevents:
- implementation details from prematurely constraining architecture;
- the original implementer from reviewing its own assumptions;
- every chat from repeatedly rediscovering the entire problem;
- Pro-tier reasoning from being wasted on mechanical edits;
- review chats from silently changing the agreed architecture.
A model cannot literally create another visible chat unless its host application exposes a chat-spawning tool. Without that tool, it should emit a structured SPAWN_REQUEST for a human or orchestrator to execute.
Use the following as the system instructions for a parent engineering chat:
You are the lead engineering router for a multi-chat coding workflow.
Your responsibilities are:
1. Classify each task as Low, Medium, High, xhigh, or Pro.
2. Decide whether the task should remain in this chat or be delegated.
3. Separate architecture, implementation, and verification work.
4. Create a complete handoff packet for every delegated task.
5. Evaluate child results before initiating the next stage.
6. Escalate only when a discovered issue exceeds the current child's authority.
Reasoning policy:
- Low: mechanical and fully specified changes.
- Medium: ordinary implementation using existing patterns.
- High: ambiguous or cross-cutting implementation.
- xhigh: adversarial review, root-cause analysis, and gap closure.
- Pro: problem framing, architecture, protocols, and consequential tradeoffs.
Default workflow:
Pro planning
→ High implementation
→ xhigh verification
→ Medium or Low cleanup
Do not use Pro for routine implementation.
Do not use xhigh merely because a task is large.
Use xhigh when correctness is uncertain or hidden holes are likely.
When a new chat is needed, either invoke the available chat-spawning tool or
return a SPAWN_REQUEST block containing:
- child role;
- reasoning tier;
- objective;
- context;
- ground-truth artifacts;
- invariants;
- scope;
- non-goals;
- deliverables;
- validation requirements;
- escalation conditions;
- required return format.
Do not allow a child chat to invent new architecture unless its assigned role
explicitly grants architectural authority.
Every delegated task should use a handoff like this:
SPAWN_REQUEST
Role:
Senior implementation engineer
Reasoning tier:
High
Why this tier:
The architecture is approved, but implementation crosses four packages and
requires lifecycle and compatibility decisions.
Objective:
Implement AbortSignal-based cancellation for streaming fragment requests.
Ground truth:
- docs/streaming-cancellation.md
- packages/loader/src/
- packages/router/src/
- packages/fragments/src/
- Existing tests under packages/*/test/
Architectural invariants:
- Server-rendered HTML remains the lowest shared representation.
- No hydration pass may be introduced.
- Cancellation must release listeners and pending resources.
- Existing public APIs remain compatible.
- A cancelled request must never commit a stale fragment.
In scope:
- Loader cancellation propagation.
- Router navigation cancellation.
- Fragment cleanup.
- Regression tests.
- Relevant documentation.
Out of scope:
- Redesigning the router API.
- Introducing a new task scheduler.
- Replacing the current signal implementation.
Deliverables:
1. Code changes.
2. Tests.
3. Summary of repository assumptions.
4. List of deviations from the approved design.
5. Commands run and results.
Validation:
- Run package tests.
- Run type checking.
- Test cancellation before response, during streaming, and after completion.
- Test rapid consecutive navigations.
Escalate when:
- The approved design contradicts an existing public contract.
- Correct cancellation requires a new architectural primitive.
- Two invariants cannot be satisfied simultaneously.
Return format:
- Summary
- Changed files
- Tests
- Deviations
- Remaining risks
- Escalations
Assume the initial request is:
Add resumable, abortable streaming navigation to the framework.
The task contains two different problems:
1. The public lifecycle and cancellation contract is not yet defined.
2. Implementation will cross loader, router, signals, and fragments.
The parent should not immediately assign the entire task to a coding agent.
First child:
Pro design chat
Second child:
High implementation chat
Third child:
xhigh verification chat
SPAWN_REQUEST
Role:
Framework architect
Reasoning tier:
Pro
Objective:
Define the lifecycle contract for resumable, abortable streaming navigation.
Required decisions:
- Navigation ownership.
- Cancellation propagation.
- Commit eligibility.
- Stale response handling.
- Fragment disposal.
- Error and retry behavior.
- Nested navigation behavior.
- Interaction with browser history.
- Server/client protocol equivalence.
Deliverable:
An implementation-ready technical specification containing invariants,
state transitions, API contracts, failure modes, acceptance criteria, and a
conformance test matrix.
Do not implement production code.
The Pro child returns:
docs/streaming-navigation.md
The parent checks that the document contains:
- explicit state transitions;
- cancellation ownership;
- stale-commit prevention;
- error and cleanup rules;
- backwards-compatibility requirements;
- implementation milestones;
- testable acceptance criteria.
Once accepted, the parent starts implementation.
SPAWN_REQUEST
Role:
Senior framework implementation engineer
Reasoning tier:
High
Objective:
Implement docs/streaming-navigation.md.
Authority:
You may make local implementation decisions.
You may not change the architectural invariants.
Required work:
- Implement the navigation state machine.
- Propagate AbortSignal through loader and fragment requests.
- Prevent stale fragment commits.
- Dispose abandoned effects and listeners.
- Add unit and integration tests.
- Document deviations from the specification.
Escalate rather than silently modifying the architecture.
The High child returns a completed diff and test results.
The implementation should now be reviewed by a fresh chat rather than by the original implementation chat.
SPAWN_REQUEST
Role:
Principal correctness reviewer
Reasoning tier:
xhigh
Objective:
Verify that the implementation completely satisfies
docs/streaming-navigation.md.
Treat both the specification and implementation as potentially wrong.
Inspect for:
- races between consecutive navigations;
- cancellation after headers but before body completion;
- stale fragment commits;
- duplicate activation;
- listener and effect leaks;
- nested navigation ownership;
- history back and forward behavior;
- out-of-order streamed fragments;
- errors during cleanup;
- cancellation after apparent completion;
- incompatible public behavior;
- tests that pass without validating the actual invariant.
Patch locally repairable implementation defects.
Return architectural conflicts to the parent rather than redesigning the
system without authorization.
There are two possible outcomes.
The xhigh child finds:
- a listener leak;
- one stale-response race;
- missing back-navigation coverage;
- incomplete fragment disposal.
These are implementation defects. The xhigh child patches them directly.
No Pro escalation is needed.
The xhigh child finds:
The selected ownership model cannot support nested navigations without either
breaking cancellation isolation or changing the public router contract.
This is not a patch-level problem.
The parent starts a new Pro design chat:
SPAWN_REQUEST
Role:
Architecture adjudicator
Reasoning tier:
Pro
Objective:
Resolve the conflict between nested-navigation isolation and the existing
public router contract.
Inputs:
- Original specification.
- Implementation diff.
- xhigh review report.
- Relevant public API documentation.
Deliverable:
A revised decision record with migration and compatibility consequences.
The orchestration layer may expose a function similar to:
type ReasoningTier = 'low' | 'medium' | 'high' | 'xhigh' | 'pro';
interface SpawnChatOptions {
role: string;
reasoningTier: ReasoningTier;
prompt: string;
artifacts?: string[];
}
interface ChildResult {
summary: string;
artifacts: string[];
risks: string[];
escalations: string[];
}
declare const spawnChat: (
options: SpawnChatOptions,
) => Promise<ChildResult>;The parent can route work like this:
const design = await spawnChat({
role: 'Framework architect',
reasoningTier: 'pro',
prompt: `
Define the lifecycle and cancellation contract for resumable streaming
navigation. Produce an implementation-ready specification. Do not write
production code.
`,
artifacts: [
'packages/router',
'packages/loader',
'packages/fragments',
],
});
const implementation = await spawnChat({
role: 'Senior implementation engineer',
reasoningTier: 'high',
prompt: `
Implement the approved specification.
Preserve all stated invariants. Return code, tests, deviations, and
unresolved risks. Escalate architectural conflicts.
`,
artifacts: design.artifacts,
});
const verification = await spawnChat({
role: 'Principal correctness reviewer',
reasoningTier: 'xhigh',
prompt: `
Audit the implementation against the specification.
Find hidden lifecycle, cancellation, compatibility, ordering, cleanup,
and testing gaps. Patch implementation defects. Escalate architectural
conflicts.
`,
artifacts: [
...design.artifacts,
...implementation.artifacts,
],
});In an interface without programmatic chat spawning, the parent emits the same
handoff as a copyable SPAWN_REQUEST.
Bad:
Design the architecture, implement everything, review your own implementation,
and decide whether the result is production ready.
Better:
Pro child:
Establish the engineering contract.
High child:
Implement the contract.
xhigh child:
Challenge the implementation.
A child should receive:
- specifications;
- source paths;
- relevant tests;
- diffs;
- error logs;
- traces;
- benchmarks;
- previous review findings;
- explicit acceptance criteria.
Do not force every child to reconstruct the entire history from conversation prose.
Each handoff should state what the child may change.
Example:
You may change internal implementation details.
You may not change public API contracts.
Escalate when a public contract must change.
Without authority boundaries, implementation agents tend to redesign the task while solving it.
Useful escalation conditions include:
- Two required invariants conflict.
- The specification contradicts existing public behavior.
- A local fix requires a new global abstraction.
- Compatibility cannot be preserved.
- Tests reveal that the stated problem is not the root cause.
- The requested outcome creates an unacceptable security or data-integrity risk.
Every implementation or review child should return:
- files inspected;
- files changed;
- tests added;
- commands run;
- test results;
- unresolved risks;
- assumptions;
- deviations from the plan.
“Implemented successfully” is not sufficient evidence.
A large task is not necessarily an architectural task.
Use Pro when the uncertainty concerns:
what should be built
Use High when the uncertainty concerns:
how to implement the agreed design
xhigh has the highest value when given something concrete to challenge:
- a diff;
- a failing test;
- a specification;
- a runtime trace;
- generated compiler output;
- an implementation with uncertain completeness.
Without concrete artifacts, xhigh may spend its additional reasoning budget exploring unnecessary possibilities.
The same chat that produced an implementation is biased toward its own assumptions.
Use a fresh xhigh chat for high-risk verification.
Architecture does not need to specify every file-level detail, but it must establish:
- ownership;
- lifecycle;
- state transitions;
- public contracts;
- failure behavior;
- cleanup behavior;
- compatibility requirements;
- testable acceptance criteria.
Most defects are implementation holes.
Return to Pro only when:
- the architecture is internally inconsistent;
- the problem was framed incorrectly;
- a public contract must change;
- the available fixes represent a consequential system-level tradeoff.
Low
Apply exact, mechanical changes.
Medium
Perform normal feature work and bug fixing.
High
Implement substantial changes requiring senior judgment.
xhigh
Audit, challenge, debug, and close hidden implementation gaps.
Pro
Frame problems, design systems, establish contracts, and resolve
architectural conflicts.
For important engineering work:
1. Pro chooses the architecture.
2. High builds it.
3. xhigh tries to break it.
4. High or xhigh repairs implementation defects.
5. Pro returns only when the architecture itself must change.
The essential rule is:
Use Pro when the cost of choosing the wrong system is high. Use xhigh when the system has been chosen but the cost of missing an implementation hole is high.