# VeriHarness V0.2 Decision Log

Updated: 2026-07-14

This file records only decisions explicitly accepted for V0.2. Background facts and V0.1
mechanisms do not become V0.2 decisions merely because they appear in the context snapshot.

## D-0001: Create A Version Boundary

Status: accepted  
Date: 2026-07-13

Decision:

- Freeze VeriHarness V0.1 as the reproducible baseline.
- Start VeriHarness V0.2 as a separate, self-contained subproject.
- Preserve V0.1 empirical results and caveats without editing them into a new experiment.
- Reconsider major harness and experimental choices before copying implementation code.

Reason:

The newly discussed direction may substantially change the research formulation. Keeping the
version boundary prevents historical case1 evidence from being confused with a newly defined
treatment.

Consequences:

- V0.2 begins in design state.
- The first new decision must describe the research change and the V0.1 assumption it affects.
- No additional V0.2 architecture is accepted yet.

## D-0002: First Tool Supports Multimodal Understanding Only

Status: accepted  
Date: 2026-07-14

Refinement note:

D-0010 later refines “schema-constrained JSON”: JSON may omit a schema when only syntactic JSON is
needed, or include one when stable fields are required.

Decision:

- The first V0.2 MCP surface exposes one general model-invocation tool.
- Inputs are explicit text and one or more images.
- Outputs are inline text or schema-constrained JSON.
- The first version does not generate images, edit images, return image artifacts, or expose an
  image-output path.
- Because only one execution family exists, the first schema does not need an
  `analyze | generate | edit` mode field.

Reason:

The immediate research need is to let the Claude orchestrator delegate general multimodal tasks
to an isolated model while keeping the Claude Code runtime otherwise intact. Image generation and
editing would add provider, artifact-lifecycle, and output-transport concerns before the core
text/image input contract is understood.

Experimental consequence:

- Tool availability is narrow and consistent across the first comparison conditions.
- Any observed use of the tool concerns multimodal understanding rather than image production.
- Text and JSON result admission can be studied without mixing in generated-artifact handling.

Implementation consequence:

- The initial MCP schema needs explicit `instruction`, typed `inputs`, model selection, and a
  text/JSON output contract.
- Image inputs must be attached as actual image content by the backend; a path mentioned only in
  instruction text is not an image input.
- Image generation and editing remain possible future extensions, not dormant fields in the V0.2
  first-version schema.

## D-0003: Capability Vocabulary Stays Out Of The MCP Schema

Status: revised by D-0007  
Date: 2026-07-14

Revision note:

The original decision below rejected capability labels as operation selectors. D-0007 later allows
versioned sub-capability tags into the request as non-routing analysis metadata. The original text
is retained to preserve how the design changed.

Decision:

- The first MCP schema does not expose `mode`, `capability`, or `capabilities` fields.
- `DISCOVER`, `READ`, `GROUND`, `STRUCTURE`, `UNDERSTAND`, `ALIGN`, `COMPARE`, and `REASON`
  remain a vocabulary in the B1 tool-use prompt.
- The vocabulary helps the Claude orchestrator decompose tasks and write the per-call instruction;
  it does not select a hidden atomic tool or inject a capability-specific backend prompt.
- The backend receives the complete agent-authored instruction together with explicit inputs and
  the requested text/JSON output contract.

Reason:

Capability labels are useful human priors but do not change transport or execution. Putting them
in the MCP schema would recreate a mode selector around a tool intended to remain general, add
ceremonial parameters, and risk constraining calls that combine several kinds of multimodal work.

Experimental consequence:

- The model's concrete instruction, inputs, and output contract expose how it chose to use the
  external model without forcing that behavior into predefined atomic categories.
- Capability usage can be annotated from the saved instruction after the run when analysis needs
  it; the runtime contract does not need to anticipate every future capability taxonomy.

Implementation consequence:

- The minimal schema continues with `instruction`, typed `inputs`, model selection, and text/JSON
  output fields only.
