AGPL-3.0-or-later · forever.

the skeleton register

document-to-fields

Your intent sounds like: extract fields from a document and keep the evidence One of 14 skeletons the pack ships, green as-is under nika check. Fill the # SLOT: lines, repair from the fix lines, re-check. Machines read the catalog; the binary lists them with nika new '?'.

  • 3SLOT pointsthe only lines you edit
  • 4patterns lockedarrive correct, stay correct
  • 0tools grantedthe minimum for the job
  • 7f05592bsha-pinnedre-hashed on every test run

the plan

derived from the file, never drawn by hand
normalize_documentinvoke
document_nonemptyinvoke
extractinfer
anchors_presentinvoke
compiledinvoke

the file, whole

conformance-gated upstream on every spec push
document-to-fields.nika.yamlsource
# SPDX-License-Identifier: Apache-2.0# yaml-language-server: $schema=https://nika.sh/spec/v1/workflow.schema.json## TEMPLATE · document-to-fields · source text → anchored facts → nonempty proof.## The source is trimmed and proved nonempty before inference. The extraction# is typed, and every value carries the exact source fragment that supports it.# An empty extraction is refused before it can look like a successful read.## Needs · nothing. Runs offline in an empty directory with mock/echo.# Run · nika run <file> --model mock/echonika: document-to-fieldsmodel: mock/echo                     # SLOT: replace with a local or hosted seatconst:  document: |                        # SLOT: replace with content from nika:read or nika:fetch    Invoice INV-204    Supplier: Northwind Tools    Total: EUR 84.50    Rehearsal marker: mockpermits:  tools: ["nika:jq", "nika:assert"]tasks:  normalize_document:    invoke:      tool: nika:jq      args:        input: ${{ const.document }}        expression: 'gsub("^\\s+|\\s+$"; "")'  document_nonempty:    with:      document: ${{ tasks.normalize_document.output }}    invoke:      tool: nika:assert      args:        condition: ${{ size(with.document) > 0 }}        message: "Document is empty after whitespace is trimmed"  extract:    with:      document: ${{ tasks.normalize_document.output }}    after:      document_nonempty: success    infer:      max_tokens: 600                # SLOT: extraction spend ceiling      prompt: |        Extract only facts explicitly present in this document. For every        value, copy the shortest exact source fragment that anchors it.        ${{ with.document }}      schema:        type: object        additionalProperties: false        required: [fields]        properties:          fields:            type: array            minItems: 1            items:              type: object              additionalProperties: false              required: [name, value, anchor]              properties:                name: { type: string, minLength: 1 }                value: { type: string, minLength: 1 }                anchor: { type: string, minLength: 1 }  anchors_present:    with:      fields: ${{ tasks.extract.output.fields }}      document: ${{ tasks.normalize_document.output }}    invoke:      tool: nika:jq      args:        input: { fields: "${{ with.fields }}", document: "${{ with.document }}" }        expression: '. as $root | ($root.fields | length) > 0 and all($root.fields[]; . as $field | (.name | length) > 0 and (.value | length) > 0 and (.anchor | length) > 0 and ($root.document | contains($field.anchor)))'  compiled:    with:      anchors_present: ${{ tasks.anchors_present.output }}    invoke:      tool: nika:assert      args:        condition: ${{ with.anchors_present }}        message: "Document extraction returned no anchored fields"outputs:  fields: ${{ tasks.extract.output.fields }}

sha256 7f05592b930782fd. The copy above re-hashes to its pin on every test run (a copy is re-provable, never trusted). Source: document-to-fields.nika.yaml in the spec pack · open it in the playground →

the patterns it locks

  • `structured-extraction` | `documents` | trim
  • nonempty assertion
  • typed fields
  • exact source anchors

Scaffold it locally: nika new document-to-fields my-flow.nika.yaml. Try the shape in the playground, or walk the showcase for the same patterns on real work. Read the spec →