Skip to content

Releases: punarduttrajput/wovyr

Release list

v0.4.1

Choose a tag to compare

@github-actions github-actions released this 05 Aug 06:59

A patch release covering the release pipeline itself. No library, server, or
CLI behavior changed.

Fixed

  • Releases publish to crates.io. The release workflow had no cargo publish
    step at all, so the registry behind the README's own first quickstart command
    (cargo install wovyr-cli) only ever advanced when somebody ran it by hand —
    it sat at 0.3.2 while the repo, the README badge, and /healthz all
    reported 0.4.0. A new crates job publishes every publishable workspace
    member with cargo publish --workspace, which derives the upload order from
    the dependency graph rather than a hand-maintained list, behind a
    sparse-index pre-flight that excludes anything already published at its
    current version — so a partial run is recovered by re-running the job instead
    of by hand.
  • The npm and PyPI publish steps can run at all. Both bound their token to
    the step's own env: and then tested it in that same step's if: — a
    condition that can never be true, since secrets cannot be referenced from
    if: and a step's env: is not populated when its if: is evaluated. Both
    steps reported skipped on every release run that has ever existed (v0.3.1,
    v0.3.2, v0.4.0) while the job and the workflow still went green, which is why
    every version currently live on npm and PyPI was in fact published manually.
    The token check moved inside each script, where a skip leaves an explanatory
    log line, and both publishes are now idempotent
    (twine upload --skip-existing, plus an npm view pre-check since npm has no
    equivalent flag).
  • @wovyr/angular's version tests no longer assert the wrong generation.
    They hardcoded 0.3.x as the matching series and 0.4.0 as a mismatch, so
    both inverted and began failing the moment TARGET_SERVER_VERSION moved to
    0.4.x — undetected, because that package has no CI job. The fixtures now
    derive from TARGET_SERVER_VERSION, so they stay correct across future bumps.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 01 Aug 16:58

A minor bump rather than a patch: the Wasmtime upgrade below changes the
wovyr-tools wasi feature's public surface, and this project follows semver
from 0.3.0 onward.