- Tool-use examples in the B1 prompt must demonstrate the capability vocabulary through complete,
  realistic instructions rather than through a `capability` argument.

## D-0004: Use `claude -p` As The V0.2 Runtime Base

Status: accepted  
Date: 2026-07-14

Decision:

- Build V0.2 around Claude Code print mode (`claude -p`) rather than the native Claude Agent SDK.
- Keep Claude Code's existing inner agent loop, coding tools, and context behavior.
- Add the general multimodal-model capability through MCP and add research instructions through an
  appended system prompt.
- Keep the first outer harness minimal: assemble prompt/config, launch Claude Code, capture its
  event stream, and preserve reproducibility metadata.
- Treat v-harness 2.3 as a technical reference for CLI/MCP integration, not as a runtime dependency
  or an experiment contract to copy wholesale.

Reason:

The immediate research need is to supplement an existing capable coding harness with model-calling
ability and compare policies for using it. Reimplementing Claude Code's inner loop with the Agent
SDK adds complexity that is not necessary for the first V0.2 causal comparison.

Experimental consequence:

- Claude Code becomes the common agent runtime across conditions.
- Later prompt treatments can be expressed as appended modules over a shared native baseline.
- Changes caused by a custom inner-loop implementation are reduced.

Implementation consequence:

- The implementation should use `--append-system-prompt-file`, `--mcp-config`,
  `--strict-mcp-config`, and stream-json capture as the initial integration surface.
- V0.1 session/controller/gate code is not copied before its necessity is re-established.

## D-0005: Keep B1 Tool Policy Independent Of Verification

Status: accepted  
Date: 2026-07-14

Decision:

- B1 describes the general MLLM call, multimodal capability vocabulary, input discipline,
  instruction-writing methods, output selection, decomposition, and ordinary result handling.
- B1 introductions, rules, and examples do not frame the tool as a verification mechanism and do
  not mention hard gates, acceptance, scores, or verification-specific stopping.
- Tool-driven and goal-driven verification instructions belong to a separate B3 module that can be
  inserted or omitted by an experiment condition.

Reason:

The MLLM call is a general model-delegation capability. Coupling its shared description to
verification would both restrict ordinary use and leak the intended treatment into conditions that
are supposed not to receive a verification policy.

Experimental consequence:

- Tool availability and competent tool-use guidance can remain shared while B3 varies verification
  behavior.
- A future ablation can distinguish general model delegation from an explicit verification policy.

Implementation consequence:

- B1 and B3 must be separate prompt source files with independently recorded hashes.
- Verification-specific examples cannot be added to the shared B1 file for convenience.

## D-0006: Name The General Tool `CallMLLM`

Status: accepted  
Date: 2026-07-14

Decision:

- Use `CallMLLM` as the public conceptual name of the general multimodal model call.
- Use the noun form `MLLMCall` for an event or stored call record when useful.
- Keep `mllm` as the proposed MCP server name and `call` as the proposed function name, yielding
  `mcp__mllm__call`; confirm the exact Claude-visible spelling during implementation.

Reason:

`CallMLLM` follows Claude Code's action-plus-object naming style, explicitly communicates that the
target is a multimodal large language model, and does not narrow the call to analysis, OCR,
comparison, or another single operation.

Implementation consequence:

- B1 prompt sources use `CallMLLM` directly rather than a placeholder.
- Event names may use forms such as `mllm_call_started` and `mllm_call_completed` without changing
  the public command name.

## D-0007: Add Composable Sub-Capability Tags As Analysis Metadata

Status: accepted  
Date: 2026-07-14

Decision:

- Every `CallMLLM` request declares one or more versioned sub-capability tags, represented as an
  array such as `capability_tags: ["A3", "B2"]`.
- Multiple tags describe one coherent call and have no execution-order or primary/secondary
  semantics.
- A single tag and a coherent combination are equally valid. B1 must not encourage either form as
  the default; the agent chooses from the current instruction.
- Tags are validated and logged but do not route the backend, select a hidden atomic tool, choose a
  model, inject a prompt, or replace the complete `instruction`.
