AGPL-3.0-or-later · forever.

the skeleton register

evaluate-and-optimize

Your intent sounds like: critique and improve a draft for a fixed number of rounds 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 '?'.

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

the plan

derived from the file, never drawn by hand
draftinfer
evaluate_1infer
optimize_1infer
evaluate_2infer
optimize_2infer
final_evaluateinfer

the file, whole

conformance-gated upstream on every spec push
evaluate-and-optimize.nika.yamlsource
# SPDX-License-Identifier: Apache-2.0# yaml-language-server: $schema=https://nika.sh/spec/v1/workflow.schema.json## TEMPLATE · evaluate-and-optimize · draft → two fixed critique/revision rounds.## The bound is structural: exactly two revision rounds are unrolled in the DAG,# followed by one score-only measurement of the final result. The model cannot# add another turn, and every infer has its own token ceiling.## Needs · nothing. Runs offline in an empty directory with mock/echo.# Run · nika run <file> --model mock/echonika: evaluate-and-optimizemodel: mock/echo                     # SLOT: replace with a local or hosted seatconst:  brief: "Explain why idempotent retries matter in two sentences."   # SLOTpermits: {}tasks:  draft:    infer:      max_tokens: 300      prompt: "Draft this deliverable: ${{ const.brief }}"      schema:        type: object        additionalProperties: false        required: [text]        properties:          text: { type: string, minLength: 1 }  evaluate_1:    with:      candidate: ${{ tasks.draft.output.text }}    infer:      max_tokens: 200      prompt: |        Critique this candidate against the brief. Name one concrete repair.        Brief: ${{ const.brief }}        Candidate: ${{ with.candidate }}      schema:        type: object        additionalProperties: false        required: [score, repair]        properties:          score: { type: integer, minimum: 0, maximum: 100 }          repair: { type: string, minLength: 1 }  optimize_1:    with:      candidate: ${{ tasks.draft.output.text }}      repair: ${{ tasks.evaluate_1.output.repair }}    infer:      max_tokens: 300      prompt: |        Revise the candidate using the repair, without changing the brief.        Candidate: ${{ with.candidate }}        Repair: ${{ with.repair }}      schema:        type: object        additionalProperties: false        required: [text]        properties:          text: { type: string, minLength: 1 }  evaluate_2:    with:      candidate: ${{ tasks.optimize_1.output.text }}    infer:      max_tokens: 200      prompt: |        Critique this revision against the same brief. Name one final repair.        Brief: ${{ const.brief }}        Candidate: ${{ with.candidate }}      schema:        type: object        additionalProperties: false        required: [score, repair]        properties:          score: { type: integer, minimum: 0, maximum: 100 }          repair: { type: string, minLength: 1 }  optimize_2:    with:      candidate: ${{ tasks.optimize_1.output.text }}      repair: ${{ tasks.evaluate_2.output.repair }}    infer:      max_tokens: 300      prompt: |        Produce the final revision using the last repair.        Candidate: ${{ with.candidate }}        Repair: ${{ with.repair }}      schema:        type: object        additionalProperties: false        required: [text]        properties:          text: { type: string, minLength: 1 }  final_evaluate:    with:      candidate: ${{ tasks.optimize_2.output.text }}    infer:      max_tokens: 200      prompt: |        Score the final candidate against the brief. Evaluate the candidate        exactly as written without proposing another revision.        Brief: ${{ const.brief }}        Candidate: ${{ with.candidate }}      schema:        type: object        additionalProperties: false        required: [score, reason]        properties:          score: { type: integer, minimum: 0, maximum: 100 }          reason: { type: string, minLength: 1 }outputs:  result: ${{ tasks.optimize_2.output.text }}  final_score: ${{ tasks.final_evaluate.output.score }}

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

the patterns it locks

  • `bounded-loop` | `quality` | two unrolled revisions
  • score-only final evaluation
  • every infer capped

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