Skip to content

AI & Engineering / An investigation you can run

AI-Native PHP Development with Semitexa

By ·

An AI coding agent can produce a convincing patch. The harder question is whether it found the right code, understood the rule, and proved that the application now behaves correctly. AI-native PHP development with Semitexa gives that investigation a concrete foundation: an explicit execution path, a queryable project graph, observable requests, and verification the agent can run.

This article includes a working bug. An order at exactly $100 is charged $12 for delivery that should be free. Run the example, follow its PHP handler, inspect the evidence, and compare the corrected rule. Every result in the lab is calculated by the Semitexa application serving this page.

About the code examples. The investigation below records the original Framework Demo implementation and its class names. This article now lives on semitexa.com; its interactive lab uses the same fixed cases in BlogShippingRuleLab. The current article route is handled by BlogArticlePayload and BlogArticleHandler in the Semitexa site module.

AI-native PHP starts with an application an agent can inspect

A developer reports: “Free shipping is broken.” Before changing a line, an agent has several questions to answer. Which route handles the request? Which policy calculates shipping? Is the browser displaying a server result or calculating its own? What happened for the failing order? Does “from $100” include $100 itself?

A repository can contain all the answers and still make them expensive to find. A string search returns references with different meanings. A class name suggests responsibility but does not prove it. A screenshot shows the wrong total without identifying the calculation. Even a successful request tells us only that execution completed.

Semitexa gives those questions named tools. Route introspection explains the request chain. Project Graph reports structural relationships. Observatory records execution. The agent can move from a user-visible symptom to a specific method with evidence at each step.

The roles remain clear: the agent reasons; Semitexa supplies an execution, inspection, memory, and verification environment. The framework does not decide the product requirement. The developer still owns the acceptance criteria and reviews the change. “AI-native” here means that an agent has useful, structured ways to discover and check the application it is editing.

EvidenceQuestion it answersWhat it cannot establish alone
Route introspection and Project GraphHow is this feature connected?Which path a particular request took
Runtime traceWhich instrumented steps actually ran?Whether the business result was correct
Acceptance cases and testsDid the result meet the stated rule?Every possible input or deployment condition

Reproduce the bug: one cent makes the difference

Our requirement is deliberately small and unambiguous: standard delivery costs $12 below a $100 subtotal, and is free at $100 or more. There are no taxes, discounts, currencies to convert, or regional exceptions in this lab. The amounts are represented as integer cents.

Start with the faulty fixture at $100.00. Then try $99.99 and $100.01. Both neighboring cases behave correctly, which is why a quick check of an ordinary order could miss the defect. Finally, choose the corrected rule and repeat all three cases.

Run the PHP example

Free standard delivery from $100, inclusive

Choose a case and a predefined rule. Each submission runs the PHP handler and renders the result with Twig.

Mismatch reproduced Exactly at the threshold · faulty fixture

Order subtotal
$100.00
Expected delivery
$0.00
Actual delivery
$12.00
Expected total
$100.00
Actual total
$112.00

Executed condition: $subtotalCents > 10000

This isolated lab uses fixed test amounts and predefined implementations. The expected delivery charge comes from explicit acceptance cases. It does not create orders or modify application code.

The controls submit a regular GET form. Semitexa hydrates a typed payload, runs the handler, and renders the result through Twig. The example also works with JavaScript disabled. The browser displays the amounts returned by PHP; it contains no second shipping calculation.

This is a controlled teaching fixture with two predefined implementations. Selecting “corrected rule” does not ask an AI model to generate a patch or edit a file. Keeping the faulty implementation available lets every reader reproduce the same mistake and compare it with the correct behavior.

The defect is a single comparison. In the faulty branch of DemoShippingRuleLab, the condition is:

PHP · the faulty fixture excludes the threshold itself
return $subtotalCents > 10000 ? 0 : 1200;

Finding that line is easy once someone tells you where it is. The useful engineering problem is reaching it from the symptom without guessing, then demonstrating that the correction satisfies the requirement.

Find the route before searching the whole repository

In a local Semitexa development checkout containing this Demo article, ask the framework for the route chain:

Terminal · route ownership and the payload's graph impact
bin/semitexa ai:ask route \
  --path=/blog/ai-native-php-development-semitexa --json

bin/semitexa ai:review-graph:impact \
  'Semitexa\Demo\Application\Payload\Request\BlogAiNativePayload' --json

The route query identifies a public GET endpoint, BlogAiNativePayload, its synchronous BlogAiNativeHandler, BlogAiNativeResource, and pages/blog-ai-native.html.twig. The graph impact query reports the handler one relationship away from the payload. These are results from the implementation of this article.