- Runtime traces store them as `declared_capability_tags` together with a taxonomy version.
- Later offline analysis may add `inferred_capability_tags`; declared and inferred labels remain
  separate.
- The first working taxonomy uses A-H capability families plus a narrow `Z1` escape hatch. Exact
  sub-capability definitions remain versioned and can be refined without rewriting historical
  calls.

Reason:

The project needs to analyze which multimodal sub-capabilities the agent attempted, which
combinations were common, and how those calls relate to later behavior. A non-routing label field
provides this observability without reverting to v-harness-style fixed atomic operations.

Experimental consequence:

- Analysis can group calls by declared operation and combination, such as OCR-only versus
  discovery-plus-recognition.
- Agent-authored labels are not treated as perfect ground truth and can be compared with an
  independent offline annotation.

Implementation consequence:

- The MCP request adds a required `capability_tags` field and a taxonomy identifier/version in
  trace metadata.
- The B1 prompt includes all current family/sub-capability codes and requires the instruction to
  explain combinations.
- Backend behavior must be invariant to tag order and must not branch on the tag values except for
  schema validation and logging.

## D-0008: Use Typed Text/Image Inputs With An Optional Neutral Region

Status: accepted  
Date: 2026-07-14

Decision:

- `CallMLLM` has one top-level `instruction` and a typed `inputs` list.
- `instruction` states the operation, scope, precision, and required result. A text input carries
  explicitly supplied auxiliary material rather than duplicating the instruction.
- Every text or image input has a unique label that the instruction can reference.
- An image input declares a controlled path and may optionally declare a pixel region using
  `{x, y, width, height}` relative to the original image's top-left origin.
- Without `region`, the complete image is attached. When both views are useful, the same path may
  be supplied under separate full-image and regional labels.
- The prompt must not encourage regional input as a default. Full image, region, full plus region,
  and multiple calls remain agent-selected alternatives.
- Invalid regions are explicit input failures; the backend must not silently adjust them.

Reason:

Typed inputs make image attachment and auxiliary text explicit. Optional regions cover focused
OCR, inspection, and other local visual work without creating another atomic tool, while neutral
prompt wording preserves the agent's choice of visual scope.

Implementation consequence:

- The MCP input union contains `TextInput {kind, label, content}` and
  `ImageInput {kind, label, path, region?}`.
- The backend crops only when the caller supplies `region`, records the original input and region,
  and attaches the resulting image bytes.
- Prompt examples may demonstrate region support but cannot prescribe a global-to-local or
  crop-first workflow.

## D-0009: Resolve Optional Model Profiles From A Runtime Catalog

Status: accepted  
Date: 2026-07-14

Decision:

- `model_profile` is optional. Omitting it resolves to the runtime profile named `default`.
- The user supplies the profile catalog for each harness configuration. The current catalog has
  one `default` profile backed by the local model proxy; future configurations may add more.
- Agent-facing profiles expose stable names and short capability descriptions, not raw provider
  model IDs, proxy addresses, credentials, or provider configuration.
- The harness injects the available catalog into the exact B1 prompt snapshot for that run.
- The agent may omit the field or explicitly choose an available profile from the task context;
  B1 does not encourage switching merely because multiple profiles exist.
- A profile may resolve to the same model family as the orchestrator or another model. Every
  `CallMLLM` invocation remains a fresh isolated model context.
- An explicitly selected unknown or unavailable profile returns an error and never silently falls
  back to `default`.

Reason:

An optional stable profile name keeps the one-model setup simple while allowing future model
catalogs without changing the tool schema. Hiding raw provider configuration also improves
portability, reproducibility, and secret handling.

Implementation consequence:

- The MCP signature uses `model_profile: str | None = None`.
- Runtime traces store `requested_model_profile`, `resolved_model_profile`, and a private
  `resolved_model_config_hash`.
- Prompt snapshots include the public profile catalog used by the run, while provider endpoints,
  credentials, and private configuration remain outside prompts and public artifacts.
