Skip to content

0.2.0 (Not ASF Release)

Pre-release
Pre-release

Choose a tag to compare

@wu-sheng wu-sheng released this 06 Sep 14:24
· 120 commits to main since this release

Collection

  • The default landing budget, max_delta_bytes, is 2 MiB rather than 8 MiB. A landed file
    travels whole as one log record, and 2 MiB keeps a record small next to what a receiver
    accepts while a session of the measured corpus still lands in a few hundred files. A single
    source record larger than the budget is landed whole, and the largest measured is 4.5 MB.
  • asz repack DEST re-cuts the landed files of a root into a new root under the configured
    budget, keeping every record's bytes and order, carrying the cursors over, and building the
    chains again on the new files. A landed file is never rewritten in place.

Export

  • asz push sends every landed file and every round to an OpenTelemetry logs receiver as OTLP
    logs, over gRPC by default or over HTTP, one log record per file with the file's bytes as the body, so a receiver stores the
    file as landed and checks its digest at once. Records name the sender with telemetry.sdk.name,
    the format and its version, the file, its kind, its digest and its line count, and the session
    and sequence a round's reference resolves against. Each file is sent once; push.state records
    which. A request carries up to batch_bytes, 8 MiB by default, under the 10 MiB the OAP accepts
    over HTTP, and a larger file goes alone.
    The service is export.otlp.service_name, or the runtime that produced each session, read off
    its landed header, Claude Code or Mock Agent, so a receiver lists conversations by the agent
    that produced them; the layer is AI_AGENT, spelled as the OAP spells a layer. The instance is
    who is pushing, export.otlp.instance_id, meant to be a mailbox, a name or a machine; empty means
    user@host of the machine running the push, stable across restarts, where it was a new UUID
    each start. A round's record also carries asz.conversation.title and the
    fold's counts, and every record is stamped with a time inside the session's range, so a receiver
    lists conversations and bounds its reads without decoding a body.
    The request is built from the OpenTelemetry protocol's own Go definitions and sent over gRPC
    by default, one connection per run and one call per batch, or over HTTP with a protobuf body;
    export.otlp.protocol chooses, and the OAP accepts both. Each
    record also carries asz.from_time and asz.through_time, the record time range of the file,
    so a receiver can place a file in time without decoding it, and a round's record carries
    asz.session.from_time and asz.session.through_time, the session's range as of that round.

  • export.otlp.max_bytes_per_minute caps what asz push puts on the wire, for the first push of
    a large history: a pass waits before a request until a minute's budget covers it. Zero, the
    default, is no limit. A pass now goes session by session, the session landed first going first,
    each session's files followed by its rounds, so a receiver holds complete sessions one after
    another during a long push. A receiver answering 429 or ResourceExhausted stops the pass,
    which leaves the rest for the next one and honors a Retry-After in watch mode. The pass line
    gained wire= and paused=.

Assembly

  • A round is cut at parse.max_round_bytes, 2 MiB by default, the same budget as a landed file,
    because a round travels whole as one log record. The parser narrows the round's input window
    until the round fits and leaves the rest of the evidence to the next round; asz parse and the
    refresh loop keep going until the chain reaches the index. Measured on the real corpus, the
    largest round was 17 MB and 8 of 589 were over 4 MiB before the budget.

  • A round's header carries from_time and through_time, the earliest and the latest record time
    among the landed files it consumed, and the session node carries the same pair for the whole
    conversation so far, which makes its from_time when the session began. The header repeats the
    session's pair as session_from_time and session_through_time, so a reader of the header alone
    has it, and its title and the fold's counts of talks, steps, streams, segments and open
    unresolved references, so a list of conversations needs no fold. All are evidence, so they
    reproduce with the round and sit inside its digest.

