Skip to content

Session Kit v0.2.1, superseded beta

Pre-release
Pre-release

Choose a tag to compare

@dob323 dob323 released this 11 Aug 07:27
· 64 commits to main since this release

Superseded. This beta line is no longer current. The supported release is the latest. Nothing here has been removed: the artifact, its checksum and its provenance file stay exactly as published.

Session Kit v0.2.1

Public beta for Linux with systemd and macOS 14 or newer.

Why this release

The headline problem was the integrity of the release chain itself. The v0.2.0
tag and the v0.2.0 artifact were built from two different commits, nothing in
the process compared them, and the source commit the artifact records has since
been collected, so that release cannot be reproduced or audited at all. The
failure was not inside any single tool; it was the manual sequence between
them, where each step could quietly name a different commit. This release
replaces that sequence with one command that binds export, public commit, tag,
and archive to a single source commit and proves the tag and the artifact are
the same bytes before anything is published.

Three other things that were silently untrue are also fixed: a verb that had
never once worked, a terminal that closed the only context a session recovery
needs, and a public export that shipped an install missing the hook files it
then registered.

Release integrity

  • tools/publish-release makes a release one verified transaction. It exports
    one source commit, syncs that exact tree into the public repository as one
    commit, annotates a tag on it, builds the artifact from the same source
    commit, and then proves rather than assumes that the tag and the artifact
    agree: the blob set of the tagged commit must equal the export, the files
    inside the archive must equal the export, and the SOURCE.json inside both
    must record the release commit. Ten named gates each fail closed, and a
    printed chain record binds version, source commit, public commit, previous
    public head, tree digest, and archive digest.
  • --dry-run rehearses the whole sequence in throwaway clones and only reads
    the real public repository. --push requires an interactive terminal and a
    typed confirmation, and refuses outright if any override was used, so a
    published release can never carry one.
  • Reproducible archives are now reproducible across Python versions. Entry
    ordering came from sorting Path objects, which defers to the interpreter's
    own path comparison, so two runners could each produce a byte-different
    archive that verified as reproducible against itself. Ordering is pinned to
    PurePosixPath parts. The builder also refuses an unreachable commit, and
    re-opens and verifies the archive it has just written.

