Refinement Harness Architecture¶
This document describes the canonical refinement harness shape for Mozaiks.
The Refinement Engine is the framework layer that sits above workflow-local AG2 execution and decides what should happen when a harnessed request or checkpoint event arrives.
It is the piece that makes the Mozaiks build and refinement UX feel intent-aware without turning every workflow into a giant router.
Purpose¶
The harness exists for requests that are not well modeled as:
- normal runtime chat
- workflow-local handoffs
- workflow-local task batching
- workflow transition routing
Examples:
- "Fix this generated dashboard."
- "Add export controls to the current app."
- "Restart this from concept."
- "This should become investor-facing."
In the first-party builder experience today, this refinement loop is driven by startup declared through app/config/ai.json, refinement runtime policy in app/config/refinement_policy.yaml, and the selected refinement_harness/config/harness.yaml pack. Do not document a dedicated RefinementWorkflow unless the runtime actually introduces one. Normal chat/workflow startup comes from app/config/ai.json; refinement policy and harness routing only take over once a refinement request or checkpoint needs routed work.
Those requests need:
- persisted session/artifact context
- intent interpretation
- deterministic continuation policy
- optional coding refinement
- clear user-facing decisions
That is the Refinement Engine.
Two Paths: Factory vs. Harness¶
First-time builds bypass the Refinement Engine entirely. They enter through extension_registry.json workflow sequences directly:
User starts a new build
→ extension_registry.json "build" sequence
→ ValueEngine → ThemeCapture → DesignDocs → AgentGenerator → AppGenerator
Refinements (user already has a built artifact and wants to change it) enter the Refinement Engine:
User submits a change request on an existing artifact
→ Refinement Engine
→ checkpoint: classify the change
→ checkpoint: route to a workflow_sequence
→ checkpoint: decide — direct code edit or factory re-run?
Path A — small targeted change (patch):
→ scope_selection find which files to touch
→ coding_refinement write the scoped change
[AppGenerator never runs]
Path B — bigger change (design / feature / core):
→ contract_surface_planning map request to contract surfaces
→ launch workflow_sequence re-enter factory at the right stage
[AppGenerator runs as part of the sequence]
The Refinement Engine does not replace the factory. It routes to it.
Checkpoint Chain¶
Checkpoints are triggered by events, not by agent turns. Each checkpoint is a discrete unit of work with a declared handler and optional LLM backing.
Full sequence (patch path — direct code edit)¶
request_submitted LLM classifies: patch / design / feature / core
│
route_requested deterministic: {artifact_kind, change_class} → workflow_sequence
│
decision_requested deterministic: direct edit eligible? → auto_patch | workflow_reentry | ...
│
scope_requested LLM selects files to touch using context graph + artifact workspace
│
coding_requested LLM writes scoped code change against selected files
Sequence for design / feature (contract surface path)¶
request_submitted classify → design or feature
│
route_requested → workflow_sequence e.g. "app_revision"
│
decision_requested → workflow_reentry
│
contract_surface_requested LLM maps request to contract surfaces needing update
│
workflow re-entry launch selected workflow_sequence from extension_registry.json
Checkpoint reference¶
| Checkpoint | Event | Handler type | What it does |
|---|---|---|---|
request_intake | request_submitted | LLM | Classifies change as patch / design / feature / core. Reads artifact state and staleness. |
refinement_route | route_requested | Deterministic | Maps {artifact_kind, change_class} to a workflow_sequence name from the routing table. |
decision | decision_requested | Deterministic | Decides outcome: auto_patch, workflow_reentry, core_restart, clarify_scope, or fallback_workflow. |
scope_selection | scope_requested | LLM | Proposes which files to touch using context graph and artifact workspace catalog. |
contract_surface_planning | contract_surface_requested | LLM | Maps a broader request to specific Mozaiks contract surfaces before workflow re-entry. |
coding_refinement | coding_requested | LLM | Writes the scoped code change against the selected files. |
Routing Table¶
The routing table in harness.yaml maps each combination of artifact kind and change class to a named workflow_sequence. The sequence name is resolved from extension_registry.json — the Refinement Engine declares the target name only; the sequence declares which workflows run and in what order.
harness.yaml extension_registry.json
──────────────────────────────────── ──────────────────────────────────────────
{artifact_kind: app_bundle}
patch → workflow_sequence: app_revision steps: [AppGenerator]
design → workflow_sequence: app_surface_revision steps: [DesignDocs, AppGenerator]
feature → workflow_sequence: app_revision steps: [AppGenerator]
core → workflow_sequence: full_rebuild steps: [ValueEngine, ThemeCapture,
DesignDocs, AgentGenerator,
AppGenerator]
{artifact_kind: design_docs}
patch → workflow_sequence: design_patch steps: [DesignDocs]
design → workflow_sequence: design_revision steps: [DesignDocs]
feature → workflow_sequence: design_revision steps: [DesignDocs]
core → workflow_sequence: full_rebuild
{artifact_kind: workflow_bundle}
patch → workflow_sequence: workflow_patch steps: [AgentGenerator]
design → workflow_sequence: workflow_revision steps: [AgentGenerator]
feature → workflow_sequence: workflow_revision steps: [AgentGenerator]
core → workflow_sequence: full_rebuild
{artifact_kind: concept}
patch → workflow_sequence: concept_patch steps: [ValueEngine]
design → workflow_sequence: full_rebuild
feature → workflow_sequence: full_rebuild
core → workflow_sequence: conceptual_replan steps: [ValueEngine, ThemeCapture,
DesignDocs, AgentGenerator,
AppGenerator]
(with carry_forward context)
The Refinement Engine does not declare affected_workflows or affected_declarative_families. Those are owned by the sequence in extension_registry.json.
Staleness-aware classification¶
The classifier reads get_stale_artifact_families before finalising the change class. If an upstream artifact family is stale relative to the target, the classifier upgrades the class so the chosen route covers the stale upstream:
User wants: app_bundle patch
But: design_docs is stale
→ classifier upgrades to "design" so the route runs DesignDocs first
This prevents the factory from re-running AppGenerator on top of stale upstream artifacts.
Ownership Model¶
mozaiksai/core/¶
Framework-wide primitives that are not specific to the Refinement Engine itself.
Examples:
- generic runtime utilities
- session/runtime internals
- workflow/runtime foundations
mozaiksai/control_plane/¶
The canonical Refinement Engine subsystem.
mozaiksai/control_plane/
__init__.py
config.py
contracts.py
executor.py
loader.py
ports.py
runtime.py
schema.py
tools/
get_revision_context.py
implementations/
change_classifier.py
coding_worker.py
contract_surface_planner.py
harness_decision.py
orchestration_control.py
refinement_router.py
scope_proposer.py
This layer owns:
- Refinement Engine runtime
- checkpoint dispatch
- config/schema/loader/contracts
- generic tool execution boundaries
- first-party Mozaiks checkpoint handlers
This is the canonical runtime package.
factory_app/refinement_harness/¶
First-party builder/reference app declaratives and builder-specific tools.
factory_app/refinement_harness/
config/
harness.yaml
refinement_policy.yaml
tools.yaml
policies.yaml
prompts/
change_classifier_system.yaml
coding_refinement_system.yaml
coding_scope_selection_system.yaml
contract_surface_selection_system.yaml
tools/
get_artifact_summary.py
get_artifact_workspace_catalog.py
get_artifact_workspace_scope.py
get_carry_forward_candidates.py
get_context_graph_catalog.py
get_context_graph_scope.py
get_contract_surface_context.py
get_stale_artifact_families.py
read_carry_forward_module_contract.py
resolve_carry_forward_preservation.py
_artifact_workspace.py
_context_graph.py
_module_inventory.py
_shared.py
ui/
factory_app is the first-party builder/reference app workspace. It should feel like an authored app surface, not the owner of the framework runtime.
This layer owns:
- the first-party declarative refinement harness
- first-party prompt text
- first-party artifact/workspace context tools
- future refinement UI surfaces
It should not own the runtime engines.
What The Harness Is Not¶
The harness is not:
- a workflow
- an AG2 1.0 beta workflow run
- a module handler under
app/modules/* - a global prompt wrapped around every message
- a replacement for
extension_registry.json
The split is:
- Refinement Engine
- interprets checkpoint events
- decides continuation
- extension graph
- defines legal workflow movement
- AG2/workflows
- execute once a workflow is selected
Pack Model¶
Startup stays in app/config/ai.json; refinement policy and routing stay in the refinement artifacts:
app/config/ai.json ask/chat/workflow startup
app/config/refinement_policy.yaml LLM profiles and refinement capability flags
refinement_harness/config/harness.yaml artifact routes and LLM-backed checkpoints
app/config/refinement_policy.yaml provides model config. harness.yaml does not point to Python implementation files.
The default declarative pack lives under factory_app/refinement_harness/. Apps that need local refinement behavior add <workspace>/refinement_harness/config/harness.yaml as an overlay with extends: mozaiks.default_refinement_harness and only app-specific overrides.
Generated App Authoring¶
Most generated apps do not need an app-local Refinement Engine. They should use ordinary workflow launches, module actions, and extension_registry.json workflow sequences first.
AppGenerator may emit an app-local harness overlay only when the product explicitly needs checkpointed lifecycle, refinement, session, or coding-control behavior that cannot be expressed as normal workflow transitions.
See app/refinement-harness.md for the overlay contract and guidance on which app-specific deltas are allowed.
Ownership Split¶
Keep startup separate from the harness pack:
app/config/ai.jsonownsask,chat, andworkflowsstartupapp/config/refinement_policy.yamlowns runtime policy (LLM profiles, feature flags)refinement_harness/config/harness.yamlowns declarative checkpoints and routing
AppGenerator Build Task¶
The canonical AppGenerator build task for a refinement harness:
task_type: refinement_harness
surface_kind: refinement
capability_pack_id: null
initial_agent: RefinementHarnessAgent
owned_paths:
- config/refinement_policy.yaml
- refinement_harness/config/harness.yaml
Optional owned paths:
- refinement_harness/config/tools.yaml
- refinement_harness/config/policies.yaml
- refinement_harness/prompts/*.yaml
The default generated harness manifest is:
schema_version: mozaiks.refinement_harness.v1
extends: mozaiks.default_refinement_harness
overrides: {}
Optional files must contain only app-specific deltas. Do not copy default OSS routes, checkpoints, policies, tools, or prompts into generated app workspaces.
Pack Constraints¶
Generated refinement harnesss are declarative only:
- no
module.yaml - no
app/modules/* - no
backend/control_plane/*.py - no custom harness Python
- no business-domain logic
The generated pack uses shipped mozaiksai.control_plane implementations and declared tool entrypoints from mozaiksai.control_plane.tools.* and factory_app.refinement_harness.tools.*. Custom harness Python is not a v1 generator contract.
Route Rules¶
harness.yamlroutes declareworkflow_sequenceonly.- each
workflow_sequencemust exist inworkflows/extended_orchestration/extension_registry.json - sequence impact metadata, including
affected_declarative_families, lives on the sequence inextension_registry.json, not inharness.yaml - do not declare
affected_workflows,requires_replanning, orrequires_rebuildin route manifests; these are derived at runtime
Declarative Files¶
config/harness.yaml¶
The factory default pack declares:
- artifact routing
- checkpoint events
- prompt ids
- tool ids
App-local packs normally declare only an overlay:
schema_version: mozaiks.refinement_harness.v1
extends: mozaiks.default_refinement_harness
overrides: {}
Factory default example:
schema_version: mozaiks.refinement_harness.v1
routing:
default_artifact_kind: app_bundle
artifacts:
- artifact_kind: app_bundle
label: app bundle
routes:
patch:
workflow_sequence: app_revision
design:
workflow_sequence: app_surface_revision
feature:
workflow_sequence: app_revision
core:
workflow_sequence: full_rebuild
checkpoints:
- event: request_submitted
prompt_id: change_classifier_system
tool_ids:
- get_revision_context
- get_artifact_summary
- event: route_requested
- event: decision_requested
- event: scope_requested
prompt_id: coding_scope_selection_system
tool_ids:
- get_revision_context
- get_artifact_summary
- get_artifact_workspace_catalog
- event: contract_surface_requested
prompt_id: contract_surface_selection_system
tool_ids:
- get_contract_surface_context
- event: coding_requested
prompt_id: coding_refinement_system
tool_ids:
- get_revision_context
- get_artifact_summary
- get_artifact_workspace_scope
Route rules:
workflow_sequenceis the canonical route target.- The sequence is resolved from
extension_registry.json. - If a route must start at a different workflow, define a dedicated sequence with that workflow first.
- Do not declare
affected_workflowsinharness.yaml; it is derived from the selected sequence. - Do not declare
affected_declarative_familiesinharness.yaml; it is declared once on the selected sequence inextension_registry.json. - Do not declare
requires_replanning; it is derived from the typed change class:patch=false,design|feature|core=true. - Do not declare
requires_rebuild; Refinement Engine rebuild decisions are runtime decision outputs, not route manifest inputs.
config/tools.yaml¶
Declares harness-owned tools. The default file lives in factory_app/refinement_harness/config/tools.yaml; app-local tools.yaml files are deltas only.
Example:
tools:
- id: get_artifact_summary
kind: context_tool
description: Load artifact lineage and version metadata.
entrypoint: factory_app.refinement_harness.tools.get_artifact_summary:get_artifact_summary
available_to:
- request_submitted
- route_requested
prompts/*.yaml¶
One prompt per file. The default prompts live in factory_app/refinement_harness/prompts/; app-local prompt files are overrides only.
Example:
id: change_classifier_system
content: |
You are the authoritative Mozaiks refinement change classifier.
config/policies.yaml¶
Declares deterministic bounds.
Current first use:
- scope size limits
- auto-apply thresholds
- overflow behavior
Checkpoint Model¶
The Refinement Engine is checkpoint-driven.
Current first-party checkpoints:
request_submittedroute_requesteddecision_requestedscope_requestedcontract_surface_requestedcoding_requested
These are the harness-native units of execution.
request_submitted¶
LLM-backed interpretation of the request.
Current first-party handler:
mozaiksai/control_plane/implementations/change_classifier.py
route_requested¶
Deterministic workflow-route selection from typed request intent.
Current first-party handler:
mozaiksai/control_plane/implementations/refinement_router.py
decision_requested¶
Deterministic user-facing decision shaping.
Examples:
workflow_reentrycore_restartauto_patchclarify_scopefallback_workflow
Current first-party handler:
mozaiksai/control_plane/implementations/harness_decision.py
scope_requested¶
LLM-backed file-scope proposal when explicit coding scope is missing.
Current first-party handler:
mozaiksai/control_plane/implementations/scope_proposer.py
contract_surface_requested¶
LLM-backed contract surface planning for feature and design refinements. Maps the request to the specific Mozaiks contract surfaces that need updating (module_action, page_binding, data_schema, workflow_agent, etc.) before workflow re-entry. Fires when a request is broader than a coding patch but narrow enough to target specific contract surfaces rather than a full rebuild.
Current first-party handler:
mozaiksai/control_plane/implementations/contract_surface_planner.py
coding_requested¶
Scoped coding-worker execution for eligible patch refinements.
Current first-party handler:
mozaiksai/control_plane/implementations/coding_worker.py
Staged Coding Worker¶
The staged coding worker (mozaiksai/control_plane/implementations/coding_worker.py) is the checkpoint handler that applies LLM-generated file edits during a coding refinement turn. It bridges between an LLM checkpoint's structured output and the staging area.
Flow¶
LLM coding checkpoint
→ structured output: list[{path, new_content, reason}]
→ apply_scoped_refinement_changes() # scoped_execution.py
→ path safety checks (no traversal, no secrets, no absolute paths)
→ write files into staging area (never live workspace)
→ return ScopedRefinementResult
→ run_app_source_validation() # app_validation.py (optional)
→ copy staging area into isolated temp dir
→ apply staged files as overlay
→ run framework-detected lint/test commands
→ return AppSourceValidationResult
→ persist staged artifact version
→ emit tool event to Studio panel
What the coding worker does NOT do¶
- It does not modify the live workspace. All writes go to a staging area.
- It does not interpret the LLM's reasoning. It receives already-typed structured output and applies it deterministically.
- It does not run validation unless
confirm_execution=Trueis passed. The default is to plan validation commands and return them without running. - It does not promote staged changes. Promotion requires a separate acceptance step through the Studio promotion flow.
Security guarantees from scoped execution¶
Every path written by the coding worker passes through apply_scoped_refinement_changes(), which enforces:
- no
..traversal components - no absolute paths (Windows drive qualifiers or POSIX
/prefixes) - no secret-sensitive filenames (
.env,id_rsa,.pem,.key, etc.) - new files only created inside directories already referenced in the change set
Files that fail these checks get status skipped_unsafe or skipped_secret and are never written. The worker reports these in the tool event so Studio can surface them.
Tool Model¶
Refinement Engine tools are leaf capabilities used by checkpoints.
They are not:
- AG2 agent tools
- workflow-local lifecycle tools
- module actions
Examples:
get_revision_contextget_artifact_summaryget_artifact_workspace_catalogget_artifact_workspace_scoperun_app_source_validation
The current first-party tools live under:
factory_app/refinement_harness/tools/*
AG2 Implementation Model¶
LLM-backed checkpoints use ag2.Agent.ask() to enforce structured outputs without custom JSON-parsing fallbacks.
Structured Output Pattern¶
Every LLM-backed handler follows this pattern:
agent = self._make_agent(system_prompt=system_prompt, llm_config=llm_config)
stream = MemoryStream()
reply = await agent.ask(
user_prompt,
stream=stream,
middleware=[RetryMiddleware(max_retries=2)],
observers=[TokenMonitor()],
response_schema=ChangeClassifierResult,
)
result = await reply.content()
response_schema— AG2 enforces the Pydantic model at the provider level. No JSON extraction or repair is needed in handler code.RetryMiddleware(max_retries=2)— transient failures retry automatically.TokenMonitor()— token accounting without custom hooks.MemoryStream— captures the full conversation for observability.
Agent Factory Injection¶
Every LLM-backed handler accepts an agent_factory callable:
LLMChangeClassifier(
agent_factory=lambda system_prompt, llm_config: _FakeAgent(system_prompt, llm_config),
config_loader=...,
pack_loader=...,
)
Production code passes None — the default builds a real Agent from the resolved llm_config. Tests inject a fake agent that records calls and returns preset structured responses without hitting the network. This makes every checkpoint independently unit-testable.
LLM-backed checkpoints:
| Checkpoint | Handler | Response schema |
|---|---|---|
request_submitted | LLMChangeClassifier | ChangeClassifierResult |
scope_requested | ArtifactScopeProposer | ScopeProposal |
contract_surface_requested | ContractSurfacePlanner | ContractSurfacePlan |
coding_requested | ScopedRefinementCodingWorker | CodingWorkerPlan |
Deterministic checkpoints (route_requested, decision_requested) do not use AG2 at all — they derive results from typed inputs and routing tables.
LLM Config Resolution¶
LLM config flows from the declarative pack, not from workflow-local AG2 config:
app/config/refinement_policy.yamldeclaresllm_profileskeyed by capability name, each withmodelandtemperature.ControlPlaneConfig.resolve_capability_llm_config(capability)returns a flat{"model": ..., "temperature": ...}dict for the resolved profile.- The dict maps directly to
OpenAIConfig(model=..., temperature=...)inside each handler's_make_agent().
Capability-level llm_config values in app/config/refinement_policy.yaml take precedence only when that capability does not reference an llm_profile. Do not put refinement model overrides in app/config/ai.json.
Runtime Flow¶
At runtime:
mozaiksai/core/runtime/app/ai_config.pyresolves startup fromapp/config/ai.jsonmozaiksai/control_plane/config.pyresolves runtime policy fromapp/config/refinement_policy.yamlmozaiksai/control_plane/loader.pyresolves the active pack fromrefinement_harness/config/harness.yamlmozaiksai/control_plane/runtime.pybuilds a checkpoint runtimeOrchestrationControlHarnessbinds the loaded declarative pack- the harness runs the checkpoints it needs
Current Studio refinement flow:
Studio trigger
-> OrchestrationControlHarness
-> request_submitted (LLMChangeClassifier)
-> route_requested (RefinementTriggerRouteResolver)
-> decision_requested (FirstPartyHarnessDecisionPolicy)
-> SessionRouter | coding worker | harness decision response
If coding is eligible (patch + scoped files):
If contract surface planning is needed (feature or design):
... -> contract_surface_requested (ContractSurfacePlanner)
-> workflow re-entry via resolved workflow_sequence
Relation To Workflows And Extensions¶
The harness depends on the workflow graph, but it is not the graph.
extension_registry.json- legal transitions and workflow movement
- Refinement Engine
- semantic interpretation and continuation choice
- workflow runtime
- actual execution
This is why the harness was required for the Mozaiks build UX. The extension graph alone cannot interpret "make this a blockchain marketplace" or decide between clarify_scope, run_workflow, or restart_upstream.
Host Model¶
Today the first-party harness is mounted by Studio.
That means:
- Studio is the primary harnessed surface
- platform/runtime apps should remain passthrough unless they opt in later
Host-aware gating still matters, but the canonical runtime ownership is now correct.
Identity Module¶
This path still exists:
It is only the zero-action Studio identity module.
It is not the harness runtime.
Canonical Paths¶
Use these paths as source of truth:
mozaiksai/control_plane/*factory_app/refinement_harness/config/*factory_app/refinement_harness/prompts/*factory_app/refinement_harness/tools/*
Do not treat these as canonical:
factory_app/app/modules/factory_control_plane/backend/*
Guidance¶
If you are changing framework runtime behavior:
- edit
mozaiksai/control_plane/*
If you are changing the first-party builder pack:
- edit
factory_app/refinement_harness/config/* - edit
factory_app/refinement_harness/prompts/* - edit
factory_app/refinement_harness/tools/*
If you are looking at the identity module under app/modules/..., you are not in the live harness runtime.