Fixed

  • A quota breach reports figures at the scale they actually occur. The
    llm_cost_per_day_usd message formatted every amount {:.4}, so a breach at real
    per-call scale — a gpt-4o-mini reply costs on the order of $0.000008 — read
    llm_cost_per_day_usd: 0.0000 + 0.0000 exceeds limit 0.0000: it named the metric
    and then told the operator nothing about what was spent, what was requested, or
    what the ceiling was. A new usd_precision picks the decimal places needed to show
    three significant digits (two for human-scale money, capped at eight), and the
    three figures in one message share that precision so the comparison lines up
    digit for digit — the admission check runs before the call, so its delta is 0.0,
    and a bare 0.00 beside eight-decimal siblings reads like a different unit
    (crates/wovyr-tenancy/src/quota.rs). Live:
    llm_cost_per_day_usd: 0.00000420 + 0.00000000 exceeds limit 0.00000100, with a
    dollar-scale budget still reading in plain dollars.

  • image_generate is available to workflows run --local, not just
    agents run --local.
    The tool was registered inline in the agent command's own
    body, so a workflow tool activity naming it failed with a bare unknown tool
    even with a provider key configured — while the same activity worked against the
    server, whose one shared registry has it. Registration moved into
    local_registry, the constructor both CLI paths already funnel through, so the
    asymmetry is now unrepresentable rather than merely fixed — the argument HLTH-901
    made for the executor, applied to the registry
    (apps/wovyr-cli/src/main.rs,
    workflow.rs). It stays conditional on a
    configured key (it needs a real, billed API), and the workflow runner now builds
    one gateway shared by its registry and executor, so image_generate routes
    through the same retry/failover/breaker pipeline as every other call. Guarded by
    tests asserting both paths produce identical tool sets at each privilege level,
    and that the tool's presence follows the key rather than the command.

  • The test suite no longer reads or writes the developer's real ~/.wovyr.
    cargo test --workspace resolved durable stores through
    wovyr_config::paths::*, which read HOME/USERPROFILE — so every run left
    test tenancy quotas (prj-quota-test, prj-async-block) sitting in live local
    state, wrote workflow checkpoints and event logs (test-exec-1.*) into the real
    workflow store, and appended test entries to the real tamper-evident audit
    chain
    (found at ~380 KB and growing on the machine this was fixed on). Beyond
    the pollution, it meant a test run and a wovyr dev on the same machine shared
    files, and pre-existing local state could influence results. AppState::for_test
    already isolated the two stores whose contents tests assert on, but everything
    else from_env builds — the audit chain, tenancy, the workflow store, the KMS
    root key, secrets, the async-run and webhook-outbox files — still landed in the
    real directory. wovyr_config::root gained a process-wide root override
    (set_root_override/redirect_to_scratch/root_override), which
    AppState::for_test and the authz_matrix integration test call before building
    anything (root.rs,
    state.rs). Overriding one function covers
    every resource directory, because they all already resolve through
    root::wovyr_dir() — the previous comment on for_test called this "a larger
    change that would have to thread a state-root parameter through every
    crate::config::*_dir() helper", which was not the case; that comment is
    corrected. Redirection is per process, not per test: tests in one binary
    share a scratch root exactly as they previously shared the real one, isolated
    from the user rather than from each other, so the two per-AppState store swaps
    stay. Guarded by a test asserting the suite's resolved root is under the temp dir
    and is not the home-derived path, plus wovyr-config unit tests for the
    override's first-call-wins semantics and its reach across every paths::*
    helper.

  • wovyr plugin build <project> works with a relative path. The documented
    flow — wovyr plugin new hello-tool then wovyr plugin build hello-tool — failed
    for every relative argument with "no build output at hello-tool\target\…".
    build_cmd derived a relative --target-dir from the project argument and then
    ran cargo with current_dir(project), so cargo resolved that path a second time
    against the new cwd and wrote the module to hello-tool/hello-tool/target/… while
    the command looked for it one level up. An absolute argument happened to work,
    which is why the round-trip test — using a scratch temp dir — never caught it. A
    new build_paths resolves the project once, up front, so every downstream path is
    cwd-independent (apps/wovyr-cli/src/scaffold.rs),
    with unit tests pinning that both resolved paths are absolute and that the target
    dir is never re-resolved against the project dir. Verified against the real binary:
    plugin new hello2 && plugin build hello2 now stages hello2.wasm + a
    digest-complete plugin.yaml, with no nested hello2/hello2/ directory.

  • Three shipped example workflows run again. greet-and-fetch.yaml,
    saga-order.yaml (all five activities) and support.yaml declared
    type: function with no name, which RM-GA-P4 HLTH-901 turned into a permanent
    activity failure when it unified function and tool onto one tool-invoking
    dispatch — so each died on its first activity. Two of them are reachable straight
    off a README quickstart line. All three now name echo explicitly.
    The comment in crates/wovyr-runtime/src/lib.rs
    that justified the unification claimed "every real example/test that uses
    type: function already expects a tool invocation" — it did not, and that wrong
    premise is why the breakage shipped; it now records what actually broke, and notes
    that wovyr-workflow's own engine tests still use nameless function activities
    (they supply their own executor and never reach this dispatch, so they were never
    evidence either way). A new test walks every examples/workflows/*.yaml and fails
    if a function/tool activity lacks a nameDefinition::from_yaml can't
    catch this, since name is legitimately absent on wait/human/for_each, so
    the breakage only ever surfaced when a human ran the example.

  • A quota set on a nonexistent project is refused instead of silently accepted.
    PATCH /api/v1/projects/{id}/quota wrote to the quota map by raw id with no
    existence check, so a typo'd project — or an empty id from a doubled slash —
    returned 200 and persisted a limit under a key no run would ever consult, while
    GET returned 200 {} for the same ghost project, even though
    GET /api/v1/projects/{id} itself correctly 404s. An operator got a success
    response for a budget enforcing nothing: the same silent-no-op class as an unpriced
    model reporting $0. Both handlers now check the project exists first
    (crates/wovyr-server/src/tenancy.rs), with
    a regression test asserting both routes 404 and that the rejected write leaves no
    stored limits behind.

  • A rolled-back saga is reported as Failed, not Completed. After a clean
    rollback the engine transitioned the execution to Completed, so a saga whose
    activity failed was missing from ?status=failed and listed among the
    successes
    — while its own event log said workflow_failed and the CLI printed
    "rolled back after failure". Every durable surface (Engine::status/query/
    list, GET /api/v1/workflows?status=, any dashboard over them) reads that
    checkpoint status, so the wrong value was the one operators actually see. The
    terminal state is now Failed — the compensation succeeded, the workflow did
    not — and CompensationCompleted in the event log is what distinguishes "failed,
    and rolled back cleanly" from a bare failure. (Compensating, Completed) is
    removed from the transition table and (Compensating, Failed) added, so the old
    state is now unreachable by construction rather than merely unused
    (state.rs,
    engine.rs). A failed rollback still stays
    non-terminal in Compensating, by design. Chosen over adding a distinct
    Compensated state, which would have been a breaking wire/on-disk change for a
    distinction the event log already carries;
    compensation-engine.md's state
    diagram — whose ambiguity is arguably what licensed the original behavior — now
    says so explicitly.

  • Real cost is recorded behind an OpenAI-compatible gateway that renames the
    model.
    PriceBook::price matched a model id only from the left (exact, then
    longest known key that is a prefix), so a vendor-prefixed id matched nothing:
    OpenRouter answers a request for gpt-4o-mini with openai/gpt-4o-mini, and cost
    is deliberately keyed on the model the upstream reports it billed, so every
    call logged no price for model and no default configured and reported
    cost_usd: 0.000000. That silently reinstated the failure class RM-AIM-P1 PRV-101
    existed to remove — wovyr-server's per-project llm_cost_per_day_usd budget is
    fed from this number, so on such a deployment it never accrued and never denied.
    price() now retries the ex...

Read more