Skip to content

microagent v0.11.0

Choose a tag to compare

@github-actions github-actions released this 01 Oct 11:08
· 120 commits to main since this release

Added

  • Workflow checks require full commit pins for external actions and reusable workflows, while correctly ignoring references printed inside shell bodies.
  • Two more fuzz harnesses over untrusted input: the output of git blame, which
    a repository, its attributes file and the user's pager choose, and a
    repository's instructions file, which goes into the system role of every run
    made in that tree. Both assert on what survives the pass rather than on that
    it does not crash, so a name left in a blame line or a fence left able to
    close the block the builder wrote is a failed check on every zig build test.
  • --repl names its own commands on stderr before the first prompt: /help repeats them, and
    /exit ends the session beside /quit and EOF.

Changed

  • A session log record's cwd carries the part of the working directory under the
    home and a ~ in front of it, so the record no longer holds the account name the
    absolute path spelled out. A directory outside the home is recorded whole, and so
    is one under a run whose HOME is unset. A monitor still tells two runs apart by
    directory, and the store holds no more about the operator than it did.

Fixed

  • Instruction-count parsing uses a POSIX regular expression on both GNU and BSD sed.

  • Portable benchmark tests resolve true through PATH on macOS, and the source-reference fixture uses an explicit condition that passes ShellCheck on hosted runners.

  • Workflow shell checks decode YAML quotes, folded scalars and block indicators,
    keep run: text inside shell heredocs in the original step, and handle braces
    in quoted expressions. SBOM checks count direct pins from the manifests rather
    than depend on inline lock annotations.

  • Dependency lock checks compare literal version pins and reject malformed
    SHA-256 digests, including bad digests beside otherwise valid ones.

  • Benchmark rows escape run IDs and agent specifications as JSON. Missing Git
    statistics are reported as unavailable instead of zero changes. Simultaneous runs
    use separate work directories and retain their own logs. An instruction gate with
    a missing baseline or an unmeasured row fails instead of silently skipping it.

  • Benchmark interruptions give commands time to flush before process-group cleanup.
    Missing deadline support, failed overhead prompts, failed instruction samples, Harbor
    runs and summaries are reported as failures. Custom Harbor endpoints supply their
    actual egress host and a JSON-escaped provider configuration. SBOM hash failures or
    malformed digests stop generation and preserve the previous inventory.

  • HTTP MCP refusal bodies use the same JSON nesting guard as successful responses,
    and every failed call releases a stdio server marked dead. Combining-mark truncation
    walks the preceding character's own UTF-8 bytes, preserving multibyte text.

  • MCP discovery follows tool catalog pages with opaque cursor values, one
    deadline and a shared byte allowance. Failed catalogs cannot advertise partial
    tables, and duplicate detection no longer scans every earlier tool per entry.

  • Benchmark deadlines kill surviving process-group descendants before
    returning, including children that ignore termination after their parent exits.

  • MCP initialization checks the server's selected protocol revision and uses
    it in later HTTP headers, rejecting unsupported or malformed selections.

  • Completion requests append to the base URL's path while preserving its
    query and percent encoding, rather than appending inside a query or fragment.

  • URL credentials stay redacted in configuration errors, malformed endpoint
    values and allocation failures as well as request diagnostics.

  • Harbor validates endpoint hosts, ports and control characters, and refuses
    control characters in API keys before setup without quoting the key.

  • Very large accepted time budgets wait within the OS timestamp range instead
    of expiring immediately, while retaining the original deadline and clock.

  • Harbor checks numeric ceilings against the binary's integer ranges before
    setup and forwards accepted number spellings as decimal digits.

  • Failed POSIX subprocess launches close their pipes and reap their children,
    including MCP startup failures, invalid executables and oversized arguments
    or environments. The build patches its cached Zig library for this cleanup.

  • Arguments of rejected tool calls still spend the response byte allowance, so
    excessive indices cannot bypass the ceiling. Rejection diagnostics count
    streamed fragments without treating interleaved fragments as separate calls.

  • MCP replies are checked for excessive JSON nesting before parsing their trees,
    so deeply nested schemas, structured results and errors cannot crash serialization.

  • Non-object MCP error replies retain only a capped diagnostic instead of the
    complete serialized reply in the run allocator.

  • Every source citation in the threat model names the line its function is defined on
    again, so make lint, and the push workflow's lint job that runs it, is green on a
    tree the gates otherwise pass. Forty of the drifted citations were moved to the line
    the source has them on, and five that cited a line inside a function's body now name
    the function beside them, which is what lets the check verify the pair rather than a
    bare line that goes stale on the next insertion above it.

  • Built-in tool subprocesses reject NUL bytes before the OS can execute truncated arguments.

  • Responses past the byte ceiling stop reading, discard pending tool calls and exit incomplete,
    even when the provider keeps the stream open. An answer exactly at the ceiling remains valid.

  • The memory benchmark rejects failed commands and unreadable measurements, checks ptrace
    errors and resumes and reaps traced children when measurement fails. A command's own
    SIGTRAP is delivered, while later exec stops are handled as tracer events.

  • Session home-path redaction checks the full prefix before slicing, avoiding crashes
    in shorter working directories and incorrect redaction of unrelated paths.

  • MCP stdio deadlines include blocked request writes. Oversized complete lines and
    notification floods are refused under the response allowance.

  • Lazy MCP initialization and the tool request share one deadline; dead servers are not
    initialized again. Structured results retain error flags and allocate only their capped prefix.

  • Conversation compaction reuses the existing message buffer instead of reserving space
    for both the old conversation and its replacement.

  • JSON buffers keep one owner throughout writes, so a failed allocation releases the
    current buffer instead of leaking it or freeing an earlier allocation twice.

  • Provider stream errors are parsed as JSON, including whitespace and escaped field names;
    a null error field does not turn a successful response into a failure.

  • An MCP server that answers a request with 202 Accepted is no longer reported as a
    failure. Only the 4xx and 5xx classes are refusals; a 202 to a request is the
    streamable-HTTP transport accepting it and answering out of band, and the frame in the
    body is the answer, so the call now succeeds the way a 200 does.

  • An MCP refusal that carries a JSON-RPC error object now reports the server's own reason
    instead of a bare status. A 400 with {"error":{"code":-32602,"message":"bad args"}}
    said HTTP 400 and threw the reason away; it now reads bad args (code -32602) (HTTP 400),
    the same sentence a 200 carrying an error frame already produced. A refusal with an HTML
    page or no body still falls back to the status alone.

  • microagent update tells a reader to set GITHUB_TOKEN on a 403 only when the body
    is actually the API's rate limit. A 403 is also a token without the scope, or a
    repository nobody may read, and sending someone after a token that changes nothing was
    the wrong answer to those. A 429 still needs no body to be told apart.

  • make check-refs reads a citation pair that the Markdown wrapped across a line break.
    The pattern asked for the name and the path adjacent, so a pair broken between them was
    never read, never checked and never repaired: a citation the gate cannot see is one it
    agrees with whatever it happens to say. Ten of the threat model's citations were in that
    shape and every one had drifted onto unrelated code, by as much as a thousand lines.
    Ten are now on the line their symbol is defined on, one naming a function that no longer
    exists, which is the control's own key resolution and now reads as it.

  • make check-refs no longer prints a fixed citation as the summary of what it found. It
    named toolCallLine at a line that was not wrong whatever the run had found, so a reader
    of a red gate was walked to a citation that was fine and the gate read as disagreeing
    with itself. The list above is the report.

  • make check-refs FIX=1 repairs a wrapped pair. The rewrite matched the name beside its
    path and sed matches inside one line, so a citation broken across a break was reported
    as moved and never was: the gate stayed red with the fix flag on and nothing explained
    why. The path span is unique in a document and is now what the rewrite matches, which
    repairs the wrapped shape as well as one written on a single line.

  • A turn whose request body was completely on the wire is not sent a second time when the
    flush of it stalls past the stall timeout. The timeout was reported as a failure to send,
    which the retry schedule answered by re-POSTing a request the provider may already have
    generated and billed; a stall after the last byte is now classified as a lost head, which
    ends the run with the same note rather than buying a second billable completion for one turn.

  • MCP tool names are checked against the provider's 64-character limit including their
    server prefix and its allowed letters, digits, dashes and underscores; unusable names
    are reported and omitted from remote and preset schemas.

  • A clock set before 1970 no longer reads as a negative number of seconds where a
    Retry-After date is subtracted from it. A container with no RTC, a host restored
    from a snapshot and a machine with a flat RTC battery all boot into one, and the
    negative reading made every wait longer than it is: a deadline that had already
    passed was read as still in the future, so the run sat out the 120-second cap
    waiting on a rate limit it was not under. Both ends of the range saturate rather
    than trapping a checked build, which is what a clock set far enough ahead did to
    the first request of a run.

  • An HTTP date outside the years a four-digit IMF-fixdate field can spell is refused
    with error.OutOfRange rather than walked to or narrowed. Past 9999 the year was
    reached one year at a time from 1970, so a value at the top of an i64 was a walk
    of billions of iterations; before 1970 the standard library's calendar counts days
    from the epoch and has no day before it to name, so a release build wrapped into a
    date at the far end of the calendar and a checked build trapped. A session record's
    own stamp saturates at the same two ends, so a clock set far ahead writes the
    largest stamp a monitor can still order rather than none at all.

  • A child process group that two tool calls claim at the same moment is no longer
    lost. The writers are every bash command and every MCP server, on whichever
    worker the io hands them, and the table's claim was a load followed by a store: two
    of them could read the same free slot and the second store overwrote the first, so
    one group sat outside the table and was exactly the child Ctrl+C left running.
    Claiming a slot is a compare-and-swap now, and retiring one swaps against the pid
    it is given, so a caller can never clear a slot another child has since taken.

  • The Harbor adapter forwards MICROAGENT_MAX_SPEND_TOKENS to the container. The
    binary read the billed-token ceiling from the environment all along, the adapter
    checked the variable and never passed it, so a benchmark operator setting it was
    working from the source and the one ceiling here counted in what the provider bills
    was the one that did not reach the run. A mistyped value is now refused at the
    command line, beside the other ceilings, rather than after a container start.

  • microagent update --help names the spelling that reaches it, microagent help update, the way the main --help already did. The two are the same text asked
    two ways and only one of them said so.