AI & developer workflow
What AI changes in my development workflow
A practical look at bounded AI assistance: turning questions into drafts, keeping source context close and using verification to decide what is ready.
AI improves my development workflow by shortening the distance between a question and something I can inspect. That might be an explanation tied to source code, a small patch or a test that exposes an edge case. The useful improvement is earlier feedback, with enough context and verification to decide what belongs in the project.
Quick answer
I organize AI-assisted development around a few concrete steps: define the behavior, provide the relevant source, ask for a bounded result and inspect what changed. Then I choose the checks that can establish whether the result works. That pattern applies across interfaces, APIs and systems code, even when the tools and failure modes differ.
The selected projects show the range of those layers: React and Laravel applications, a C++ game engine, embedded software and reverse-engineered protocols. A useful assistant needs to follow the actual problem across those boundaries instead of assuming that every task is another frontend component.
Getting oriented in unfamiliar code
The first useful question is often about relationships. Where does a request enter? Which module owns the state? What happens between a user action and the operation that actually changes data? A source-grounded explanation can make the next investigation more focused.
The prompt needs a boundary. “Explain this error using these files and this output” identifies the available evidence. It gives the answer something to point to. An explanation that names a function can then be checked against the implementation, rather than accepted because it resembles a familiar framework pattern.
This is especially useful when a codebase combines technologies. A frontend error might originate in an API response. A desktop application's visible behavior might depend on a native command. A renderer's failure might belong to resource lifetime rather than the draw operation where it becomes visible.
An orientation pass should therefore end in a better question or a smaller search area. A long tour of every file is less useful than identifying the specific boundary that needs inspection. The result should make the next action easier to choose.
Describing the result before asking for implementation
A bounded task includes a trigger and an observable outcome. “When a user expands this record, show the engineering notes without covering the next control” is something a patch can be reviewed against. It also identifies the surrounding behavior that should remain available.
Constraints belong beside the requested outcome. An existing component interface, a data ownership rule or a requirement to keep keyboard navigation working can change the implementation substantially. If those constraints are only supplied after a large patch appears, the next step becomes a rewrite rather than a focused review.
The same idea applies to backend work. A request to add an integration should say what identifies an event, what can be retried and where a failed operation becomes visible. Naming a framework alone does not answer those questions.
For systems code, the task might describe who owns a resource, when it becomes invalid and which thread or context may use it. Those details are part of the behavior. An assistant that produces code without them has filled in an assumption that still needs to be examined.
Reviewing a small diff
The useful output of an implementation task is a change that can be inspected. Git's diff reference describes the available comparisons; the review needs the one that corresponds to the work being accepted.
A small change is easier to connect back to its cause. If a task concerns a navigation control, the diff should explain why other files changed too. A dependency update, a broad formatting pass and the requested interaction may each be reasonable work, but combining them makes it harder to identify which part changed the behavior.
That review also exposes assumptions that a fluent explanation can hide. An API response may be treated as always present. A parser may assume a read operation contains a complete message. A component may hide content until a callback runs. Each assumption is a place to ask what happens when the expected condition is absent.
The next request can then name the exact problem: preserve this state, handle that incomplete buffer, or keep the link reachable during the transition. Specific feedback produces a more inspectable correction than asking for a general improvement.
Debugging with evidence from the failure
An error message is the beginning of an investigation. The relevant inputs, the current state and the point where the behavior diverges help distinguish an explanation from a guess. AI assistance is more useful when that evidence stays attached to the question.
A minimal reproduction is valuable because it reduces the number of moving parts. That can be a small input for a parser, a request with a known response or a component rendered with a particular state. It should retain the condition that causes the failure, rather than simplify away the part that needs understanding.
The proposed fix needs a prediction. If the explanation says the problem is an incomplete header, a test that splits the header should demonstrate the difference. If the problem is an interaction state, the same gesture should produce the intended state after the change. The prediction gives the investigation a stopping condition.
This also helps when the first suggestion is wrong. The reproduction and observed output remain useful. They narrow the next question instead of requiring the entire investigation to be reconstructed from memory.
Choosing verification for the claim
Different checks answer different questions. A type check can establish consistency with the program's types. A behavior test can exercise a specified interaction. A rendered page can show whether the intended hierarchy survives a narrow viewport. The claim determines which evidence matters.
Node's built-in test runner is one option for testing JavaScript behavior without introducing a separate runner. The important part is the scenario: feed the implementation an input that would expose the failure, then check the outcome that the task requires.
For a user interface, a successful compile leaves several questions open. Can a keyboard user reach the control? Does enlarged text reflow? Does a direct link reach the right section? A screenshot can establish a resting composition, while an interaction check is needed to establish what happens between states.
A useful verification pass is proportional. It focuses on meaningful risks and the boundaries touched by the change. Repeating an unrelated check does not make a weak test more relevant to the requested behavior.
Keeping responsibility visible
The workflow works better when the current state of the work is explicit. A suggestion is ready for inspection. A patch is ready for checks. A passing check establishes the behavior it actually covers. A reviewed result can move to the next stage with a clear account of what is still uncertain.
That makes AI assistance useful across a broad engineering stack. The assistant can help produce an explanation, implement a bounded change or explore a failure. The engineer still needs to decide whether the assumptions fit the system and whether the evidence supports accepting the result.
For work spanning interfaces, integrations and low-level systems, that continuity matters more than a particular tool name. The task can move between layers while keeping its intended behavior and verification visible. That is the improvement worth preserving as the tools change.
Technical leadership at Legacies
I co-founded Legacies with Horia Stan and work as its Technical Lead. My responsibilities cover backend architecture, integrations and product stability. That gives the question of AI assistance a practical boundary: a proposed change still needs clear ownership, a reviewable implementation and evidence that it fits the surrounding system.
DockLab, our developer workspace in beta, brings terminal, files, browser and AI into one workspace. The connection to this article is keeping the tools and the problem close together. That product direction does not remove the engineer’s responsibility to review assumptions and decide whether a change is ready.
Legacies also builds custom websites, applications and automations. If you are evaluating a team for that work, these engineering notes explain the concerns behind my technical role; the Legacies overview on this portfolio introduces the people and product.
Frequently Asked Questions
What tasks are good candidates for AI assistance?
Tasks with a clear boundary and an inspectable result are useful starting points. Source explanations, small implementation changes, reproducible examples and focused test cases give the next review something concrete to compare against the original request.
Does a generated patch count as a finished task?
A patch is ready to inspect. Completion also needs evidence for the requested outcome, which may include source review, relevant automated checks and direct inspection of the running behavior.
How can AI help with reverse engineering?
It can help organize observations, explain an existing parser or propose an experiment that distinguishes competing hypotheses. The captured evidence still determines what the protocol does; a plausible field name from a model is not a specification.
Should every change run the same checks?
Checks should follow the behavior and the boundaries affected by the change. A copy correction, a stateful protocol change and a resource-lifetime fix need different evidence, even if they share some routine build checks.