Typed payload→ handlerPHP lab service
Calculated result→ resourceTwig → HTML
The article's code path, combining route metadata with the handler source. This diagram is an explanation, not a live trace visualization.

Now the investigation has a narrow starting point. The handler's source shows its injected DemoShippingRuleLab service and the call to run(). That is the policy to inspect; the template is responsible for displaying its result.

Graph results have a scope. In the inspected build, the handler dependency query exposed its typed payload, resource, and interface relationships, but did not list the injected lab service. Reading the identified handler supplied that last connection. An agent should treat the graph as evidence about the edges it reports, rather than assume that an absent edge proves there is no dependency.

This becomes especially useful when a feature spans modules. Start from an actual route or symbol, follow the relevant relationships, and open the files that answer the remaining question. The Project Graph guide explores that structural workflow in more detail.

Observe the request that produced the wrong answer

Structure tells us where to look. Runtime evidence tells us whether the request reached that code. In your local development environment, open this article's route with the trace flag:

Development URL · request a full trace for the failing case
/blog/ai-native-php-development-semitexa?scenario=boundary&rule=buggy&__trace=1

Use the process journal to find the request, then inspect its source-linked trace. The request name is the payload class name; the process ID comes from the journal:

Terminal · inspect the recorded execution and its source
bin/semitexa ai:observe tail \
  --kind=http --name=BlogAiNative --lines=4 --json

# Replace p-YOUR-ID with the completed request's id.
bin/semitexa ai:observe show --id=p-YOUR-ID --source

The request used while preparing this guide returned HTTP 200 and recorded a pipeline.handler span whose source_ref was BlogAiNativeHandler::handle, with its full namespace. The source output included the actual call that passes the selected scenario and rule to the lab service.

Notice the distinction: the request completed successfully while displaying a wrong business result. HTTP 200 is not a shipping-policy test. Likewise, the handler span proves that the instrumented handler ran; it does not imply a separate span exists for every internal PHP method call.

A developer can inspect the same development environment through /__observatory and the waterfall at /__trace. Source views connect recorded steps to code without a second search through similarly named handlers. Those source slices are read from the current files, so they are most useful before the implementation changes; they are not an immutable historical copy of the code.

Full traces, source inspection, and replay in this walkthrough require development mode. Observatory also has a restricted production monitoring mode for lifecycle records, with different access and data limits. The public lab on this page exposes only its fixed shipping cases.

Correct the rule where the rule lives

The acceptance criterion includes the threshold itself. The corrected PHP expression is therefore:

PHP · free delivery includes an exact $100 subtotal
return $subtotalCents >= 10000 ? 0 : 1200;

In a real shipping policy, that is the implementation we would keep. This article retains both branches in the isolated lab so the comparison remains runnable. The expected amounts are stored separately as explicit acceptance cases; they are not calculated by calling the same shipping function and trusting its answer twice.

The handler coordinates the work and passes decided values to the response resource. This is the relevant call from the page's real handler:

PHP · handler excerpt, expanded for readability
->withLab($this->shippingLab->run(
    $payload->getScenario(),
    $payload->getRule(),
));

Twig owns the view: labels, amounts, selected options, and the visible comparison. The service owns the calculation. This separation reduces the number of places an agent must change and the number of competing implementations a reviewer must reconcile.

The same ownership principle matters when interfaces become more dynamic. A deferred region can receive a server-calculated result, and a live update can deliver newly rendered content without inventing a browser-side shipping policy. Our Server Side Rendering 2.0 article demonstrates shared templates and deferred blocks; the Streaming SSE guide follows live delivery.

One source of truth has a precise meaning here: one owner for the business rule, and one authoritative template for the view. Moving the comparison into Twig would blur that boundary again. Asking an agent to keep duplicated PHP and JavaScript pricing functions synchronized would preserve the duplication rather than resolve it.

Replay the handler with an explicit change of input

Once a request has a full trace, Semitexa can use it as the starting point for a handler replay. For this isolated lab, provide both inputs explicitly and select the already implemented corrected branch:

Terminal · re-execute the recorded handler with explicit lab inputs
bin/semitexa ai:observe replay --id=p-YOUR-ID \
  --mutate=scenario=boundary --mutate=rule=fixed

The replay we ran returned verdict: ok. Its resource contained the following lab values, shown here as a shortened selection from the output:

Observed replay output · selected lab fields, not the full envelope
{
  "scenario": "boundary",
  "rule": "fixed",
  "actualShippingCents": 0,
  "expectedShippingCents": 0,
  "actualTotal": "$100.00",
  "matches": true
}

