Files
markitect-tool/docs/runtime-context-forms-assessments.md

5.4 KiB

Runtime Context, Forms, Rules, And Assessments

Date: 2026-05-04

Purpose

The runtime layer turns contract extension points into executable behavior while keeping the deterministic contract framework intact. Static checks still handle document type, sections, assertions, and metric bands. Runtime checks add external context, field prefill, UI-neutral form state, dynamic rules, and a provider-neutral assessment protocol.

The layer is deliberately local-first. Core Markitect reads YAML or JSON context files and runs deterministic rules. Network calls, application lookups, and LLM providers belong behind adapters.

Context Files

Runtime context can be a raw YAML/JSON mapping:

recipient:
  name: Ada Lovelace
sender:
  name: Markitect Team

or an envelope with metadata and schema:

metadata:
  case_id: case-42
schema:
  type: object
  required: [recipient, sender]
context:
  recipient:
    name: Ada Lovelace
  sender:
    name: Markitect Team

The value under context is bound as context in field sources and dynamic rules. schema validates the full context object. schemas can validate named objects individually.

Malformed context and schema failures produce normal diagnostics:

  • runtime.context.malformed
  • runtime.context.schema_invalid
  • runtime.context.schema_target_missing
  • runtime.context.schema

Field Runtime

Field specs continue to live in the contract:

fields:
  recipient_name:
    type: string
    required: true
    source: context.recipient.name
  delivery_channel:
    type: string
    default: email
    enum: [email, print]

Runtime resolution order is:

  1. Manual document value from path, usually frontmatter.
  2. Context value from source or sources.
  3. Contract default.
  4. Missing.

Manual document values win over context. If both exist and differ, Markitect emits runtime.field.conflict as a warning by default. A field can set conflict: error to make that stricter. Multiple context sources with distinct values produce runtime.field.ambiguous.

mkt contract check uses runtime evaluation only when --context is supplied:

mkt contract check document.md --contract contract.md --context context.yaml

mkt contract form-state always emits the UI-neutral runtime view:

mkt contract form-state document.md --contract contract.md --context context.yaml

Form State

Form state is not a UI framework. It is a stable contract that future UIs, agents, generators, and workflow steps can render:

  • field id
  • value
  • origin: manual, prefilled, defaulted, calculated, or missing
  • required/optional
  • visible/hidden
  • enabled/disabled
  • allowed values
  • diagnostics
  • metadata

Hidden fields are not required unless a future adapter explicitly asks for hidden validation. This matches practical form behavior and avoids punishing authors for data that the current context made irrelevant.

Dynamic Rules

Rules are deterministic YAML. They use a deliberately small condition language:

rules:
  - id: postal-address-for-print
    if:
      path: fields.delivery_channel.value
      equals: print
    then:
      required: [postal_address]
      visible:
        postal_address: true
    else:
      hidden: [postal_address]

Supported condition operators:

  • exists
  • equals / eq
  • not_equals
  • in
  • contains
  • matches
  • gt, gte, lt, lte
  • all, any, not

Supported actions:

  • required / optional
  • visible / hidden
  • enabled / disabled
  • allowed_values
  • set
  • assert
  • sections

Calculated values can reference runtime paths:

then:
  set:
    contact_label: "${fields.sender_name.value} <${context.sender.email}>"

Context assertions use the same condition vocabulary:

assert:
  path: context.sender.email
  matches: "@example\\.com$"
  message: Sender email must come from example.com.
  severity: warning

Dynamic section rules are intentionally narrow. They can require, recommend, discourage, or forbid section specs already declared in the contract.

Assessment Protocol

Rubrics remain provider-neutral contract declarations:

rubrics:
  - id: tone-fit
    scope: section.body
    criteria: The body should match the recipient relationship.
    threshold: 0.75

Core Markitect turns rubrics into AssessmentRequest objects and normalizes adapter results into AssessmentResult and diagnostics. It does not call an LLM provider directly. The cache key includes contract id, rule id, scope, text, criteria, context, structured inputs, threshold, provider, model, and metadata.

Adapters can be injected from workflows, applications, or tests. A transparent in-memory cache exists for tests and short runs; persistent storage remains a backend concern.

Workflow Integration

Workflow contract_check steps accept context:

steps:
  - id: check-letter
    kind: contract_check
    document: letter.md
    contract: letter.contract.md
    context: letter.context.yaml

Workflow form_state steps expose the runtime state as a step result:

steps:
  - id: form
    kind: form_state
    document: letter.md
    contract: letter.contract.md
    context: letter.context.yaml

This keeps workflow orchestration separate from the runtime engine. The runtime engine answers "what does this contract imply in this context"; the workflow engine decides when to run it and where to send the output.