- Current examples omit `model_profile` and therefore use `default`.

## D-0010: Use A Required Nested Text/JSON Output Contract

Status: accepted  
Date: 2026-07-14

Decision:

- Replace separate `output_kind` and `output_schema` fields with one required `output` object.
- `TextOutput` is `{kind: "text"}` and cannot contain a schema.
- `JsonOutput` is `{kind: "json", schema?: JSONSchema}`.
- JSON without a schema requires syntactically valid JSON but allows a variable JSON shape.
- JSON with a schema requires both syntactically valid and schema-valid output.
- Schema use is optional and selected from downstream structure needs; B1 does not encourage a
  schema for every JSON call.
- The first version has no image output variant.

Reason:

A discriminated output object prevents invalid text/schema combinations. Optional JSON Schema
keeps general calls lightweight while preserving strict machine-consumable output when needed.

Implementation consequence:

- The MCP signature uses `output: TextOutput | JsonOutput`.
- Provider-native structured output may be used when available, but retry and final failure
  behavior remain a separate decision.
- Examples and event records store the nested output contract rather than parallel kind/schema
  fields.

## D-0011: Keep Output Recovery In The `claude -p` Agent Loop

Status: accepted  
Date: 2026-07-14

Decision:

- One `CallMLLM` invocation makes one delegated model request and returns that result to Claude.
- The backend does not automatically repair, reprompt, normalize, or retry malformed or
  schema-invalid model output.
- When requested JSON cannot be parsed or validated, the tool exposes the raw model output and a
  concise validation diagnostic to the `claude -p` agent.
- Claude decides whether to change the instruction, inputs, output contract, model profile, or make
  another call.
- Ordinary provider/transport failure remains an ordinary tool error; V0.2 does not build a second
  intelligent recovery loop around the model call.

Reason:

The research harness only needs to give Claude a general model-calling behavior. Claude Code
already owns the agent loop and can inspect a tool result and choose its next action. Automatic
backend repair would add hidden control, obscure the agent's behavior, and recreate complexity
that V0.2 intentionally removed by returning to `claude -p`.

Implementation consequence:

- There is no output-retry field, retry policy, repair prompt, or hidden model attempt in
  `CallMLLM` V0.2.
- Event traces preserve the single raw delegated response and any parse/schema diagnostic.
- A subsequent agent-authored call is a new visible `CallMLLM` event rather than an internal
  backend attempt.

## D-0012: Do Not Add A Recipe Field

Status: accepted  
Date: 2026-07-14

Decision:

- The first `CallMLLM` request has no `recipe`, operation-template, or hidden prompt selector.
- B1 capability definitions and detailed examples provide reusable human priors.
- Claude always sends the complete instruction for the current delegated call.
- Traces preserve the expanded instruction and capability tags rather than only a recipe name.
- If a future version genuinely needs runtime templates, that is a new versioned interface decision
  rather than a dormant V0.2 field.

Reason:

A recipe selector would recreate fixed atomic operations and hidden backend prompting. The purpose
of V0.2 is to expose one general model call and let Claude formulate its use inside the native
agent loop with as little harness control as possible.

Implementation consequence:

- The request surface remains `instruction`, `inputs`, `capability_tags`, `output`, and optional
  `model_profile`.
- Backend code does not maintain an OCR/diff/align recipe registry or rewrite the instruction from
  a recipe name.

## D-0013: Fix The MCP Identity For `CallMLLM`

Status: accepted  
Date: 2026-07-14

Decision:

- Use MCP server name `mllm` and function name `call`.
- Claude Code therefore sees the tool id `mcp__mllm__call`.
- `CallMLLM` remains the public concept, documentation, and research name.
- B1 introduces the mapping explicitly as “`mcp__mllm__call`, referred to in this policy as
  `CallMLLM`.”

Reason:

The namespaced MCP id is the actual callable identifier in Claude Code, while `CallMLLM` is clearer
in research descriptions and event semantics. Stating both avoids relying on custom display-name
support from a particular FastMCP version.