Fixed

  • sp msg intake delegate launches a worker. The CLI read the intake
    entry's cwd, but the spool has stored the project directory as source_cwd
    since the schema's first commit, so every delegation died with dispatch is uncertain. The verb had therefore never worked, in any configuration. Alias
    message ids now resolve before the entry is read, and a new end-to-end test
    drives record → preflight → delegate through the installed CLI with nothing
    stubbed.
  • A managed terminal survives a clean provider exit. A clean /exit closed
    the shpool terminal immediately, destroying the only context that still knew
    the exact conversation identity a reopen needs. The default is now the
    recovery menu with the terminal alive; closing is one more keypress and is
    not undoable. ~/.sk_autoclose_on_clean_exit restores the old behaviour, and
    a crash stops at the menu either way.
  • A public install receives the hook files it registers. The export
    manifest matched 187 of 220 tracked files and missed everything under
    extras/, including both intake hooks, which are registered by absolute path
    into the installed release. Such an install worked until the first prompt.
    The manifest now exports 224 files: extras/**, the supervisor-family tests,
    and this release's new checker and end-to-end tests.
  • The Linux watchdog no longer installs dead. session-kit services enable
    never enabled session-kit-watchdog.service, so every Linux install carried
    a watchdog unit that was installed, disabled, and inert.

Security

  • Every test-only environment hook is gated behind SESSION_KIT_TESTING.
    Five hook families reached fourteen production sites, eleven of them honoured
    unconditionally. The largest was SESSION_KIT_PROC_ROOT, ungated in seven
    places: /proc is where every identity proof in the kit gets its answer, so
    one environment variable could hand-author that evidence, including the
    evidence the reaper uses to decide a session is dead. The lifecycle
    failpoint's fatal branch also fired ungated, and two JSON-file hooks could
    substitute the whole session roster. A gate that refuses a hook falls back to
    real evidence rather than dying, a new test proves every gate closed and
    open, and a regression test fails if a hook name is ever read again without a
    gate beside it.
  • Personal identifiers no longer ship. The maintainer's name was present as
    prose and as public API surface: a supervisor ledger key, an MCP
    send_message schema property, receipt strings, and the From: line of the
    envelope injected into every messaged agent. Test fixtures carried real email
    addresses and account aliases. Those are role words, @invalid.example
    addresses, and neutral aliases now. tools/public-scan digests the private
    tokens and also hashes the parts of underscore-separated identifiers, so an
    identifier compound can no longer hide a private word, seeded files that
    passed the old scanner are refused by this one.

Health and checks

  • Doctor verifies the conditions under which it previously reported healthy
    while sessions could not survive a logout: the watchdog unit enabled and
    active rather than merely installed, logind lingering on, the installed
    shpool meeting the pinned 0.11.0, per-unit socket and timer state, and that
    every registered hook file exists and is executable at the exact path the
    registration runs. Every failure row carries a one-line fix command.
  • tools/check-embedded-scripts extracts all 116 heredoc bodies from the 34
    shell files, compiles each with the right tool, and maps errors back to real
    line numbers. CI runs it on Linux and macOS.
  • ruff and py_compile now reach the 2,186-line release engine that no check
    had ever read, and the mypy target grows from 24 files to 58.

Licensing

  • Vendored Maniple files named their upstream source but shipped no copyright
    notice and no MIT permission text, which is the part MIT requires to be
    included. Upstream publishes no LICENSE file at the pinned commit, so the
    notice reproduces the standard MIT text with the holder taken from upstream's
    own declared authors and says so explicitly.
  • Every shpool-patch file, not only 0001, now opens with the project, the
    Apache-2.0 copyright, the base revision fe2d115 (shpool 0.11.0), and what
    it changes. All four were re-proven to apply cleanly to a fresh upstream
    clone.

Upgrading

No breaking changes for public users. Commands, exit codes, JSON fields, and
configuration keys are unchanged, and the release payload schema a pinned older
release validates is untouched, so a rollback still works.

Two behaviour notes:

  • A clean provider exit now leaves the terminal open at the recovery menu
    instead of closing it. If you preferred the old behaviour, create
    ~/.sk_autoclose_on_clean_exit. The previous ~/.sk_keep_exit_menu marker
    no longer does anything.
  • The supervisor ledger and the MCP send_message schema name the operator
    confirmation with a role rather than a person. This is internal: a ledger row
    written before this release records the old key, so it now reads as
    unconfirmed and counts toward the autonomous turn budget. That fails in the
    restrictive direction rather than the permissive one, the ledger is
    append-only, and a one-shot local migration is available for anyone who wants
    the earlier rows to keep counting as confirmed.

Install

Beta releases are published as GitHub prereleases. releases/latest does not
resolve to a prerelease, so name the tag explicitly. Release assets are named
by source commit rather than by version.

mkdir session-kit-download
cd session-kit-download
gh release download v0.2.1 --repo dob323/session-kit
if command -v sha256sum >/dev/null; then
  sha256sum --check session-kit-*.sha256
else
  shasum -a 256 --check session-kit-*.sha256
fi
tar -xzf session-kit-*.tar.gz
cd session-kit-*/
./install.sh --check
./install.sh
session-kit doctor
session-kit services enable

Without the GitHub CLI, download the .tar.gz, .sha256, and
.provenance.json assets from this release page into one empty directory. The
checksum file covers the archive; check it with sha256sum --check on Linux or
shasum -a 256 --check on macOS. The provenance file records the exact source
commit and public-tree digest.

./install.sh --check is read-only. The installer copies files and user-service
definitions but does not start, stop, restart, or enable a service.

Full instructions, requirements, and the unattended path: docs/install.md.
Updating an existing install and rolling back: docs/update-and-rollback.md.
Every change in this release: CHANGELOG.md.