I was using AI to build a feature based on a product requirements.
The code looked fine, it compiled normally, and the initial set of tests passed.
Later, I found one wrong assumption inside it.
Debugging that assumption took me around 40 min, which was longer than writing the code itself.
The initial tests covered the cases I had already thought of. The wrong assumption existed outside of those cases.
So, this is the workflow that I use which changes the order in which I work with AI.
I do not ask it to start coding immediately.
I first make my understanding visible, challenge it, write down the accepted decisions, and protect the highest-risk behaviour with tests.
This is the workflow I follow:
Problem → Diagram → Challenge → Specification → Tests → Code
I use this skill in particular:
# challenge-me - rules for reply while ideating
1. Do not write code. Review my design first.
2. Separate requirements, assumptions, and open questions.
3. Challenge every payload field, data source, and trust boundary.
4. Find missing failure cases and turn them into tests.
5. End with the three highest-risk problems to solve first.
Here is how I use it from start to finish.
1. Draw the Design Myself First
Before calling /challenge-me, I open Excalidraw and create two boxes.
The first box contains:
- The proposed payload.
- Where each value comes from.
- Which value the client can control.
The second box contains:
- The successful flow.
- Invalid input cases.
- Primary test cases.
The design does not need to be perfect.
The goal is to put my current understanding somewhere visible before AI starts influencing it.
2. Give Everything to /challenge-me
I give the skill enough context to review the complete design.
/challenge-me
Here is the original requirement:
-
Here is my proposed payload:
-
Here is the data flow:
-
Here are my assumptions:
-
Here are the test cases I have considered:
-
At this stage, I do not ask it to improve the code because no code should exist yet.
I only want it to find problems in my understanding.
These questions are more useful before implementation than after it.
3. Review Every Finding Myself
I do not accept the complete AI response automatically.
I divide each finding into three groups:
# ACCEPT
This is a real problem and should change the design.
# REJECT
This does not match the requirement or is outside the POC.
# OPEN
I need more product or technical information before deciding.
AI can identify a missing decision, but it should not silently make an important business decision for me.
This is the main value of challenging the payload first.
The final payload becomes smaller because the client controls less trusted data.
4. Write the Accepted Decisions in spec.md
Once I understand and accept the decisions, I ask AI to document them.
The spec.md file becomes the main reference for future AI sessions.
The AI should read it before writing tests or implementation code.
5. Start With the Highest-Risk Tests
Do not start by generating every possible test.
I begin with the three cases that would cause the most damage if they were wrong.
I ask AI to explain each test before writing it.
Read spec.md.
For each priority test, explain:
1. Which requirement it implements
2. Which action it performs
3. What result it expects
Do not write implementation code.
After reviewing the test plan, I ask it to write only the first test.
I run the test before implementation and check that it fails for the correct reason.
A test failing because the application cannot start is not useful evidence.
It should fail because the required behaviour is missing.
6. Implement One Test at a Time
Once the first test fails correctly, I ask AI to write the smallest amount of code needed to make it pass.
Then I repeat the loop:
Write one test
→ Run it
→ Confirm the failure
→ Implement the behaviour
→ Run the test again
→ Review the diff
I avoid asking AI to implement the entire feature in one step.
Smaller changes are easier to understand, review, and reverse.
7. Review the Final Diff
After the important tests pass, I compare the code with spec.md.
I check:
- Did the implementation introduce a new assumption?
- Are all high-risk cases tested?
- Did AI add anything outside the agreed scope?
Finally, I run the focused tests and the complete test suite.
This process does not guarantee bug-free code.
AI can still miss a case, and the specification can still contain a wrong decision.
The purpose is to expose more assumptions before they spread across the payload, code, tests, and database.
The most useful time to challenge a design is when it is still only a box in Excalidraw.