Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
The 0.20.0 beta line follows the frozen operator contract; earlier alpha releases
remain historical snapshots. Beta does not mean error-free operation.

## [0.20.0-rc.2] — 2026-11-01

### Security

- Require and hash-lock pypdf 6.21.4, excluding seven high-severity advisories
affecting the PDF parser in RC.1. Malformed PDF processing remains subject to
the existing authorization and execution boundaries.
- Keep the remaining dependency versions and frozen operator contract unchanged.
- This security update starts a new deployed RC observation window. Stable 0.20.0
still requires seven consecutive healthy calendar days and final-artifact checks.

## [0.20.0-rc.1] — 2026-10-28

### Release qualification
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ come from `stdin` instead of `getUpdates`.
```
$ talos chat

◉ Talos / 0.20.0-rc.1
◉ Talos / 0.20.0-rc.2
Your terminal. Your rules.
──────────────────────────────────────────────────────────────────────────
model claude-cli/claude-opus-4-1
Expand Down Expand Up @@ -937,7 +937,7 @@ artifact checks and the seven-day operating observation. The frozen
[beta contract](docs/beta-contract.md), [recovery runbook](docs/recovery.md) and
local `python scripts/beta-gate.py --previous <published-version>` make these checks repeatable.
The [RC and stable qualification plan](docs/stable-readiness.md) tracks the next
transition from beta through `0.20.0-rc.1` to `0.20.0`; stable remains subject to the RC observation and final-artifact gates. The path to 1.0
transition from beta through `0.20.0-rc.2` to `0.20.0`; stable remains subject to the RC observation and final-artifact gates. The path to 1.0
requires evidence from the beta line and a verified upgrade from a previous beta;
it is not a calendar promise.

Expand Down
16 changes: 9 additions & 7 deletions docs/stable-readiness.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# From beta to a stable 0.20.0

This tree identifies `0.20.0-rc.1`, followed by `0.20.0` only after the evidence
This tree identifies `0.20.0-rc.2`, followed by `0.20.0` only after the evidence
below passes. Publication is established by the signed release assets, not this
source label. The upgrade baseline is `0.20.0-beta.9`.
source label. The upgrade baseline is `0.20.0-rc.1`. RC.2 updates pypdf to address newly
reported high-severity advisories; its deployed observation window starts afresh.

The historical `0.20.0-alpha.rc.*` artifacts qualified the earlier transition
**into beta**. They are not candidates for this transition out of beta. `1.0.0`
Expand Down Expand Up @@ -30,7 +31,7 @@ not silently included in a broad claim that everything passed.
| Real model flow | Isolated real-model E2E: read, approval/refusal, exactly-once effect, restart/state restoration and the event chain. Record provider and results; do not send external test messages. |
| User-visible flow | Telegram reply/approval/background completion behavior, including conversation isolation and no false completion while waiting. Injected transport tests and an actual service probe are distinct evidence. |
| Exact artifact | Build from the qualified public commit; SHA-256, pinned Ed25519 verification, tamper rejection and archive hygiene. Source tests alone do not qualify an archive. |
| Installation/recovery | Clean install and beta.9→RC signed upgrade on macOS and ARM64 Linux; check operator identity/configuration, selected model, history, schedules, file modes and rollback. Rehearse isolated service restart and retain the prior runtime. |
| Installation/recovery | Clean install and RC.1→RC.2 signed upgrade on macOS and ARM64 Linux; check operator identity/configuration, selected model, history, schedules, file modes and rollback. Rehearse isolated service restart and retain the prior runtime. |
| Delivery | Native Homebrew lifecycle, Pinokio clean/repeated install, and byte-for-byte HTTPS read-back of the release, website and installer definitions. Check main CI after each merge. |
| Observation before stable | Seven consecutive calendar days on a deployed RC, with daily health/event-chain records, investigated errors, no unexplained restart and no unresolved security or data-loss regression. Preserve failed samples. A release-blocking runtime fix starts a new candidate/window. |
| Stable promotion | Rebuild/sign the final version and requalify its exact bytes, including RC→stable upgrade and recovery. A version-only change is still a new artifact. |
Expand All @@ -47,7 +48,7 @@ Start with the current published baseline in a prepared, hash-locked development
environment:

```sh
python scripts/beta-gate.py --previous 0.20.0-beta.9 --current 0.20.0-rc.1
python scripts/beta-gate.py --previous 0.20.0-rc.1 --current 0.20.0-rc.2
python -m pytest macos/Tests -q
python e2e.py
```
Expand All @@ -58,8 +59,8 @@ dependency locks, a disposable clean install, and signed upgrade/migration/rollb
`--without-upgrade` is a partial source check and says so; it does not qualify a
candidate. Tests and artifact downloads require their normal dependencies/network.

For an unpublished candidate, use `--current 0.20.0-rc.1`, `--previous
0.20.0-beta.9`, an explicit `--base` pointing to the candidate's `dist/` directory
For an unpublished candidate, use `--current 0.20.0-rc.2`, `--previous
0.20.0-rc.1`, an explicit `--base` pointing to the candidate's `dist/` directory
parent, and `--assets-dir` containing both versions' archive/checksum/signature.
The checkout's installer must name the candidate. The existing scripts support
`file://` for an isolated pre-publication install. Run against the actual signed
Expand Down Expand Up @@ -90,5 +91,6 @@ installation or restart its service.
| Artifact | State | Evidence boundary |
|---|---|---|
| `0.20.0-beta.9` | Published baseline | [Core main CI](https://github.com/talos-kernel/Talos/actions/runs/40661310306), [Homebrew](https://github.com/talos-kernel/homebrew-tap/actions/runs/40661911664), [Pinokio](https://github.com/talos-kernel/talos-pinokio/actions/runs/40663657826). These qualify beta.9 only. |
| `0.20.0-rc.1` | Candidate source | Requires matching signed assets and platform/install/recovery evidence; deployed RC observations start only after rollout. |
| `0.20.0-rc.1` | Published, superseded candidate | Original signed assets remain available. Its observation days do not qualify RC.2. |
| `0.20.0-rc.2` | Candidate source | Requires matching signed assets and platform/install/recovery evidence; seven new observation days start after rollout. |
| `0.20.0` | Not qualified | Needs the RC observation window and final-artifact gates above. |
6 changes: 3 additions & 3 deletions requirements.lock
Original file line number Diff line number Diff line change
Expand Up @@ -878,9 +878,9 @@ pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementatio
--hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \
--hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992
# via cffi
pypdf==6.21.2 \
--hash=sha256:0a3e1c5c886a1be03646c16a04827cc166c2a0575c971b26a4bf89686551c2d4 \
--hash=sha256:1d44d1a3a200f25062adff0085b02040e4646431ac2ccac22e42679e91466084
pypdf==6.21.4 \
--hash=sha256:33e4fb41ca352810eb4e9838aa0d82d6888a5f8bf682f43e99cce5faa666255c \
--hash=sha256:c8817e3f888d47a087872ded69812c1ef30cacb871d6e053e0c00bbaf0bc2163
# via -r requirements.txt
pyyaml==6.0.3 \
--hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ faster-whisper>=1.0 # lokales Hoeren (MIT) — siehe talos/hearing.py
cryptography>=50.0.1 # Ed25519 fuer die Release-Signatur (updater.py). Bewusst eine
# gepflegte Bibliothek statt eigener Krypto: das Update ist die
# eine Stelle, an der ein Fehler fremden Code ausfuehrt.
pypdf>=6.21.2 # PDF parsing: bounded stream/tree/xref work and October security fixes.
pypdf>=6.21.4 # PDF parsing: security fixes for malformed stream, tree and xref input.
# Office documents use standard-library ZIP/XML.
idna>=3.15 # transitiv ueber requests. Untergrenze 3.15: alles darunter
# traegt PYSEC-2026-215 (CVSS 6.9). Dieselbe Regel wie bei pypdf:
Expand Down
6 changes: 3 additions & 3 deletions site/console.html
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@

<header class="hero" id="top">
<div class="wrap">
<p class="sys">talos 0.20.0-rc.1 · operator console · MIT</p>
<p class="sys">talos 0.20.0-rc.2 · operator console · MIT</p>
<span class="rec-chip">recorded · unfurled · no live wire</span>
<h1 id="main-content" tabindex="-1">Witness one deed from door to ledger.</h1>
<p class="lede">This hall unfurls one true session, recorded on the working machine
Expand Down Expand Up @@ -553,12 +553,12 @@ <h2 class="rv">Numbers this candidate must ship.</h2>
embedded below. Either way the digits come from a count, not from memory.</p>

<div class="stats" id="releaseStats">
<div class="stat rv"><div class="n" data-f="version">0.20.0-rc.1</div><div class="l">release candidate</div><div class="sub-l" data-f="installer_version">public installer v0.20.0-rc.1</div></div>
<div class="stat rv"><div class="n" data-f="version">0.20.0-rc.2</div><div class="l">release candidate</div><div class="sub-l" data-f="installer_version">public installer v0.20.0-rc.2</div></div>
<div class="stat rv"><div class="n" data-f="tests">3456</div><div class="l">automated tests, collected by pytest</div></div>
<div class="stat rv"><div class="n" data-f="redteam_faelle">277</div><div class="l">adversarial cases, all behaving</div></div>
<div class="stat rv"><div class="n" data-f="kernel_zeilen">996</div><div class="l">lines in policy.py, readable in one sitting</div></div>
<div class="stat rv"><div class="n" data-f="werkzeuge">37</div><div class="l">tools, every one through the gate</div></div>
<div class="stat rv"><div class="n" data-f="release_ref">v0.20.0-rc.1</div><div class="l">release tag</div></div>
<div class="stat rv"><div class="n" data-f="release_ref">v0.20.0-rc.2</div><div class="l">release tag</div></div>
</div>

<div class="measure-note rv">
Expand Down
2 changes: 1 addition & 1 deletion site/docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ <h2><span class="n">Section 04</span>Run it</h2>
<section id="session" class="rv">
<h2><span class="n">Section 05</span>The terminal session</h2>
<pre>$ talos chat
Talos 0.20.0-rc.1 · anthropic-api/claude-opus-4-8 · autonomy 3
Talos 0.20.0-rc.2 · anthropic-api/claude-opus-4-8 · autonomy 3
speaking as cli:1000 · approvals possible · you are at a terminal
/help for commands, `exit` to leave

Expand Down
2 changes: 1 addition & 1 deletion site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ <h2 class="rv">Talos AI agent: your questions</h2>
<div class="wrap">
<p class="sec-tag rv">raise the keep</p>
<h2 class="rv">The command remains yours</h2>
<p class="sub rv">Release candidate 0.20.0-rc.1. Tested on Python 3.11 · 3.13, Linux and macOS, including Raspberry Pi.
<p class="sub rv">Release candidate 0.20.0-rc.2. Tested on Python 3.11 · 3.13, Linux and macOS, including Raspberry Pi.
Bring your own model: a supported CLI, configured API provider or local Ollama.
The installer runs the unit and adversarial suites in front of you, then <strong>starts nothing.</strong></p>
<div class="term rv">
Expand Down
2 changes: 1 addition & 1 deletion site/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

set -euo pipefail

VERSION="0.20.0-rc.1"
VERSION="0.20.0-rc.2"
BASE="${TALOS_BASE:-https://talos-agent.ch}"
TARBALL="${BASE}/dist/talos-${VERSION}.tar.gz"
PREFIX="${TALOS_PREFIX:-$HOME/talos}"
Expand Down
6 changes: 3 additions & 3 deletions site/status.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"version": "0.20.0-rc.1",
"version": "0.20.0-rc.2",
"release_state": "released",
"source_state": "release",
"installer_version": "0.20.0-rc.1",
"installer_version": "0.20.0-rc.2",
"tests": 3456,
"redteam_faelle": 277,
"kernel_zeilen": 996,
"werkzeuge": 37,
"release_ref": "v0.20.0-rc.1"
"release_ref": "v0.20.0-rc.2"
}
2 changes: 1 addition & 1 deletion talos/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
advertised and a released package is never left behind.
"""

__version__ = "0.20.0-rc.1"
__version__ = "0.20.0-rc.2"
6 changes: 4 additions & 2 deletions tests/test_requirements_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,13 @@ def test_pypdf_declared_floor_excludes_known_denial_of_service_versions() -> Non
requirement = next(r for r in _declared(RUNTIME[0]) if _canonical(r.name) == "pypdf")
assert not requirement.specifier.contains(Version("6.19.0"))
assert not requirement.specifier.contains(Version("6.20.0"))
assert requirement.specifier.contains(Version("6.21.2"))
assert not requirement.specifier.contains(Version("6.21.2"))
assert not requirement.specifier.contains(Version("6.21.3"))
assert requirement.specifier.contains(Version("6.21.4"))


def test_pypdf_lock_includes_denial_of_service_security_fixes() -> None:
assert all(version >= Version("6.21.2")
assert all(version >= Version("6.21.4")
for version, _ in _pins(RUNTIME[1])["pypdf"])


Expand Down
Loading