Scenarios

  • asz scenario build turns a short YAML scenario, written in the model's own words, into the
    input a session leaves behind: Claude Code's own files for the adapter to collect, or Session
    Data landed directly under a new mock/1 dialect. asz scenario check runs a scenario as a
    test against an expectation file, in both formats and at every checkpoint, and checks the
    properties every chain must have. The rounds are never mocked; the ordinary parser writes them.
    The project's own assembly tests are now scenarios under tests/scenarios/, and the Go
    transcript builder they used became the claude-code writer. Every scenario is also pushed to
    an OTLP receiver in the test and checked against the export page, one file per request, both
    formats and all six file kinds, then rebuilt from the wire and verified.

  • A scenario can say what the original lost. lost: true on a step leaves its records out of
    the file, on a result only the result, and on an agent, a skill or a workflow child the
    child's whole file, while the clock, the ids and the parent chain move as if the records were
    there. Both writers leave the same records out, so the landed data verifies and the loss shows
    as open references. tests/scenarios/lost-records.yaml covers each kind of loss, is pushed
    over both transports like every scenario, and is pushed into the real Collector in CI next to
    the scenario that holds every kind of file, so a session with open references is rebuilt and
    verified from what the Collector wrote.

  • An expectation file can say what a person deleted from the storage root. lose on a checkpoint
    names landed files by stream or run and kind, and the runner deletes them after that
    checkpoint's parse, so every later check runs over a root missing a file a round bound to. The
    structure survives in the rounds, the document reports incomplete and names the round and the
    sequence, and later rounds are whole. tests/scenarios/lost-file.yaml is the example. view
    gained problems and a checkpoint gained verify: {problems: N}, and the document's state must
    agree with asz verify in every scenario.

  • asz verify binds every round to the landed files it consumed, the way the page always did: a
    file a round names that is gone, or that no longer digests to what the round consumed, is
    reported by round and sequence, and the command exits non-zero. It was silent before when the
    lost file was the only one of its stream, since the stream checks see only what exists. The
    page and the command now share the one check.

Read

  • asz.view, version 1.0, is one conversation rebuilt from its rounds and its landed files as one
    document: every talk as a tree with the text, usage and flags its records carry, the streams, the
    segments, the relations, and the rounds and files it was built from, each verified, with a gap or
    a failed digest written into the document rather than returned as an error. Package
    pkg/sessionview defines and owns the shape and asz view serves it at /api/c/{id}/view;
    asz conversation -json or -yaml prints it. It is never a file. The format page says how each
    view of a conversation is drawn from the document, and carries a complete example generated from
    the fixture scenario, which a test keeps current. The document holds every run and step of the
    fold: what no talk contains sits under loose, and a property of every scenario holds the
    document to the whole session, every round and every landed file included, however many rounds
    the session was parsed in. A server holding the same files, such as the SkyWalking OAP, builds the same
    document. See the format page.

  • A chain with a missing or broken round is served as a document with the gap written into
    summary.state and summary.problems, the fold stopping before it, where it was an error in
    place of the document; the format page always required this.

  • A node's edges are ordered by relation id and then direction, so the same fold renders the same
    document every time, and a property of every scenario checks that it does.

  • An observed time renders to the millisecond by flooring, as time.Time does, so a time before
    1970 rounds the same everywhere; an elapsed time still divides toward zero.

  • A text preview keeps the longest prefix of whole characters within 2,000 bytes rather than
    cutting a character in two.

  • The conversation list's time span is the session node's, when it began and its last activity,
    the same pair the document and the wire carry; it was the span of the talks, which ended before
    a reset's boundary.

  • The page reads Session Data and Session Flow and nothing else. It took every record's time from
    the index; it now takes it from the record, so a root that arrives with only its landed files
    and its rounds renders in full, and the index is assembly's alone.

Formats

  • Session Data's reader and writer can carry a record as the bytes of its line, unchanged, which
    is what a repack and a receiver on a wire need so file digests still match.

Packaging

  • Every binary package and the container image carry the license of every dependency built into
    the binary, under licenses/, a LICENSE that lists each module under its license, and a NOTICE
    that carries the notice of every bundled module that ships one, gRPC-Go and the YAML parser
    today. They are generated into dist-material/ by license-eye and a small script over the
    build, the way the other SkyWalking repositories do it, and CI fails when the committed copy is
    not what the dependencies resolve to.

Where to get it