Explicit inputs matter. This page's original hydration trace contained an empty payload snapshot, so it would be incorrect to claim that replay automatically preserved the selected form values. Here we know exactly which scenario we are rerunning because the command supplies it.

Replay also has a narrower execution boundary than a fresh browser request: it invokes the resolved handler with a hydrated payload and resource. It does not reproduce the complete HTTP, authorization, and rendering pipeline. Use it to inspect a handler result, then exercise the actual page to verify delivery and presentation.

The replay runner rolls back its managed database transaction and captures queue handoffs. Supported mail transport is withheld during the sandboxed run. Arbitrary outbound HTTP calls and LLM provider calls are not universally suppressed, so replay is not a blanket guarantee of external isolation. This lab performs no such calls and creates no orders.

Make the acceptance criterion executable

A plausible patch becomes a useful fix when the requirement survives independent checks. For our inclusive threshold, the three adjacent cases provide a compact specification:

SubtotalExpected deliveryFaulty ruleCorrected rule
$99.99$12.00$12.00 · matches$12.00 · matches
$100.00$0.00$12.00 · mismatch$0.00 · matches
$100.01$0.00$0.00 · matches$0.00 · matches

The article's test suite checks all six scenario/implementation combinations and the fallback for unknown inputs: seven tests and 25 assertions. A test for the faulty branch asserts that the lab exposes the mismatch; it does not approve that charge as correct product behavior.

Terminal · execute the acceptance cases and scoped framework checks
bin/semitexa test:run \
  packages/semitexa-demo/tests/Unit/Service/DemoShippingRuleLabTest.php

bin/semitexa ai:verify \
  --files=packages/semitexa-demo/src/Application/Service/DemoShippingRuleLab.php \
  --files=packages/semitexa-demo/tests/Unit/Service/DemoShippingRuleLabTest.php \
  --json

ai:verify selects applicable checks for the files under review. Its report is evidence about the checks it ran. The focused service tests establish the boundary behavior; a browser check additionally establishes that form inputs reach PHP, values render correctly, and the page remains usable.

Semitexa's long-running workers cache discovered classes and compiled templates. After changing the implementation, run bin/semitexa server:restart before testing the running HTTP server. CLI verification uses fresh processes and does not need that restart.

The product decision still comes first. If the requirement had said “strictly over $100,” the original comparison would be correct. An agent must resolve that ambiguity with the product owner or an authoritative specification. Neither a graph nor a trace can invent the intended meaning of a promotion.

Keep the evidence when the conversation moves on

Long investigations often fail at the handoff. The next session sees a modified file but loses the reason for the change, the failing input, and the hypothesis that was already disproved. The agent spends time reconstructing an investigation someone already completed.

Semitexa's ai:epic, ai:work, and ai:trace commands give ongoing work durable artifacts. ai:orient brings the active work and recent verification back into view. ai:context retrieves relevant prior context before an agent starts reading from scratch.

For this example, a useful handoff would preserve the inclusive-$100 requirement, the $112 failing result, the identified handler and service, the empty trace snapshot limitation, and the passing acceptance cases. “Investigated shipping” would preserve almost nothing.

The amount of process should fit the work. A focused correction can stay small. A change spanning several modules needs explicit tasks, dependencies, decisions, and a next step that another session can actually execute. The purpose is continuity: preserve the facts needed to continue without asking an agent to remember a conversation forever.

Evidence also needs freshness. A graph, a source view, or a passing test report describes a particular state of the project. After editing relevant code, rerun the checks that could have changed and record the new result.

Start AI-native PHP development with one real bug

The shipping mistake is small enough to understand in one sitting. The workflow scales because each step asks a specific question: reproduce the symptom, locate the route, inspect the relevant structure, observe execution, correct the owning rule, and verify the requirement.

Semitexa makes that sequence concrete through the application itself. An agent can query framework metadata, follow a source-linked runtime step, execute a focused test, and leave the evidence for the next session. A developer can review those same artifacts and challenge a conclusion at the point where it was made.

That is the useful promise of AI-native PHP development: a shorter, more inspectable path from “this behavior is wrong” to “here is the rule, the change, and the evidence that it now holds.” The strongest demonstration is an application you can run and question.

Try it on your own feature. Choose one reproducible request and write its expected result first. Start with bin/semitexa ai:orient --json, then ask for its route chain. Keep the investigation narrow enough that every proposed change can be connected to a concrete acceptance case.

Continue with the Semitexa installation guide, explore the development tooling package, or return to the shipping lab and test the boundary yourself. Commands in this guide reflect the development build used for the article; your installed version's --help and capability output describe its available options.