Implementation consequence:

- The server uses `FastMCP("mllm")` and a tool function named `call`.
- Tool-call traces preserve the raw MCP id and may additionally record the conceptual operation as
  `CallMLLM`/`MLLMCall`.

## D-0014: Freeze The Full B1 Prompt As `b1-callmllm-v0.1`

Status: accepted  
Date: 2026-07-14

Decision:

- Use the complete current B1 prompt for the first V0.2 implementation, not a shortened derivative.
- The prompt source is `docs/design/01-b1-model-tool/system-prompt-v0.1.md` with prompt id
  `b1-callmllm-v0.1`.
- The harness extracts the single fenced `<multimodal_model_tool_policy>` block, replaces only
  `{{MODEL_PROFILE_CATALOG}}`, saves the resolved run snapshot, and passes that file to
  `--append-system-prompt-file`.
- Prompt commentary outside the fence is not sent to Claude.
- Any later compact prompt is a separately versioned prompt-strength variant, not an unrecorded
  modification of V0.1.

Reason:

The current prompt contains the intended human priors, complete capability vocabulary, autonomous
scope/decomposition policy, and detailed instruction examples. Using one full version first keeps
the initial behavior contract explicit; prompt compression can be studied later without changing
the baseline silently.

Implementation consequence:

- Every run stores the prompt id, source hash, resolved prompt hash, and injected public profile
  catalog.
- B1 source changes require a new prompt version rather than editing the frozen V0.1 contract in
  place.

## D-0015: Limit B2 To Task Semantics And Artifact Constraints

Status: accepted  
Date: 2026-07-14

Decision:

- Build the initial image-to-code B2 around four selected task-facing parts: Task Objective, Live
  and Editable Artifact, Layout and Content Layering, and Typography and Visual Fidelity.
- Include only the minimal input, output, entrypoint, and canvas facts required to make the task
  unambiguous.
- Prefer normal flow, flex, and grid for primary structure. Prohibit widespread absolute pinning of
  readable content, while allowing absolute positioning for genuine overlays, decorations, and
  deliberate overlap.
- Do not copy V-harness-specific tool descriptions into B2. This excludes its `grep`, `inspect`,
  `align`, `diff`, and `inpaint` interfaces.
- Do not prescribe the V-harness Playbook or another fixed tool/authoring/rendering/repair sequence.
  Claude Code decides how to execute the task using the capabilities available at runtime.
- Do not include inpainting instructions or assumptions because V0.2 does not currently expose an
  inpainting tool.

Reason:

B2 should contribute task knowledge, not recreate the control logic of the earlier V-harness. This
keeps the task prompt compatible with native `claude -p`, prevents old tool implementations from
leaking into the new experiment, and leaves completion strategy to the agent. The softer layout
policy preserves structural HTML while recognizing that absolute positioning is semantically valid
for some visual elements.

Experimental consequence:

- B2 remains constant across verification ablations and does not itself prescribe verification.
- Observed tool selection and execution order remain agent behavior rather than a task-prompt
  requirement.
- Inpainting cannot become an implicit advantage or hidden dependency in the initial experiment.

Implementation consequence:

- The B2 prompt draft must not contain legacy MCP operation names or a numbered execution Playbook.
- Rendering and tool availability belong to runtime configuration or public environment facts, not
  a mandatory task-solving procedure.
- A future task-specific tool or inpainting capability requires an explicit, versioned design
  change rather than being assumed by B2.

## D-0016: Fix The Initial Image-To-Code Deliverable

Status: accepted  
Date: 2026-07-14

Decision:

- The image-to-code task starts from the reference image provided in the workspace.
- Claude must create a faithful, self-contained, live, and editable web artifact.
- The required entrypoint is a single `answer.html` that opens directly in the configured browser
  environment.
- This decision fixes the entrypoint, not yet the supporting-asset policy, canvas behavior, or
  interaction requirements.

Reason:

