)]}'
{
  "log": [
    {
      "commit": "b62d9716bd16b2c3678b5f4bf8bf516490f1d509",
      "tree": "acb0a1de4bff05a888d1921fb3210b44cb2af6be",
      "parents": [
        "770be3b102be2b6dc231fee662b4a41167a2bdb1"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 22:52:45 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 22:52:45 2026 +0800"
      },
      "message": "The instance is who is pushing: a mailbox, a name or a machine, and user@host by default\n\nservice.instance.id defaulted to a new UUID each time asz push started,\nwhich said nothing about the sender and made every run a new instance on\nthe receiver. The instance is now documented as who is pushing, in words\nthe people reading the receiver recognise, a mailbox, a name or a\nmachine, and the default is user@host of the machine running the push,\nwhich is stable across restarts and already says where the records come\nfrom. A machine that can name neither still gets a UUID.\n"
    },
    {
      "commit": "770be3b102be2b6dc231fee662b4a41167a2bdb1",
      "tree": "1ac2f46799cf455f08ee075f69ed6197abce2835",
      "parents": [
        "8ccb5c52a70283ba5df0ecdd38e1903e9ea5a21a"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 22:28:32 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 22:28:32 2026 +0800"
      },
      "message": "Six findings from the receiving side\n\nThe service a session is pushed under is now the runtime that produced\nit, read off its landed header\u0027s adapter, Claude Code or Mock Agent,\nrather than the adapter the configuration names; an sd build pushed from\nits own configuration said Claude Code, and the guide said Mock Agent. A\nroot that holds both kinds is pushed as both. Every scenario\u0027s push check\nnow also runs once without a configured service and expects the runtime.\n\nA build refused a DIR/asz.yaml a person had appended the export block\nto, so the guide\u0027s own recipe could not be followed across stages; a file\nthat starts with what the build writes is the build\u0027s.\n\nThe conversation list\u0027s time span was the talks\u0027 span while the document\nand the wire carry the session node\u0027s; they differed by the gap between\na reset\u0027s summary and its boundary. The list reads the session node.\n\n--repeat started at the second id and never emitted the scenario\u0027s own;\nthe first session is the scenario\u0027s now.\n\nThe three-rounds scenario has a child agent in its third stage, so every\nstage lands files of more than one kind.\n\nA round\u0027s lines in the document is the file\u0027s line count, as it is for\nevery other file, rather than a count of frames.\n"
    },
    {
      "commit": "8ccb5c52a70283ba5df0ecdd38e1903e9ea5a21a",
      "tree": "88a97e37e3a9339c35ec634d6a5ecb6fdbe4f22f",
      "parents": [
        "a67b6408f51b69ed17a3a93f8dc87c002fe469f9"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 21:33:12 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 21:33:12 2026 +0800"
      },
      "message": "Hold the document to the whole session across rounds, and check it in three stages\n\nA scenario with two checkpoints already landed and parsed in three\nstages and wrote three rounds over landed files cut at each stage. Now a\nscenario says so, three-rounds, with expectations at every stage, and a\nproperty of every scenario, view_covers_the_session, holds the final\nasz.view document to the whole session: every round, verified; every\nlanded file with its digest as on disk; every talk, run and step of the\nfold in a tree; the session\u0027s own range; and a verified state.\n\nFor that to hold in general the document gained loose: the runs and\nsteps no talk contains, as trees from their highest such ancestor, such\nas a child\u0027s output the fold parents to the session when the child\u0027s\nstream opened no talk. It is empty for every scenario and for most\nconversations, and it exists so the document holds every step the fold\nholds. The example on the format page is regenerated.\n"
    },
    {
      "commit": "a67b6408f51b69ed17a3a93f8dc87c002fe469f9",
      "tree": "1357e2e4ef56d8f562ea58a04d8e39cdfea36a8f",
      "parents": [
        "3c6ae037ee20486d35f96401bb7a01790df52ca7"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 21:15:38 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 21:15:38 2026 +0800"
      },
      "message": "Define what asz conversation -json and -yaml print, with a complete example\n\nThe asz.view page read as a schema. It now says what produces the\ndocument, the two flags and the page\u0027s own response, how each view of a\nconversation is drawn from it, the transcript, the flow timeline,\ncross-stream flow, the evidence and the verification, and how the YAML\nrendering relates to the JSON. A complete example, the whole document of\nthe fixture session as the command prints it, sits beside the page,\ngenerated from the fixture scenario by make asz-view-example, and a test\nfails when the committed example no longer matches what the code\nproduces.\n"
    },
    {
      "commit": "3c6ae037ee20486d35f96401bb7a01790df52ca7",
      "tree": "5a0ffd623457b3aed731a7d85a7ad39a19a7a5d3",
      "parents": [
        "4b6bd17f145064a39ec573407b115866fe8de350"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 21:11:52 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 21:11:52 2026 +0800"
      },
      "message": "Print the asz.view document with asz conversation -json or -yaml\n\nThe document was reachable only over HTTP from a running asz view. asz\nconversation now prints it to standard output with -json, and with -yaml\nas a rendering of the same JSON with the same keys in the same order,\nfor a pipeline or a diff. The YAML is produced from the JSON, never from\nthe types, so a reader of either sees one document. The page stays the\npage.\n"
    },
    {
      "commit": "4b6bd17f145064a39ec573407b115866fe8de350",
      "tree": "3ffd7ef017e4fb48c1afabe766c8460667fa2858",
      "parents": [
        "7c96649a6596d5163b5e3ac8e572658508612cd9"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:50:48 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:50:48 2026 +0800"
      },
      "message": "Check the OTLP push in every scenario, and against a real Collector in CI\n\nEvery scenario, in both formats, is now pushed to a receiver inside the\ncheck, one file per request, and every request is compared with the\nexport page: the resource and the scope, one record per file with the\nfile\u0027s bytes and digest, the attributes a landed file carries and the ones\nonly a round carries, the record time range, the list attributes, and the\nstamp a receiver bounds a read on. A refused request must leave every file\nfor the next pass, a second pass must send nothing, and writing every body\nback to its path must give a root that verifies and folds the same. The\npackage gained a decoder for its own wire so the receiver can read it, and\na scenario with every kind of file names all six kinds the push must\ncarry.\n\nThe in-process receiver proves the wire matches this project\u0027s reading of\nit. A real OpenTelemetry Collector proves an OTLP receiver that is not ours\naccepts it: a CI job pushes a generated session into a Collector container,\nreads what its file exporter wrote, checks every record against the root,\nand rebuilds the root from the records. make e2e-collector runs the same\nlocally.\n"
    },
    {
      "commit": "7c96649a6596d5163b5e3ac8e572658508612cd9",
      "tree": "ed1f931b626d4300388c0ed532bf9988b1f80184",
      "parents": [
        "72de4f513774e035f1fad68ded23b0d6f0ed9a45"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:42:34 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:42:34 2026 +0800"
      },
      "message": "Keep a repeated session\u0027s id shape, and document generate, load, parse and export\n\nA repeated build of a scenario with a named session appended a counter to\nthe id, which is no longer the UUID shape session discovery requires, so\nthe collector found nothing. The last group of the id is counted up\ninstead, and any other name keeps its suffix. Walked through: three\nsessions generated, collected, parsed, verified and pushed as twelve\nrecords.\n\nThe generated configuration now carries the export block, commented, with\nthe one key a push needs, and the scenario guide spells out the whole\npath from generation to export, including a repeated build for a demo\ncorpus.\n"
    },
    {
      "commit": "72de4f513774e035f1fad68ded23b0d6f0ed9a45",
      "tree": "2d89e7ecca20b14facb67a45ce14b43c503367c5",
      "parents": [
        "402286ab9d319868e2d04b96b289c31162cd18db"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:29:57 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:29:57 2026 +0800"
      },
      "message": "Make the adapter\u0027s conversion a property of every scenario, and retire the raw corpus\n\nThe hand-made Claude Code corpus and the tests over it checked what the\nadapter lands: that every source line becomes one record, that discovery\npasses over noise and joins a session across directories, that values\nsurvive conversion, that a repack keeps records and structure. Each is now\na property every scenario checks. The strongest is records_match: the\nrecords the real adapter lands from a scenario\u0027s Claude Code files must\nequal, field by field, the records the sd writer lands from the same\nscenario. It found three places where the sd writer had guessed the\nconversion wrong, an attachment\u0027s producer and part shape and a workflow\nlaunch\u0027s label, and each was corrected against the adapter.\n\nThe claude-code writer now plants the noise a real project directory\nholds, a file that is not a session and a directory that is not one, and\na workflow\u0027s script can be filed under another project directory, as a\nreal corpus does; an uppercase session id is a scenario of its own. The\ntests a scenario cannot express, crashes, lost state, races, the round\nbudget and a refused repack, moved to tests/chain. CI runs the scenarios\nin go test and once more through the built command.\n"
    },
    {
      "commit": "402286ab9d319868e2d04b96b289c31162cd18db",
      "tree": "d83db641a8433a06df28dddcc4bb801c38cb51d8",
      "parents": [
        "af6be7b0b50ea4e3a97cae136b9b972cbb1472bf"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:18:38 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:18:38 2026 +0800"
      },
      "message": "Give the scenario files their license headers, and keep the source directory out of the session listing\n\nThe scenario and expectation files under tests/scenarios went in without\nthe Apache header, which the license check refuses. The check ran before\nthe commit but its status was lost in a pipe, so the commit went out\nanyway; this one carries the headers.\n\nA build wrote the runtime\u0027s files under DIR/source, and the storage root\u0027s\nsession listing takes any directory not starting with an underscore as a\nsession, so asz parse tried to parse the source and failed. The directory\nis DIR/_source now, passed over like _conversations, and a repeated build\ncollects, parses and verifies through the ordinary commands.\n"
    },
    {
      "commit": "af6be7b0b50ea4e3a97cae136b9b972cbb1472bf",
      "tree": "c0391cf71087b2ec96d919f0fd331f1ccca8aa48",
      "parents": [
        "28a0937af1b35ca2c17ef5c8b05377dcfd64bc13"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:16:23 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 20:16:23 2026 +0800"
      },
      "message": "Add scenarios: build a session from YAML, and run the assembly tests as scenarios\n\nA scenario is a short YAML description of a conversation in the model\u0027s own\nwords. asz scenario build turns it into the input a session leaves behind,\neither Claude Code\u0027s own files for the adapter to collect, or Session Data\nlanded directly under a new mock dialect, and writes a configuration so the\nordinary commands collect and parse it. The rounds are never mocked. asz\nscenario check runs a scenario as a test: at every checkpoint it builds,\ncollects, parses and compares the fold with an expectation file, then runs\nthe properties every chain must have, and compares the formats\u0027 folds with\neach other, which makes one scenario a conformance test for an adapter.\n\nThe Go transcript builder the end-to-end tests used became the claude-code\nwriter, and the assembly tests it drove became fourteen scenarios under\ntests/scenarios, one property each. Go tests remain for what a scenario\ncannot express: a crash between landing and committing, a lost or stale\nstate file, concurrent parses, a shared collector, and the round budget,\nall of them now sourced from a scenario. The boundary test gained a third\nside, wiring, for the scenario runner, which only the command and the\ntests may import.\n"
    },
    {
      "commit": "28a0937af1b35ca2c17ef5c8b05377dcfd64bc13",
      "tree": "0ea2efb1823d19d4302bb96c9cb192472b3c7c64",
      "parents": [
        "33616b5e5abf17d7946462135f6192461a5feb13"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 17:22:17 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 17:22:17 2026 +0800"
      },
      "message": "Define asz.view 1.0, and carry on every round what a list of conversations shows\n\nThe document a viewer needs is now a format of its own, asz.view, version\n1.0, defined and owned in pkg/sessionview: format and version first, the\nconversation and its sessions, the head, a summary with a verification\nstate and the problems found, every round and every file with its digest\nand its time range, the streams, the segments, every talk as a tree with\nthe text, usage, flags and dropped list its records carry, and the\nrelations. It is never a file. asz view builds it in memory once per fold\nand serves it at /api/c/{id}/view, and a server that holds the same files\nbuilds the same document. Verification is content: a gap in the chain or\na failed digest is written into the summary, never returned as an error.\n\nA round\u0027s header now also carries the session\u0027s title and the fold\u0027s\ncounts of talks, steps, streams, segments and open references, and a\nround\u0027s OTLP record copies them as asz.conversation.*, so a receiver\nlists conversations off its newest round per conversation without\nfolding. Steps are counted as the document and the list page count them,\nevery node that is not structure, so the three agree.\n\nThe sender\u0027s defaults follow the receiver: the layer is AI_AGENT, spelled\nas the OAP spells a layer; a request carries 8 MiB, under the 10 MiB the\nOAP accepts over HTTP; and every record is stamped with a time inside the\nsession\u0027s range, a landed file with its last record time or the session\u0027s\nlatest, a round with the session\u0027s last activity, so a receiver can bound\na read by the range the head round carries.\n\nMeasured on the largest real conversation: the document is 19.8 MB, built\nin 0.6 s; the push is 7 requests; every file rebuilt with its digest, and\nevery record stamped inside the session\u0027s range.\n"
    },
    {
      "commit": "33616b5e5abf17d7946462135f6192461a5feb13",
      "tree": "7ac8b0eac7334b4319ada48f99129b92618e4de1",
      "parents": [
        "b71e7d95518d8d3c390837d8448a3895513b0445"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 17:07:14 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 17:07:14 2026 +0800"
      },
      "message": "Define the Conversation View and serve it as one document\n\nA reader of a conversation wants one thing: every talk as a tree with the\ntext its records carry, plus the streams, the segments, the relations,\nand what it was all built from. The page assembled that across many\nrequests, and a server holding the same files, such as the SkyWalking\nOAP, would have had to invent its own shape for the same answer.\n\nThe Conversation View, cv/1, is that shape, defined once in\npkg/sessionview and documented with the other two formats. It is never\na file: asz view builds it in memory once per fold and serves it at\n/api/c/{id}/view, and another server builds the same document from the\nsame files. The page\u0027s own tree, stream and segment types are now the\nview\u0027s, so there is one definition. Measured on the largest real\nconversation: 19.0 MB, built in 0.7 s, 11 MB of it the text and results\non the trees.\n\nThe Session Data page now describes each file kind, what its records\ncarry and what refers to it, and the Session Flow page says a round is\nthe one kind of .sf file.\n"
    },
    {
      "commit": "b71e7d95518d8d3c390837d8448a3895513b0445",
      "tree": "ba3ef36f3efe0e0be699ea99d32f0b8e86b11529",
      "parents": [
        "dbba7de616a22fc0b5fe134c818f279519d235b5"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 14:32:07 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 14:32:07 2026 +0800"
      },
      "message": "Repeat the session\u0027s time range on the round header, and name the service after the runtime\n\nA round\u0027s header carried the range of the files it consumed, and the\nsession\u0027s own range sat only on the session node inside the body, so a\nreceiver looking at a record\u0027s attributes could place a file in time but\nnot the session. The header now repeats the session node\u0027s pair as\nsession_from_time and session_through_time, and a round\u0027s OTLP record\ncarries them as asz.session.from_time and asz.session.through_time. A\nlanded file never carries them: it can travel before any round exists,\nand the last activity keeps moving, so the value there would be missing\nor stale.\n\nThe service every record is attributed to is now the configured name or\nthe runtime the adapter reads, Claude Code, rather than the project\ndirectory of each session. A receiver lists conversations by the kind of\nagent that produced them, and the project is still in every main\ntranscript\u0027s header. The pusher refuses to run without a service name.\n"
    },
    {
      "commit": "dbba7de616a22fc0b5fe134c818f279519d235b5",
      "tree": "38fe08bb79e21f217c36c53c7772146b86995ba4",
      "parents": [
        "e8ffe8caa40526c14761711e38eef2e820d986bf"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 13:59:36 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 13:59:36 2026 +0800"
      },
      "message": "Carry the record time range on rounds, the session node and the wire\n\nA round carried no time at all, and a reader that wanted to know when a\nsession began or was last active had to open its landed files. Record\ntimes are evidence the runtime wrote, not the parser\u0027s clock, so they can\nsit inside a round\u0027s digest and reproduce with it.\n\nThe session node now carries from_time and through_time, the earliest and\nthe latest record time of the whole conversation so far, computed by the\nassembler from the index. Each round\u0027s header carries the same pair for\nthe files that round consumed. On the wire every record carries\nasz.from_time and asz.through_time, the range of its file, so a receiver\ncan place a file in time without decoding it; a file whose records carry\nno time, such as a child\u0027s meta file, carries neither.\n\nMeasured on the real conversation: 145 of 315 records carry a range, the\nattributes are 0.24% of the body, and every file still rebuilds with a\nmatching digest. A test parses two rounds and checks that the session\nbegin never moves later and the end covers both windows.\n"
    },
    {
      "commit": "e8ffe8caa40526c14761711e38eef2e820d986bf",
      "tree": "81fd3bc04e0b72500b8ad9138369c2ee18f00b41",
      "parents": [
        "46af5cb83e856fd7a500cedc38b8eaee831e9f67"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 13:08:34 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 13:08:34 2026 +0800"
      },
      "message": "Send one log record per file, and cut rounds at the same budget\n\nThe first exporter sent one log record per line. Measured on one real\nconversation of 306 files that was 39,683 records, attributes 16% on top\nof the body even after trimming, and a receiver that had to track which\nlines had arrived before it could verify a file. A landed file is cut at a\nbudget, so a whole file is a small record: the same conversation is now\n315 records in 3 requests, attributes 0.22% of the body, and every file\nrebuilt from what an OpenTelemetry Collector received matched its digest\nand its line count. A receiver stores a file as landed and checks the\ndigest at once.\n\nThe budgets now follow from that. A landed file is cut at 2 MiB rather\nthan 4 MiB, a request carries 20 MiB of files rather than 1 MiB of lines,\nand a round is cut at 2 MiB too, by narrowing its input window until the\nround fits. Rounds had no budget before and the largest in the real corpus\nwas 17 MB. asz parse and the refresh loop keep parsing until the chain\nreaches the index. A test parses one session whole and under a one-byte\nbudget and checks that the two folds hold the same entities.\n"
    },
    {
      "commit": "46af5cb83e856fd7a500cedc38b8eaee831e9f67",
      "tree": "a2eb7169ce7c88ff50f184017ac3f37bf38f76cd",
      "parents": [
        "d5e2402df45bacda79dc319b1f2266b7aff962b0"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 12:20:45 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 12:20:45 2026 +0800"
      },
      "message": "Keep per-file OTLP attributes on the header line only\n\nEvery line still carries what resolves a round\u0027s reference: the session,\nthe sequence and the line for Session Data, the conversation and the\nround for Session Flow. The format version, the file kind, the stream or\nrun and the digest are constant for a file, so they now ride on the\nheader line only, with the digest repeated on the closing line so a\nreceiver can verify from either end.\n\nMeasured on one real conversation of 306 files and 39,683 records:\nattributes fell from 356 to 204 bytes per record, from 28% to 16% of the\nbody. Every file still rebuilt from the received records with a matching\ndigest.\n"
    },
    {
      "commit": "d5e2402df45bacda79dc319b1f2266b7aff962b0",
      "tree": "7b47e0fe1f2740ba1614674d4414c4c918a136ea",
      "parents": [
        "981ebc1354a42caece0b83891d51bd0876583274"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 11:34:09 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 11:34:09 2026 +0800"
      },
      "message": "Make the sender\u0027s instance id configurable and default the layer to AI-AGENT\n\nservice.instance.id identifies the process that sends, not the session:\nit is export.otlp.instance_id, or a new UUID each time asz push starts.\nThe session a record belongs to stays on the record as asz.session.\nThe layer defaults to AI-AGENT, and service.name stays configurable\nwith the session\u0027s project directory as its fallback. asz push prints\nthe service, the instance and the layer it will send.\n"
    },
    {
      "commit": "981ebc1354a42caece0b83891d51bd0876583274",
      "tree": "8f168607a1240fe6a7ce855fb7a27e63825b02d9",
      "parents": [
        "9c320336bd114256974fcbfbbe325764dec9b4bb"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 11:05:07 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 11:05:07 2026 +0800"
      },
      "message": "Send landed files and rounds to an OpenTelemetry logs receiver\n\nasz push sends every landed file and every round to an OTLP/HTTP logs\nendpoint, one log record per line with the line\u0027s bytes unchanged, so a\nreceiver can write the files back byte for byte and every digest and\nevery {seq, row} reference still holds. Measured against an\nOpenTelemetry Collector: 306 files of one session, 39,683 records in 49\nrequests in 1.3 s, and all 306 files rebuilt from the received bodies\nmatched their digests on disk.\n\nThe resource names the sender with telemetry.sdk.name \"asz\" and its\nversion, the service as the project directory the session\u0027s main\ntranscript was recorded under, the session as the instance, and the\nlayer the OAP should place it in. Each record carries the format and\nits version from the file\u0027s first line, the file\u0027s kind and digest, the\nline\u0027s index and kind, and the session, stream, run, sequence,\nconversation or round it belongs to. A landed record is stamped with its\nown time; a round, which carries none by design, with the time it was\nsent.\n\nFiles are write-once, so each is sent once; push.state records which,\nand a file is recorded only after the request carrying its last line\nsucceeded. The protobuf encoding is written here, so the module keeps\nits one dependency. The exporter sits on the collector side of the\nboundary test.\n"
    },
    {
      "commit": "9c320336bd114256974fcbfbbe325764dec9b4bb",
      "tree": "19f1a34393fde71ed46a4450f80b9321c0b4982e",
      "parents": [
        "7b07ba1df745d828ef7986aecd1c8edad60b1e73"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 10:44:18 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 10:44:18 2026 +0800"
      },
      "message": "Let the page read Session Data and Session Flow only\n\nThe page took every record\u0027s time from the index, which is derived and\ndisposable, so a root that arrived with only its landed files and its\nrounds rendered without any times. It now takes the time from the\nrecord itself. Measured on a root holding only one session\u0027s .sd and\n.sf files, every one of 16,121 flow items carries a time, and the\nlargest conversation, 49,817 items, loads in the same time as before.\nThe boundary test now fails if the page imports the index.\n"
    },
    {
      "commit": "7b07ba1df745d828ef7986aecd1c8edad60b1e73",
      "tree": "29924e483fa4469da79a31f974c4f4d44d440b5b",
      "parents": [
        "4dbf7be1015a61f343a963f5bcb377d06c0c5bf2"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 10:44:18 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 10:44:18 2026 +0800"
      },
      "message": "Repack landed files into a new root, and land 4 MiB files by default\n\nA landed file is cut once: a round addresses records by file and line\nand binds itself to file digests, so re-cutting a referenced file would\nbreak every reference. A change of budget therefore applies to new\nfiles only, and asz repack brings an existing root under a new budget by\nre-cutting every file into a new root, keeping each record\u0027s bytes and\norder, carrying the cursors over, and building the chains again there.\nOn a real session of 305 files it took 8 s and the chain built on the\nnew files describes the same conversation.\n\nThe default budget moves from 8 MiB to 4 MiB so a landed file fits in\none message under the default limit of an OpenTelemetry Collector.\nMeasured on 6,970 files, 38 exceeded 4 MiB under the old default; a\nsingle record larger than the budget is still landed whole.\n"
    },
    {
      "commit": "4dbf7be1015a61f343a963f5bcb377d06c0c5bf2",
      "tree": "2db766db823ce113bd1a7df46933520b49b48461",
      "parents": [
        "9a7c715e4a0c9a62add5af3beef1014591f40afa"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 10:44:18 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 10:44:18 2026 +0800"
      },
      "message": "Carry a record\u0027s line unchanged and find its time without decoding it\n\nSession Data\u0027s reader and writer can pass a record through as the bytes\nof its line. A repack and a receiver on a wire need that: a record\nre-encoded from its decoded form could differ in bytes and break the\nfile digests that rounds bind to. The closing line is verified the same\nway on the raw path.\n\nLineTime finds a record\u0027s time from its line without decoding it. The\nrecord\u0027s own fields are encoded before its parts, so the first time\nfield before the parts is the record\u0027s own and never one nested in a\npart. A page turning tens of thousands of node references into moments\nmust not pay for a full decode of every record.\n"
    },
    {
      "commit": "9a7c715e4a0c9a62add5af3beef1014591f40afa",
      "tree": "13f33904f0dee878aa7e483977cf048c74497d70",
      "parents": [
        "f538b504f35df09ddeee147213bcdd74a9cc4479"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 09:05:18 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Sep 04 09:05:18 2026 +0800"
      },
      "message": "Release 0.1.0 and open 0.2.0 (#2)"
    },
    {
      "commit": "f538b504f35df09ddeee147213bcdd74a9cc4479",
      "tree": "3c1e16b664ced0a81fe714d47ac179965a23fbea",
      "parents": [
        "e9ae54f352cda75271ccd0526d8a583f4e7aa649"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 07:39:20 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Fri Sep 04 07:39:20 2026 +0800"
      },
      "message": "Run the license checks with the module\u0027s Go toolchain\n\nThe skywalking-eyes dependency action brings its own Go, 1.25 with the\ntoolchain pinned local, and go.mod now requires 1.27, so its go command\nrefused and the check failed. Both checks now run through the Makefile\nunder the toolchain the module declares, as make check does locally,\nwhere they pass.\n"
    },
    {
      "commit": "e9ae54f352cda75271ccd0526d8a583f4e7aa649",
      "tree": "c077940c70dc5908c53c0b6c43a0fc496e26628e",
      "parents": [
        "8d8d74da478d6c19d2365837a879d9f13872f988"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:44:53 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:44:53 2026 +0800"
      },
      "message": "Move to Go 1.27 and golangci-lint v2\n\nGo 1.27.1 is the current stable release and 1.26 the previous line, so\nthe module, the CI matrix, the image base and the docs move from 1.25\nto 1.27. The build, the five cross-compiles, the tests and the image on\ngolang:1.27 were verified locally under the 1.27 toolchain.\n\ngolangci-lint v1.64.8 cannot read Go 1.27 export data, so the linter\nmoves to v2.13.2, installed from its v2 module path. Its own migrate\ncommand converted the configuration: the standard linters are on by\ndefault in v2, gofmt and goimports are formatters, and the v1 default\nexclusions are kept as presets so nothing that passed before fails now.\nThe newer staticcheck asked for one tagged switch in discovery.\n"
    },
    {
      "commit": "8d8d74da478d6c19d2365837a879d9f13872f988",
      "tree": "5b21e280451ec217fa0fe0e6530711fa14759a0f",
      "parents": [
        "c1fdeede939a2a235cadf7b5f0732a1aa9738fb9"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:34:15 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:34:15 2026 +0800"
      },
      "message": "Prepare a release on a branch, complete it on GitHub, and attach the packages\n\ntools/release.sh prepare asks for the version and the next one, cuts\nrelease/VERSION from the current commit, finalises the changelog page,\nlists the version, writes its release notes into the repository, commits\nand tags on that commit, opens the next version in a second commit,\npushes the branch and the tag, and raises the pull request. main is\nnever pushed to directly, and the tag carries the notes and the finished\nchangelog but nothing about the next version.\n\ntools/release.sh complete creates the GitHub release from the notes\nstored in the tag and stops there. CI publishes the image on the\nreleased event and now attaches the binary packages and their checksums\nto the release, which is where people download them while the project\ndoes not distribute through dist.apache.org. The Apache steps stay in\nthe guide as a later section, not part of either command.\n"
    },
    {
      "commit": "c1fdeede939a2a235cadf7b5f0732a1aa9738fb9",
      "tree": "4a0a5b98b3d6a5ca844640f41dba30d84e44588e",
      "parents": [
        "93fe38beac8ead82259153fd0cf995d8904a84eb"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:16:03 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:16:03 2026 +0800"
      },
      "message": "Give the GitHub release step its commands\n\nThe guide described creating the release in words. It now shows the\nterminal commands: the release notes into a file, gh release create\nwith the tag verified, how to find the run that publishes the image,\nand how to check the image once it is green.\n"
    },
    {
      "commit": "93fe38beac8ead82259153fd0cf995d8904a84eb",
      "tree": "71e7e0ee1c964b5af8bb85b6ecb3cc6711f70070",
      "parents": [
        "fe69dd6f09adf57ce1457ff9baa1b238d924c706"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:14:41 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:14:41 2026 +0800"
      },
      "message": "Split the release script into release and next, and drop the rolling page\n\nA tag must carry the finished changelog of its version and nothing about\nthe next one, and opening the next version is its own change after the\ntag, raised as a pull request. A rolling page for the next version\ncannot give that: the tag would carry a page for a version with nothing\nin it, and finalising needs the rename that is easiest to get wrong. So\nthe version in development has its own page from the start and Current\nVersion in the menu points at it.\n\ntools/release.sh release VERSION finalises the page, lists the version\nunder Changelog and in CHANGES.md, commits, and with --tag puts the tag\non that commit. tools/release.sh next VERSION opens the next version on\na branch named for it, with --pr pushing it and opening the pull\nrequest. Both refuse a dirty tree, and release refuses an existing tag.\n"
    },
    {
      "commit": "fe69dd6f09adf57ce1457ff9baa1b238d924c706",
      "tree": "34972b736d0d0fd7cbeb113c0d352f9f1badfaa6",
      "parents": [
        "2bd3dcc7de79145ef4472f04041d596abeeaa180"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:09:19 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:09:19 2026 +0800"
      },
      "message": "Give each version its own changelog page and script the release preparation\n\nThe version being prepared has its own page from the start of its\ndevelopment, changes-0.1.0.md, and the next version collects on the\nrolling page, which now opens 0.2.0. The Changelog menu and the root\nCHANGES.md list both.\n\ntools/release.sh prepares a release in one commit: it refuses a dirty\ntree, a malformed version, a next version that does not advance, and an\nexisting tag; checks the license headers; runs make check unless told\nnot to; removes the in-development note from the version\u0027s page; starts\nthe rolling page for the next version when it is not started; lists the\nversion under Changelog in the menu and in CHANGES.md; and commits. A\ndry run prints the plan and writes nothing. Tagging, building and\npushing stay separate steps, each easy to undo on its own. The release\nguide\u0027s prerequisites now call it.\n"
    },
    {
      "commit": "2bd3dcc7de79145ef4472f04041d596abeeaa180",
      "tree": "1c6e8229d7497c2a2516c768880f84f6bdf3dd7b",
      "parents": [
        "e40c7a1e2fdbd598ce8292801f59b56921938887"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:01:20 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 21:01:20 2026 +0800"
      },
      "message": "Keep the changelog as a current-version page and generate release notes from it\n\nThe changelog follows the main SkyWalking repository: one page for the\nversion in development, renamed to its version at release time, and a\nChangelog menu that lists the current version and each released one. A\nCHANGES.md at the root points there, so the source package carries it.\n\nmake release-notes prints the text for a GitHub release page from the\nversion\u0027s changelog page with the download, documentation and image\nlinks appended, so the page never holds a second copy of the changes.\n"
    },
    {
      "commit": "e40c7a1e2fdbd598ce8292801f59b56921938887",
      "tree": "ac8694687c0fd3ed4b60f05ad34ad38a118a5807",
      "parents": [
        "ac411d909c64e1dc6b92feeb011e0d30b3d23932"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:44:29 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:44:29 2026 +0800"
      },
      "message": "Say what counts as a release\n\nA git tag is a candidate, and a GitHub release, an image tag or a\nbinaries artifact are conveniences. The release is the vote, the signed\npackages in the release directory on dist.apache.org, and the website\nannouncement. The guide now says so before the steps, so nobody reads\nthe GitHub release page as the release.\n"
    },
    {
      "commit": "ac411d909c64e1dc6b92feeb011e0d30b3d23932",
      "tree": "7aa3d17d8a9c94b67a9cb9b000cf0b61ab327804",
      "parents": [
        "31de7cb5d5e22b92dd141d506579658fea8bc867"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:34:59 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:34:59 2026 +0800"
      },
      "message": "Publish the image on the GitHub release, never on a tag\n\nA tag is a release candidate and now publishes nothing, which is how the\nmain SkyWalking repository behaves. Releasing the GitHub release, after\nthe vote, publishes the image under its version. The event is released\nrather than published, so a draft or a prerelease publishes nothing\neither.\n\nNothing is attached to a GitHub release. No SkyWalking project does\nthat; the packages a release ships are built and signed by the release\nmanager and distributed through dist.apache.org and the downloads page.\nCI still cross-compiles every platform on every run and keeps the\npackages as an artifact, so a broken build is caught at once.\n"
    },
    {
      "commit": "31de7cb5d5e22b92dd141d506579658fea8bc867",
      "tree": "38a63b453f26f98f354be028614bcbd329b25d92",
      "parents": [
        "5bbbaf9624dcd01725256654fae4996f211a65ba"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:30:44 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:30:44 2026 +0800"
      },
      "message": "Report the version without the tag\u0027s v\n\nThe tag carries a v, as Go modules require, but the version stamped by\nmake release and by CI does not. A local build on a tagged checkout\nprinted v0.1.0 while a released binary printed 0.1.0. The default now\nstrips the prefix so every build of one tag prints the same version.\n"
    },
    {
      "commit": "5bbbaf9624dcd01725256654fae4996f211a65ba",
      "tree": "c83e999fa49a1d95b1b927b505220ad6ec4127b0",
      "parents": [
        "9e621957706a2dda0c25886404cb0c395cdbdf39"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:22:00 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:22:00 2026 +0800"
      },
      "message": "Say that the container image is Linux only\n\nIt is built for linux/amd64 and linux/arm64. Docker Desktop on Windows\nruns it as a Linux container, and the Windows binary package is the\npath without Docker. The pages that describe the image now say so.\n"
    },
    {
      "commit": "9e621957706a2dda0c25886404cb0c395cdbdf39",
      "tree": "36bb04de150e6106040ba013fa18dc5423b8fec3",
      "parents": [
        "9db072f08662700729b04c2dae70fb5588bb11e5"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:21:37 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 20:21:37 2026 +0800"
      },
      "message": "Tag images and artifacts with the complete commit id\n\nA commit build was tagged sha- and eight characters. It is now the\nwhole 40-character id, which is what a person copies from git and what\nthe revision label already carried. The binaries artifact and the\nversion stamped into a non-release build use the same id.\n"
    },
    {
      "commit": "9db072f08662700729b04c2dae70fb5588bb11e5",
      "tree": "0dbe0a9cce30e04966e76c1aac46cb6e23525722",
      "parents": [
        "4cef7159de5874a0d462d5459e0dc330b5bcce1c"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 18:42:18 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 18:42:18 2026 +0800"
      },
      "message": "Compare zone paths the platform\u0027s way in the layout test\n\nThe zone builds real filesystem paths, so on Windows they carry\nbackslashes, and the test compared them to slash literals. It was the\nonly failure in the first Windows run.\n"
    },
    {
      "commit": "4cef7159de5874a0d462d5459e0dc330b5bcce1c",
      "tree": "50a08057640a7d5743c6f4e3c8a88aff028c2f1a",
      "parents": [
        "8ed397493eda56ea1e1392073feff8dd8bd77b49"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 18:05:59 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 18:05:59 2026 +0800"
      },
      "message": "Keep the collector side and the server side from importing each other\n\nThe collector side lands Session Data. The server side assembles it and\nserves it. They share the storage root, the index, the two public formats\nand the model, and nothing else, so that a later split into a collector\nbinary and a server binary is packaging and not a refactor.\n\nTwo imports crossed that line. The index rebuild lived in the adapter\nalthough it reads converted records and needs no runtime knowledge; it is\nnow index.Rebuild and the parser\u0027s default. The view imported the adapter\nfor its glossary; the command now hands the glossary to the view. A test\nunder tests/boundary parses every import and fails when either side\nreaches the other.\n\nThe two commits before this one were pushed without it by mistake and do\nnot build on their own: the adapter\u0027s rebuild file is already removed\nthere while its replacement arrives here.\n"
    },
    {
      "commit": "8ed397493eda56ea1e1392073feff8dd8bd77b49",
      "tree": "8422bb0af4c8fb05ed488817ed0762dd011d5d21",
      "parents": [
        "c57fd3d1a6cd3e6682a62fb9a35c4be92eb370ec"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 18:05:33 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 18:05:33 2026 +0800"
      },
      "message": "Ship binary packages for macOS, Linux and Windows\n\nmake binaries cross-compiles darwin/arm64, darwin/amd64, linux/amd64,\nlinux/arm64 and windows/amd64 and packages each with LICENSE and NOTICE,\nand make release now builds them beside the source package, with a\nchecksum and a signature for every file. It refuses to run unless the\ntag is checked out and the tree is clean, because the binaries come from\nthe working tree.\n\nCI builds and tests on Windows as well, without the race detector, which\nneeds a C toolchain the runner does not put on its path. A new job\ncross-compiles every platform on each run and keeps the packages as an\nartifact; when a release is published, after the vote, it attaches them\nto the release.\n"
    },
    {
      "commit": "c57fd3d1a6cd3e6682a62fb9a35c4be92eb370ec",
      "tree": "3e8f3e115f180dd55ed0dfc68dd97fee3c780d32",
      "parents": [
        "720568ef85e0bafe4af56dc0d2243217ddd31015"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 18:05:33 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 18:05:33 2026 +0800"
      },
      "message": "Build and run on Windows\n\nThe session lock used flock, which Windows does not have. Opening the\nlock file with no sharing allowed does the same job: every other open\nfails until the handle closes, and the system closes it when the process\ndies. A file\u0027s identity was an inode; on Windows it is the volume serial\nnumber and the file index. Each now lives in one file per platform.\n\nRelative source paths are written with forward slashes on every\nplatform. They go into cursors and landed headers, and a storage root\nmust read the same wherever it was collected. A checkout is LF\neverywhere, because a digest is computed over source bytes and a Windows\ncheckout that rewrote line endings would change every one.\n"
    },
    {
      "commit": "720568ef85e0bafe4af56dc0d2243217ddd31015",
      "tree": "23b203eeb96bc771c49558ed22a0e6e981a39c18",
      "parents": [
        "b51aeef5fc16169d8b10be7e250eb862fa6e2770"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 17:23:43 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 17:23:43 2026 +0800"
      },
      "message": "Document setup, the data formats, the guides and the 0.1.0 changes\n\nThe published menu had two sections. It now follows the layout of the\nother SkyWalking projects: concepts and designs, setup, data formats,\nadapters, guides and changes.\n\nSetup covers the quick start, the configuration file, every command and\nthe container image. Every sample is the output of one real run on\n2026-09-03. Data formats describe the storage root, Session Data and\nSession Flow from the code that defines them, for a third-party adapter\nthat produces the first and a consumer that reads the second. The guides\nare contributing and how to release in the Apache way. The changes page\nis what 0.1.0 contains. The status paragraphs that still said nothing\npast collection existed are corrected.\n"
    },
    {
      "commit": "b51aeef5fc16169d8b10be7e250eb862fa6e2770",
      "tree": "0422b4402699042d3d71031cfc6372e1fa7c4bb4",
      "parents": [
        "7bd7e517ecb2ed96d4e44548733280595d14b86f"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 17:23:43 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 17:23:43 2026 +0800"
      },
      "message": "Publish version tags for the container image after the release vote\n\nA v* tag is a release candidate until the Apache vote passes, so pushing\none now publishes only the immutable sha tag. Publishing the GitHub\nrelease, which happens after the vote, attaches the version, its\nmajor.minor line, and latest when it is the newest release. A\npre-release moves no floating tag. The development head gets main\ninstead of latest, so latest always names a release. A workflow run by\nhand promotes a tag whose release predates this or retries a failed\npublish.\n\nThe version reaches the binary through a build argument and asz version\nprints it. Images carry the source, revision and version labels. make\nrelease builds the source package, its checksum and its signature for a\nvote.\n"
    },
    {
      "commit": "7bd7e517ecb2ed96d4e44548733280595d14b86f",
      "tree": "c62d3f1a3edf23cb54c3dc4837111a60e90ac1e1",
      "parents": [
        "1f64dd90e918878e54ac600553093c1512ec55bd"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 17:23:42 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 17:23:42 2026 +0800"
      },
      "message": "Let a source resume under a new inode when its bytes are unchanged\n\nThe cursor treated a changed inode as a replaced file. That is also what\na bind mount into a container, a restored backup or a copied source tree\nlook like, and inside a container every source collected on the host\nconflicted although not one byte had changed. The bytes now decide: the\nwindow before the cursor is verified against the digest the cursor\nalready keeps, and only a mismatch or a truncation is a conflict. A\ncursor with no digest still conflicts, because the bytes cannot be\nchecked.\n\nWhen nothing new landed, the new identity is saved anyway. Otherwise\nevery later pass re-reads the tail window of every unchanged source to\nverify it again.\n"
    },
    {
      "commit": "1f64dd90e918878e54ac600553093c1512ec55bd",
      "tree": "a2b2f41f970a1f050c4fe9a2420a9449a2e8ccdf",
      "parents": [
        "2b3619ba071173d0449606bb7609bce00a812340"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 16:42:21 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 16:42:21 2026 +0800"
      },
      "message": "Render every date and time in English with a 24-hour clock\n\nThe pages left the locale to the browser, so the month and day came out\nin the viewer\u0027s own language and two people looking at one conversation\nsaw different text. Every date, time and number formatter now uses one\nfixed English locale. The timeline clocks switch from hour12:false to\nhourCycle:h23, because the older option renders midnight as 24:05 in\nsome browsers.\n"
    },
    {
      "commit": "2b3619ba071173d0449606bb7609bce00a812340",
      "tree": "f22c31845f824dc491197b936ea0dbf92d599c5b",
      "parents": [
        "6af47bc8fb95fdeb50bbe3d51611bf78b2a84c09"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 15:40:14 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 15:40:14 2026 +0800"
      },
      "message": "Add the default configuration file at the repository root\n\nasz.yaml carries every built-in default written out with a comment on\neach value, so the defaults can be read and edited without reading Go.\nEvery command reads it from the working directory when no -config flag\nis given; an explicit -config still wins. A test holds the file to the\ncompiled defaults so the two cannot drift apart.\n\nThe default storage root ./data may be a link on a developer machine.\nThe ignore rule now matches a link as well as a directory, and the\nlicense header check skips the root, which a checkout that has collected\nneeded anyway.\n"
    },
    {
      "commit": "6af47bc8fb95fdeb50bbe3d51611bf78b2a84c09",
      "tree": "fd6a5772a366b303c93c28037d5eeaf1b950757e",
      "parents": [
        "23102e717623fc7331a44ec14e9940059b1e4273"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 15:40:14 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 15:40:14 2026 +0800"
      },
      "message": "Show the SkyWalking logo and keep the page current from the local source\n\nThe README opens with the SkyWalking logo and the license badge, and its\nlicense section names the trademarks, as the Horizon UI repository does.\nThe served pages carry the same wordmark and product name in their header\nand the SkyWalking mark as the tab icon. Both images are embedded and\nserved from one handler, so the tab and the page cannot drift apart. The\ncopied files had the license comment before the XML declaration, which\nstrict renderers reject, so the declaration now comes first.\n\nasz view never refreshed anything, so a page could only show data as old\nas the last parse. With the local Claude Code adapter it now runs the\ncollector and the parser in the same process, once with -once or on the\ncollector interval otherwise. A new /api/status endpoint reports the last\nand next refresh, and the list page shows them and fetches the list again\nonly when the refresh time moves. In static mode the strip is hidden.\n\nParsing every session after each pass measured 3.3 s on a 43-session\ncorpus with nothing new, most of a 5 s interval, so the collector now\nreports which sessions changed and only those are parsed after the first\npass. The first pass parses everything, because rounds can lag behind an\nearlier collect that was never parsed.\n"
    },
    {
      "commit": "23102e717623fc7331a44ec14e9940059b1e4273",
      "tree": "17d69d23848ea55e4ac5339ab0e7606668d6b93c",
      "parents": [
        "eea59a1f8032fbda26db5662b976d41562992ea0"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 15:40:14 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 15:40:14 2026 +0800"
      },
      "message": "Say the v0.8 draft predates the repository\n\nThe design note referred to it by its old file name, which is not part of\nthis repository. Name it as the earlier draft from when the project was\ncalled Agent Sessionizer, so a reader does not look for a missing file.\n"
    },
    {
      "commit": "eea59a1f8032fbda26db5662b976d41562992ea0",
      "tree": "a075379ccca706dc73a155ba59c05ee150776e04",
      "parents": [
        "9a81ef38641321d9de731e40b028b3401c457237"
      ],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 14:11:08 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 14:11:08 2026 +0800"
      },
      "message": "Forbid AI attribution in commits and pull requests\n\nThe initial import commit carried a Co-Authored-By trailer naming an AI\ntool. Apache project history records people, so CLAUDE.md now states\nthe rule plainly: no trailer, no \"Generated with\" line, no other\nmention of an AI tool in a commit message or a pull request\ndescription.\n"
    },
    {
      "commit": "9a81ef38641321d9de731e40b028b3401c457237",
      "tree": "5c3ea61f91def21c31947a9c995d8e5a27fda988",
      "parents": [
        "a29e3ffbf899ab0e11525963d010c3c0a56411dc"
      ],
      "author": {
        "name": "吴晟 Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 14:10:22 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Sep 03 14:10:22 2026 +0800"
      },
      "message": "Remove branch protection and the required review (#1)\n\nThe project is new and has one committer. A required approving review\nmeans no pull request can ever merge, because the author cannot approve\ntheir own change and there is nobody else to ask. The same rule also\nblocks direct pushes to main, which is how a one-person project is\nmaintained at this stage.\n\nSetting protected_branches to null is the form the ASF documentation\ngives for removing every protection rule. The fan-in CI job named\nRequired stays, so protection can be turned back on with one line when\nthe project has more committers."
    },
    {
      "commit": "a29e3ffbf899ab0e11525963d010c3c0a56411dc",
      "tree": "5683250107d0ff1e41e305d497056f947c1d08ab",
      "parents": [],
      "author": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 11:20:35 2026 +0800"
      },
      "committer": {
        "name": "Wu Sheng",
        "email": "wu.sheng@foxmail.com",
        "time": "Thu Sep 03 11:20:35 2026 +0800"
      },
      "message": "Initial import of SkyWalking AI Sessionizer\n\nConversation-level observability for long-lived AI agents: it assembles\nfragmented agent telemetry - transcripts, subagent streams, workflow\njournals - into one durable conversation structure, and serves it as a\npage. Collection from local Claude Code files, assembly into an\nappend-only chain of immutable rounds, and the reading view are in;\nstatic export and OTLP push are not yet.\n\nThis is the current tree of the personal project it grew from, imported\nwithout its history. The module path is the ASF repository, every file\ncarries the ASF header, NOTICE is in the ASF form, and .asf.yaml sets\nsquash-only merges and a protected main behind the CI\u0027s single required\ncheck. CI uses only apache/*, actions/* and github/* actions, and its\nDocker job builds the image on pull requests and publishes it to GHCR\nfor linux/amd64 and linux/arm64 on pushes to main and on version tags,\nwith plain shell for login and buildx so no third-party action is needed.\n\nCo-Authored-By: Claude Fable 5.1 \u003cnoreply@anthropic.com\u003e\n"
    }
  ]
}
