AGPL-3.0-or-later · forever.

local API · admission

Read the run before it exists.

Turn check and dry-run output into an admission decision over findings, permits, requirements, cost and wave shape.

check answers whether the file is admissible. dryRunPlan answers what the clean file would ask the engine to schedule. Neither method spends a token or runs a command.

Treat findings as data.

A dirty workflow resolves to a report. Reserve exceptions for process failures such as an unavailable binary so product code can show every finding in one pass.

const report = await nika.check('workflows/release.nika.yaml')

if (!report.clean) {
  for (const finding of report.findings) {
    console.error(finding.code, finding.message)
  }
}

Never read the floor as a ceiling.

The static minimum can be zero while one model remains unpriced. The boolean beside the floor is part of the decision, not optional metadata.

  • min_path_total_usd is the cheapest statically known path
  • has_unbounded means at least one spend branch lacks a finite ceiling
  • a task usd value of null means unpriced, never free

Inspect waves and authority.

Only ask for the plan after a clean report. The result carries task verbs, wave membership, requirements and permits in one versioned object.

[ check ]
    │ clean
    ▼
[ plan v1 ] ── waves
    ├───────── permits
    ├───────── requirements
    └───────── cost floor
if (report.clean) {
  const plan = await nika.dryRunPlan('workflows/release.nika.yaml')
  renderPlan({
    waves: plan.waves,
    tasks: plan.tasks,
    permits: plan.permits,
    requirements: plan.requirements,
  })
}

Survive additive engine releases.

Unknown report or plan versions keep the known subset and append driver warnings. Product code should surface those warnings and retain raw for diagnostics.