A stable entrypoint makes runs and downstream evaluation comparable while leaving implementation
strategy to Claude Code. Keeping the task objective artifact-focused also avoids importing the
earlier V-harness tool workflow.

Implementation consequence:

- Every task workspace exposes the reference image and expects `answer.html` at its root.
- The runtime and evaluator open `answer.html` as the candidate artifact.
- Remaining B2 decisions must clarify what "self-contained" permits without changing this
  entrypoint.

## D-0017: Fix The Remaining Image-To-Code Artifact Semantics

Status: accepted  
Date: 2026-07-14

Decision:

- Treat `answer.html` as the single required entrypoint, not as a prohibition on supporting files.
  Permit local supporting files under `assets/` and prohibit remote dependencies.
- Do not hardcode a reference filename in B2. Use a prompt placeholder that the runtime resolves to
  the actual reference image path, preserving both template and resolved prompt snapshots.
- Optimize the artifact for fidelity at the reference image's dimensions. Keep the implementation
  structurally authored, but do not require inferred responsive behavior at unobserved viewports.
- Require readable text, buttons, inputs, labels, and other interface content to remain real,
  visible DOM content. Permit local assets for photos, logos, icons, illustrations, and complex
  charts.
- Prohibit using the complete reference screenshot as the page or a large background substitute,
  and prohibit baking readable page content into images to imitate live content.
- Reproduce the visible reference state by default. Require interaction only when the task input
  provides an explicit interaction requirement; do not invent behavior from a static screenshot.

Reason:

These rules make the expected artifact evaluable without forcing all bytes into one HTML file or
asking the model to infer information absent from the source. They preserve editable web structure
while allowing legitimate visual assets and keep runs portable by excluding remote dependencies.

Experimental consequence:

- All conditions receive the same reference path, viewport target, asset policy, and interaction
  scope.
- Differences in unsupported responsive or imagined interaction behavior do not confound the
  initial image-to-code comparison.
- Screenshot substitution and text-baking cannot create a misleading appearance of task success.

Implementation consequence:

- The B2 source contains a versioned reference-path placeholder; each run stores its resolved
  prompt snapshot.
- The workspace packager preserves `answer.html` and local `assets/` while rejecting or auditing
  remote runtime dependencies.
- Rendering and offline evaluation use the reference image dimensions as the primary viewport.
- Future responsive or interactive task variants require explicit task inputs and separate
  versioned profiles.

## D-0018: Freeze The B2 Prompt As `b2-image-to-code-v0.1`

Status: accepted  
Date: 2026-07-14

Decision:

- Freeze the complete English image-to-code task prompt as `b2-image-to-code-v0.1` in
  `docs/design/02-b2-task-prompt/task-prompt-v0.1.md`.
- Keep a section-aligned Chinese review translation in `task-prompt-v0.1.zh.md`; the English source
  remains the only normative runtime prompt.
- The harness extracts the English source's only fenced `text` block and replaces only
  `{{REFERENCE_IMAGE_PATH}}`.
- Save the resolved B2 snapshot for every run and assemble it after the shared B1 module.
- Keep all V-harness-specific tools, prescribed workflows, inpainting, and verification treatment
  outside the frozen B2 text.

Reason:

The accepted task semantics can now be expressed as a stable, auditable module without importing
the earlier harness's execution policy. A separate Chinese review translation makes detailed
inspection easier while preserving one unambiguous runtime source.

Implementation consequence:

- The first implementation uses the full frozen B2 prompt without manual shortening or rewriting.
- Run metadata stores prompt ID, frozen template hash, resolved reference path, and resolved prompt
  hash.
- Any wording, placeholder, task-rule, or assembly-order change creates a new B2 prompt version.
- B3 can now vary independently while B1 and B2 remain shared across ablation conditions.

## Decision Template

```text
## D-NNNN: Short title

Status: proposed | accepted | revised | rejected
Date: YYYY-MM-DD

Decision:
Reason:
Alternatives considered:
Experimental consequence:
Implementation consequence:
Open follow-up:
```
