Skip to content

v0.18.0

Choose a tag to compare

@github-actions github-actions released this 28 Oct 01:32
· 24 commits to main since this release
947802b

Added

  • rote run shows a gate's message while the run waits (#304). Every
    workflow runtime now renders a hitl_gate's notify.message_template with
    the run's real values and reports it on the channel rote run already
    watches (a rote_gate_status event on DBOS, a query on Temporal, a
    rote-gate-park log line on Cloudflare and Inngest). rote run prints it
    on stderr. Display only: channel and target are still never sent to.
  • A node declares the environment variables its code reads (#302).
    env: [NAME, ...] on pure_function and external_call nodes. Verification
    finds literal os.environ / os.getenv reads and sends an undeclared one
    back for repair. rote skill install records each declared variable's
    value, and a run whose value differs is refused, so a compiled skill no
    longer silently drops a variable its module reads (expense-audit's report
    directory). Names rote reserves (ROTE_*, vendor keys, proxies, PATH,
    PYTHON* and the like) are refused in the IR.
  • Structure-pass constants are typed, with a unit (#303). A constant is a
    number, boolean or string checked against the skill's own words, and a
    number carries a unit in the new Node.constant_units (percent, count,
    days, currency:USD, ...). 75% is 75 with unit percent, never 0.75
    or the text '75%'. A number the skill writes in words is kept and listed
    for review.
  • A compile's repair can declare a pipeline input field (#297). A module
    that reads a caller-supplied field the skeleton never declared can now add
    it through system1/input_fields.yaml (or the parallel path's
    input_fields), checked against the skill's text and the sample input.
    Every applied or refused entry is an Open question in compile-report.md.

Changed

  • Agent-loop tools are pinned to the one grounded server that offers
    them (#296).
    The compile pins a loop tool to its server when exactly one
    listed server offers it, and leaves it as an Open question when two do.
    System-1 no longer picks the first of two servers. A loop tool no listed
    server offers is a review gap (loop_tool_unserved), not an error.

  • The static eval sizes a compiled judge's input along the IR's data flow
    (#300).
    A judge that receives a whole external result used to be priced
    as its prompt plus a few tokens per field, so compiled cost looked far
    too small. It now carries the same size the agent side uses, and each
    judge and loop states its input sizes under Assumptions in the scorecard.

  • A compile's constants keep the sign the skill writes. The structure
    pass compared a number's absolute value to its quote, so 5 passed for
    "below -5%" and a flipped rule shipped as decided. A number now matches its
    quote with its sign. A negative value for an unsigned number ("a drop of
    15%" as -15) is still accepted, since that is a real reading, but it is
    listed for review like a number read from words. A minus that runs into a
    word or digit ("5-10 days", "COVID-19") is not read as a sign.

  • A compiled skill's gate message reads as it does on the workflow
    runtimes.
    The HUMAN block filled a gate's placeholders with Python's
    str(), so a boolean read True, a whole float 2.0 and a missing owner
    an empty string, where rote run shows true, 2 and null, and a bidi
    override in a value reached the agent's terminal raw. The renderer is now
    one module (rote.adapters._gate_runtime_helper): the Python runtimes embed
    its source and a compiled skill ships it as scripts/_rote_gate.py when a
    gate has a message.

  • Behavior change: a node with no retry: is attempted once on every
    runtime.
    It ran once on dbos, python and temporal, but up to six times on
    cloudflare (step.do's default of 5 retries) and four on inngest (the
    SDK's function-level default of 3), so a paid judge or a call that is not
    idempotent did different things per runtime. Cloudflare now emits
    retries: { limit: 0 } and inngest retries: 0 when no node declares a
    retry. A declared retry: is unchanged. tests/test_retry_parity*.py
    counts the attempts on all six runtimes.

  • A failing generated test shows its local values to the repair. The
    test run passes --showlocals, so a failed assertion on an overall
    outcome now carries the finding that caused it (a $2,500 meals line that
    also trips the $75 meals cap). pytest shortens each value when not
    verbose, so the output budget holds.

  • System-1's test rules name the three mistakes behind most red tests.
    GENERATE.md now says to build each case from one clean fixture changing
    only the field a rule reads, to compute expected numbers in the test
    instead of by hand, and to pass inputs shaped like the sample (JSON
    numbers, never Decimal).

Fixed

  • Compile usage that was not measured reads as unknown (#299, #301).
    Missing token counts were reported as zeros, so an unmeasured compile looked
    free. Each stage is now measured, partial or unavailable, in the
    summary, --json, compile-metrics.json and the progress file. Codex usage
    comes from the last turn.completed, with cache reads and writes split out
    once. A deliverable that still fails verification now says verification FAILED in the header and prints no next: rote run line.

  • A compile checks the boundaries its generated tests cannot see (#291).
    A real compile passed 38 generated tests while every MCP call went out with
    no arguments, two gate consumers read keys their gates never declared, and
    a renderer required an input field the contract left out. Verification now
    reads the deliverable for each:

    • an MCP call whose node holds constants mcp.args never sends is an error
      when the tool's schema names its parameters, and an unresolved call
      (listed, blocking the run, never guessed) when no schema does;
    • code that reads a key a gate does not declare is an error;
    • code that reads a pipeline-input field the contract does not declare is
      an error.
      Gates that split one section's items between them are held to what they
      collect together, not each to the whole section.
  • A compile no longer ships a field read from an MCP result that has no
    such field.
    Verification checks every <node>.output.<field> read of an
    MCP-bound node against the result a recorded run returned, else the
    outputSchema the server declares. A result that is text or a list, or a
    closed object without the field, goes back to the agent as an error,
    because the run would fail at that read. With nothing recorded or
    declared, it is an Open question in the report.

  • rote run on a temporal app names the exception a failed step raised,
    not only Temporal's "Activity task failed" wrapper.