WebFront C++23
FR ↗GitHub ↗

CHAPTER 07 / WEBFRONT

Developing with an AI harness

Configuring local automation and using its results during development.

Notation conventions

Function names, types, commands, options and filenames appear in monospace, for example describe, wf test or main.cpp. Italics introduce a term at its definition. Code blocks give the fragments to enter; the preceding text states their location and prerequisites.

The role of the harness

A harness is the programme that gives a model its tools and arranges their execution. Here, it allows the model to edit sources and then check the consequences of those edits.

The editor’s or harness’s tools write the files. WebFront provides type checking, interface compilation, testing and preview inspection. The model can therefore correct an error from a diagnostic and request another check.

The value of a common environment

When an agent works on a native interface, the project must provide ways to build the programme, operate its controls and interpret the results. Many GUI libraries provide such facilities, but assembling and adapting them often remains project work.

WebFront brings TSX compilation, type checking, Jasmine and preview into one environment. The same C++ callback is used during normal operation and during tests. A change can therefore be accompanied immediately by an executable check.

The practical benefit is fewer occasions on which a developer must rerun a command, read its output and relay it to the agent. The benefit depends on the project, its tests and the model; it is not a guaranteed speed-up factor.

This method applies from the creation of an application through its subsequent evolution. Functions and tests added in the first iterations become the working material for maintenance and distribution.

Building the launcher

The following commands build webfront-agent and the webfront-wf driver from the 0.7.0 checkout on macOS. Enable the appropriate embedded engine on Windows or Linux.

The launcher requires an environment archive at version 0.6.3 or later containing automation API v1, together with a trusted SHA-512 digest. Use the verified distribution or build it as described in the source guide.

Prepare the project manifest, lock file and dependencies before connecting the agent. Automation tools provide neither install nor restore.

SYSTEM TERMINAL
cmake -S . -B build-agent -DCMAKE_BUILD_TYPE=Release \
  -DWEBFRONT_EMBED_WKWEBVIEW=ON \
  -DWEBFRONT_BUILD_AUTOMATION=ON -DWEBFRONT_ENABLE_TESTING=ON
cmake --build build-agent --target webfront-agent webfront-wf --parallel 2

Sharing a development window

The following command opens a window that remains available to the developer. Replace the paths and sha512-TRUSTED_DIGEST with their real values; that string is not a valid digest. The session directory must be new, private and outside the project.

  • --serve keeps the window and terminal open.
  • --listen allows a local client to attach.
  • Each --allow option permits the named operation.

Grant only the operations required for the work. Type checking and test execution do not require inspection or interaction permissions.

SYSTEM TERMINAL
webfront-agent --project /absolute/project \
  --environment /absolute/environment.tgz --integrity sha512-TRUSTED_DIGEST \
  --allow check --allow build --allow test \
  --allow preview --allow inspect --allow interact \
  --serve --listen /absolute/private-session

Configuring the MCP client

The launcher exposes MCP over a local process’s standard input and output. Here, the client starts an adapter that attaches to the already open window. It does not connect to an HTTP service.

The example uses the common mcpServers configuration format. Use the location expected by your client and the actual executable path. Closing the client detaches the adapter without closing the developer’s window. The client cannot broaden permissions granted by the session owner.

JSON
{
  "mcpServers": {
    "webfront": {
      "command": "/absolute/build-agent/webfront-agent",
      "args": ["--attach", "/absolute/private-session", "--mcp"]
    }
  }
}

Using the command line

A harness that can start a process can use the JSON command-line interface. --schema describes the contract; --agent-help provides short instructions.

Each command waits for its final result. Exit statuses include:

  • 0: success;
  • 1: operation failure;
  • 70: bootstrap failure;
  • 71: native deadline expiry.

Build commands compile the interface. The harness must arrange the application’s C++ compilation separately.

SYSTEM TERMINAL
webfront-agent --attach /absolute/private-session --operation check
webfront-agent --attach /absolute/private-session --operation test
webfront-agent --attach /absolute/private-session --operation preview --entry ui/main.tsx

Following an MCP operation

The client has four tools:

  • webfront.session obtains session information.
  • webfront.start starts an operation and returns its runId.
  • webfront.result reads that operation’s state and result.
  • webfront.cancel requests cancellation.

The fragment below describes tool calls; do not paste it into the page’s JavaScript. After each start, wait for a terminal state: succeeded, failed, cancelled, timeout or disconnected.

Acceptance of a request does not mean the operation succeeded. Compiler diagnostics may identify the file, line and column; Jasmine supplies its report in report.

MCP
webfront.session({})
// Use the returned session identifier:
webfront.start({session: SESSION, operation: "check"})
// Use the returned runId; poll until a terminal state:
webfront.result({session: SESSION, runId: RUN_ID})
// For a preview after a successful build:
webfront.start({session: SESSION, operation: "preview",
               arguments: {entry: "ui/main.tsx"}})
// After completion, inspect and use the returned pageId and element IDs:
webfront.start({session: SESSION, operation: "inspect"})
webfront.start({session: SESSION, operation: "fill",
               arguments: {pageId: PAGE_ID, elementId: "quantity", value: "3"}})
webfront.start({session: SESSION, operation: "click",
               arguments: {pageId: PAGE_ID, elementId: "calculate"}})
// Operations must run sequentially; inspect again to observe the result.

Example: adding a quotation screen

The quotation screen from the preceding chapter is a suitable first exercise. The request below specifies the expected behaviour, where the calculation belongs and the test to produce.

The harness edits files with its usual tools, then asks WebFront to check types, build the interface and run tests. It can then inspect the preview and try the controls.

The developer reviews the modified sources and assertions. The Jasmine journey remains in the repository, where CI can execute it and detect a later regression.

EXAMPLE REQUEST
Add a quantity field and a Calculate button to the quotation screen.
Keep the price calculation in the existing C++ callback.
Give the controls stable IDs and show bridge failures in the UI.
Add a Jasmine journey: enter 3, calculate, expect a total of 75.
Run check, build and test; inspect the preview and try the controls.
Read each final run state. Report changes, test results and limitations.

Further applications of the method

Correcting a TypeScript error is a simple case. The model reads the diagnostic, edits the source and reruns wf check, followed by relevant tests. The developer no longer has to relay every compiler message.

For a settings panel, a description of C++ fields can generate the form and TypeScript declarations. The model can then add boundary and invalid-value tests.

For a functional regression, first reproduce the defect in a Jasmine test. Evaluate the correction against that case and the existing tests. This leaves a lasting check that is independent of the conversation with the model.

Scope of inspection

inspect describes visible elements that have explicit identifiers. It provides bounded text and labels, together with observed errors. fill accepts ordinary text and number fields; click accepts buttons and checkboxes among other controls.

An action must use the inspected pageId. Navigation invalidates that revision, so a subsequent action is refused. Inspection supplies no screenshots, arbitrary selectors or full accessibility tree. DOM interactions are synthetic.

The terminal and agent cannot execute incompatible operations concurrently. A wf dev watcher may, however, remain open while waiting for a change.

Observed results and limitations

The local qualification of 29 October 2026 used five installed models. All 30 final sources passed independent type and test checks. In 29 of the 30 conversations, the model itself observed both successful results. The report details the tasks and incomplete case. These observations are not a productivity comparison with another GUI library.

The launcher is optional and local. It supplies no shell, unrestricted JavaScript evaluation or arbitrary file reads. Projects and tests still execute code with application authority. Use an isolated environment without secrets for unfamiliar code. WKWebView and WebKitGTK do not isolate browser storage per process.

Check your understanding

Does acceptance of a webfront.start call indicate that the tests passed?