v0.99.4
Added
-
The free read-only Studio command centre now renders exact-status board
columns from the blackboard and live claim leases. Open, claimed, working,
input-required, blocked, and closed work remain distinct; future statuses
fail visibly into Other, ad-hoc claims are labelled undeclared, and partial
board snapshots disclose truncation without fabricating omitted dependencies
as blockers. The 550-line inline command renderer is
split into focused packaged CSS/JavaScript assets, and every untrusted task,
event, and operator field is inserted as DOM text rather than HTML. -
A standalone, hosting-neutral Managed GitHub App package now ships under
integrations/github-app/. It renders a least-privilege App manifest,
verifies bounded HMAC-SHA256 pull-request webhooks before parsing, creates
short-lived RS256 App credentials, scopes installation tokens, reads bounded
open-PR file inventories through a fixed-origin no-redirect REST client,
reuses the existing core conflict finder, and creates completed neutral
advisory checks. The local core gains no GitHub dependency or hosted state;
App registration, secret custody, hosting, retries, tenancy, and billing
remain owner-gated. A dedicated Python 3.10–3.13 workflow enforces strict
typing, 100% line/branch coverage, security/dependency scans, package build,
and wheel-boundary inspection. -
The read-only cockpit risk panel now enriches its bounded safe-work queue
with explainable route candidates and resource bids from the existing local
advisory scorers. Risk and ready-task rows link to a new
/postmortem.json?task=IDdurable-store feed. The renderer and styles live in
dedicated risk-panel assets, shrinking the original cockpit JS/CSS instead
of turning either into a Godfile; no hint claims work, assigns an owner,
reserves capacity, or grants authority.
Security
-
A weekly or manual read-only Actions-history audit now classifies the latest
500 main-branch workflow runs and fails visibly when a failure, timeout,
stale run, action-required run, or cancellation lacks later successful
evidence for the same workflow. Raw and classified evidence remains attached
to every audit. A separate SHA-pinned link workflow checks public Markdown on
documentation changes and weekly drift, refuses private or loopback targets,
requires TLS 1.2 or newer, and does not treat HTTP 5xx responses as healthy. -
A read-only property-based fuzz workflow now exercises the production bounded
wire decoder and SQLite event store on a weekly or manual schedule. Separate
Hypothesis targets cover arbitrary wire bytes, JSON round-trips, depth bombs,
persistence across reopen, bounded cursor walks, and exact deletion with
1,000 examples per property. Any falsifying case is promoted to a committed
regression; the workflow is automated local evidence, not external protocol
certification. -
Future tag releases now fail closed unless GitHub's first-party attestation
action signs SLSA provenance for every checksum-recorded wheel, source archive,
and SBOM before PyPI publication. The GitHub Release workflow independently
verifies the portable Sigstore bundle against the repository, tag, source
commit, and pinned publishing workflow before attaching the same canonical
files and a stablesynapse-channel-vX.Y.Z-provenance.sigstore.jsonasset.
This applies beginning with the next release; it does not retroactively sign
the already-published 0.99.3 artifacts.
Changed
-
make install-hooksnow installs a lightweight pre-push stage alongside the
pre-commit and commit-message hooks. It fails on stale generated capability
counts, invalid commit-trailer history, or version-surface drift, and
deliberately runs no pytest, coverage, or exhaustive preflight. The latter is
reserved for explicitly requested/resource-reserved verification while CI
owns the full suite on ordinary pushes. -
Staging Python or
pyproject.tomlnow runs strict whole-tree mypy in the
pre-commit gate instead of relying on later CI or partial-path checks. A small
cross-platform resolver prefers the repository virtual environment, supports
one explicit fail-closed interpreter override, and invokes mypy with fixed
non-shell arguments. The remote pre-commit job installs the same hash-locked
development environment before running the hook. -
Commit identity discipline is now enforced instead of relying on operator
habit.make install-hooksinstalls acommit-msggate requiring exactly
one vendor-neutral Synapse seat suffix and the exact project authorship line;
it also rejects forbidden self-promotional subject language. A SHA-pinned
workflow audits every introduced commit and the complete forward-only history
weekly, and the same audit runs in local preflight. -
Main-branch CI no longer cancels an in-progress earlier head when another
commit lands. Every push is keyed by its immutable commit SHA and must finish
the existing Python 3.10–3.13 matrix; pull-request and manual runs retain
stale-run cancellation on their shared ref. -
The repository coverage gate now fails below 98% instead of 95%, raising the
enforced minimum floor.pyproject.toml, the contributor guide, and the
validation guide record the same threshold, and no existing coverage was reduced.
Fixed
-
GitHub Releases and PyPI now receive the exact same wheel and source archive
from one tag build. The tag-bound OIDC publish workflow records the complete
distributions and SBOM inSHA256SUMS, preserves them as one immutable
Actions artifact, verifies them before upload, and never tolerates an existing
file from a rebuilt run. Only after PyPI succeeds does the GitHub Release
workflow consume that exact source-run artifact; it rechecks the file set and
every SHA-256 digest, pins the source SHA and version tag, and remains safely
rerunnable without rebuilding if GitHub release creation fails. -
The handshake-abort log filter now recognises the reconnect-storm
signature:ConnectionClosedErrorwith no close frame received or sent.
That class subclassesWebSocketExceptionrather thanConnectionError
and carries no cause chain, so the live 0.99.3 hub logged four full
opening handshake failedtracebacks while its clients reconnected after
a restart. The rule is fail-narrow — a framed close (a genuine close code
in either direction) and every other handshake error stay loggable.