AGPL-3.0-or-later · forever.

showcase · tier 2 · builders

Release radar

Reads your dependencies’ release feeds and diffs against last run, so only new ships reach you.

No ping, nothing shipped. A ping, something worth a look. You stop checking tabs. · conformance-gated in nika-spec ↗ · re-proven at every push

  • 6tasksthe plan falls out of the bindings
  • 3wavesparallel by construction
  • 2verbs exercisedinvoke · infer
  • T2the tierbuilders

The whole file

6 tasks · 3 waves

The plan falls out of the bindings, nothing is scheduled by hand.

release-radar.nika.yamlsource
nika: v1workflow:  id: release-radar  description: "dependency release feed → diff vs last run → only the NEW ships"model: ollama/qwen3.5:4b   # local · zero key · swap for any provider in the catalogconst:  releases_feed: "https://github.com/tokio-rs/tokio/releases.atom"  state_path: "out/release-radar.json"permits:  tools: ["nika:fetch", "nika:jq", "nika:json_diff", "nika:read", "nika:write"]  fs:    # The state-file pattern touches exactly ONE path, on both sides: read    # last run's state, write the next. `const.state_path` names it and a run    # cannot move a const, so the same literal is the whole boundary —    # `create_dirs:` makes out/ underneath it on the first run.    read: ["out/release-radar.json"]    write: ["out/release-radar.json"]  net:    http: ["github.com"]   # the feed's host · net entries are exact names, never globstasks:  # First run has no state file · recover to an empty list.  no_state:    invoke:      tool: "nika:jq"      args: { input: [], expression: "." }  previous:    invoke:      tool: "nika:read"      args: { path: "${{ const.state_path }}" }    on_error:      on_codes: [NIKA-BUILTIN-READ-001]   # not-found ONLY · a permission error still fails loudly      recover: ${{ tasks.no_state.output }}  feed:    invoke:      tool: "nika:fetch"      args:        url: "${{ const.releases_feed }}"        mode: feed    output:      entries: "[.items[] | {title, url, published}]"    on_error:      # No network → this sample stands in for the RAW feed response, so it      # carries `items:` exactly as `mode: feed` returns it and the `output:`      # jq above runs over it unchanged. Recovering the BINDING's shape      # instead makes the jq throw NIKA-VAR-004 — the recovery must mirror the      # response, never the binding.      recover:        items:          - { title: "tokio 1.48.0", url: "https://github.com/tokio-rs/tokio/releases/tag/tokio-1.48.0", published: "2026-07-21T09:14:00Z" }          - { title: "tokio 1.47.1", url: "https://github.com/tokio-rs/tokio/releases/tag/tokio-1.47.1", published: "2026-07-02T16:40:00Z" }  fresh:    with:      previous: ${{ tasks.previous.output }}      entries: ${{ tasks.feed.entries }}    invoke:      tool: "nika:json_diff"      args:        before: "${{ with.previous }}"        after: "${{ with.entries }}"  digest:    with:      fresh: ${{ tasks.fresh.output }}      entries: ${{ tasks.feed.entries }}    when: ${{ size(with.fresh) > 0 }}    infer:      max_tokens: 500      prompt: |        New releases appeared on our dependency radar (RFC 6902 patch        against last run) ·        ${{ with.fresh }}        Full current feed · ${{ with.entries }}        Write 3 bullets · what shipped · whether it looks breaking ·        what to check in our code.  save_state:    with:      entries: ${{ tasks.feed.entries }}    invoke:      tool: "nika:write"      args:        path: "${{ const.state_path }}"        content: "${{ with.entries }}"        create_dirs: true        overwrite: trueoutputs:  new_entries:    value: ${{ tasks.fresh.output }}    description: "RFC 6902 ops · empty = nothing new since last run"  # Untyped on purpose: `digest` is `when:`-gated, so on a quiet week it is  # SKIPPED and this reads null. Exporting it is also what keeps those tokens  # from being dead spend — an infer whose output nothing consumes is paid for  # and thrown away, and `check` says so.  briefing: ${{ tasks.digest.output }}

nika inspect · engine 0.106.1 · vendored graph, never re-derived

6 declared edges · 3 waves · the plan falls out of the bindings