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
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ preferences live in `USER.md`. All three are operator-owned prompt state and rel
|---|---|
| Gate path | `policy.py`, **985 lines** — has to stay readable in one sitting |
| Tools | **33**, every one gated |
| Suites | **3216** collected tests · **263** adversarial · 44 end-to-end |
| Suites | **3219** collected tests · **263** adversarial · 44 end-to-end |
| Home | <https://talos-agent.ch> · docs at `/docs/` |
| Repository | `talos-kernel/talos` is the public source tree |

Expand Down Expand Up @@ -261,7 +261,7 @@ properties covered by `test_fallback_control.py` and `test_runtime_failure_repai
```bash
python3 -m venv .venv && . .venv/bin/activate && pip install --require-hashes -r requirements.lock -r requirements-dev.lock

python -m pytest tests/ -q # 3216 collected tests; platform-specific skips are explicit
python -m pytest tests/ -q # 3219 collected tests; platform-specific skips are explicit
python redteam.py # 263 adversarial cases — mandatory for any kernel change
python e2e.py # 44 cases against a real model (costs tokens and time)
python -m talos --once # single cycle, for diagnosis
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
</p>

<p align="center">
<!-- ⚠️ Bewusst „tests“, nicht „passing“: die Zahl kommt aus dem Einsammeln (3216).
<!-- ⚠️ Bewusst „tests“, nicht „passing“: die Zahl kommt aus dem Einsammeln (3219).
Plattformabhaengige Sandbox- und Repository-Pruefungen koennen uebersprungen werden;
`test_site_claims` prueft deshalb die gesammelte Zahl statt ein Umgebungsresultat. -->
<img src="https://img.shields.io/badge/tests-3216-2e7d32.svg" alt="Tests">
<img src="https://img.shields.io/badge/tests-3219-2e7d32.svg" alt="Tests">
<img src="https://img.shields.io/badge/red%20team-263%2F263-2e7d32.svg" alt="Red team">
<img src="https://img.shields.io/badge/gate%20path-985%20lines-8a4318.svg" alt="Gate path">
<img src="https://img.shields.io/badge/tools-33%20gated-8a4318.svg" alt="Tools">
Expand Down
4 changes: 2 additions & 2 deletions site/console.html
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ <h1 id="main-content" tabindex="-1">Witness one deed from door to ledger.</h1>
<a class="btn ghost" href="#measured">This candidate, measured</a>
</div>
<div class="meter-row">
<span><b>3216</b>automated tests</span>
<span><b>3219</b>automated tests</span>
<span><b>263/263</b>adversarial</span>
<span><b>985</b>lines · gate</span>
<span><b>33</b>gated tools</span>
Expand Down Expand Up @@ -554,7 +554,7 @@ <h2 class="rv">Numbers this candidate must ship.</h2>

<div class="stats" id="releaseStats">
<div class="stat rv"><div class="n" data-f="version">0.20.0-beta.4</div><div class="l">beta candidate</div><div class="sub-l" data-f="installer_version">public installer v0.20.0-beta.3</div></div>
<div class="stat rv"><div class="n" data-f="tests">3216</div><div class="l">automated tests, collected by pytest</div></div>
<div class="stat rv"><div class="n" data-f="tests">3219</div><div class="l">automated tests, collected by pytest</div></div>
<div class="stat rv"><div class="n" data-f="redteam_faelle">263</div><div class="l">adversarial cases, all behaving</div></div>
<div class="stat rv"><div class="n" data-f="kernel_zeilen">985</div><div class="l">lines in policy.py, readable in one sitting</div></div>
<div class="stat rv"><div class="n" data-f="werkzeuge">33</div><div class="l">tools, every one through the gate</div></div>
Expand Down
2 changes: 1 addition & 1 deletion site/docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ <h1 id="main-content" tabindex="-1">Talos AI agent: the field manual</h1>
<p class="lede">That one decision shapes the rest of this manual. It is why the
command list is short, and why a few obvious conveniences are missing on purpose.</p>
<div class="spec-row">
<div class="spec"><b>3216</b>automated tests</div>
<div class="spec"><b>3219</b>automated tests</div>
<div class="spec"><b>263/263</b>adversarial</div>
<div class="spec"><b>985</b>gate lines</div>
<div class="spec"><b>33</b>gated tools</div>
Expand Down
2 changes: 1 addition & 1 deletion site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ <h2 class="rv">Measured, with the path stated</h2>
<p class="sub rv">None of this asks for belief. The installer runs the unit and
adversarial suites in front of you; the real-model cases are a separate opt-in E2E run.</p>
<p class="source-caption">Release snapshot: 0.20.0-beta.4. Counts describe its test suite, not speed or real-world success rates.</p><div class="stats">
<div class="stat rv"><div class="n cnt" data-n="3216">0</div><div class="l">automated tests collected from this beta release</div></div>
<div class="stat rv"><div class="n cnt" data-n="3219">0</div><div class="l">automated tests collected from this beta release</div></div>
<div class="stat rv"><div class="n cnt" data-n="263">0</div><div class="l">adversarial cases trying to pass the kernel</div></div>
<div class="stat rv"><div class="n cnt" data-n="44">0</div><div class="l">opt-in end-to-end cases against a real model</div></div>
<div class="stat rv"><div class="n cnt" data-n="985">0</div><div class="l">lines in the file that decides every verdict</div></div>
Expand Down
2 changes: 1 addition & 1 deletion site/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

- Permission kernel: 985 lines of Python, the only code that decides
- 33 tools, all gated; unattended runs cannot escalate
- 3216 tests (automated) and 263/263 red-team cases green at the release gate
- 3219 tests (automated) and 263/263 red-team cases green at the release gate
- MCP servers run only inside a UID-separated worker, from an operator-owned registry — no marketplace, no third-party code in the agent process
- Channels: Telegram, mail (IMAP pull), CLI, WhatsApp via an operator-controlled broker — every channel fetches; no inbound port, no webhook
- Updates: signed tarballs, verified before anything is unpacked; dependencies pinned and hashed, installed with --require-hashes
Expand Down
2 changes: 1 addition & 1 deletion site/redteam/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ <h1 id="main-content" tabindex="-1">263 ways to break an agent.</h1>
<div class="spec"><b class="red">25</b>attack surfaces</div>
<div class="spec"><b>985</b>kernel lines</div>
<div class="spec"><b>33</b>gated tools</div>
<div class="spec"><b>3216</b>automated tests</div>
<div class="spec"><b>3219</b>automated tests</div>
<div class="spec"><b class="red">0</b>passes sold as safety</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion site/registry/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ <h1 id="main-content" tabindex="-1">The MCP registry</h1>
guide with the full protocol is <a href="https://github.com/talos-kernel/talos/blob/master/docs/claude-worker.md">docs/claude-worker.md</a>.
A curated starting point ships as <code>examples/mcp-servers.json</code>.</p>
<div class="spec-row">
<div class="spec"><b>3216</b>automated tests</div>
<div class="spec"><b>3219</b>automated tests</div>
<div class="spec"><b>263/263</b>adversarial</div>
<div class="spec"><b>985</b>gate lines</div>
<div class="spec"><b>33</b>gated tools</div>
Expand Down
2 changes: 1 addition & 1 deletion site/setup/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ <h1 id="main-content" tabindex="-1" class="rv">This address moved.</h1>
<a class="btn ghost" href="/">Return to the keep</a>
</div>
<div class="spec-row rv">
<div class="spec"><b>3216</b>automated tests</div>
<div class="spec"><b>3219</b>automated tests</div>
<div class="spec"><b>263/263</b>adversarial</div>
<div class="spec"><b>985</b>gate lines</div>
<div class="spec"><b>33</b>gated tools</div>
Expand Down
2 changes: 1 addition & 1 deletion site/status.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"version": "0.20.0-beta.4",
"release_state": "released",
"installer_version": "0.20.0-beta.4",
"tests": 3216,
"tests": 3219,
"redteam_faelle": 263,
"kernel_zeilen": 985,
"werkzeuge": 33,
Expand Down
2 changes: 1 addition & 1 deletion site/vergleich/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ <h1 id="main-content" tabindex="-1">The others can do more.</h1>
<div class="spec-row">
<div class="spec"><b>33</b>tools here, every one gated</div>
<div class="spec"><b>100+</b>skills there · counted honestly</div>
<div class="spec"><b>3216</b>automated tests</div>
<div class="spec"><b>3219</b>automated tests</div>
<div class="spec"><b>263/263</b>adversarial cases</div>
<div class="spec"><b>985</b>gate lines</div>
<div class="spec"><b>0</b>inbound ports</div>
Expand Down
13 changes: 13 additions & 0 deletions talos/provider_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ def event_data(self) -> dict:
"unknown": "The provider process failed without a classified diagnostic.",
}

_AUTH_FAILURE_MARKERS = (
"your authentication token has been invalidated",
"your access token could not be refreshed because your refresh token has expired",
"refresh token has expired. please log out and sign in again",
)


def cli_failure(stdout: str, stderr: str, exit_code: int, *,
provider: str, model: str) -> ReasonerFailure:
Expand Down Expand Up @@ -81,6 +87,13 @@ def cli_failure(stdout: str, stderr: str, exit_code: int, *,
or "The API returned a response containing only thinking content" in bounded):
kind = "empty_response"
break
# Official Codex CLI refresh failures are plain stderr rather than the
# structured provider envelope above. Match only the bounded, stable
# authentication diagnostics; arbitrary Exit-1 output remains unknown.
lowered = bounded.lower()
if any(marker in lowered for marker in _AUTH_FAILURE_MARKERS):
kind = "key_rejected"
break
message = _MESSAGES[kind]
if reset:
message = "You've hit your session limit · resets " + reset
Expand Down
18 changes: 18 additions & 0 deletions tests/test_provider_resilience.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ def test_failed_cli_does_not_expose_unknown_output():
assert 'private entire prompt' not in str(e)


@pytest.mark.parametrize('diagnostic', [
'Your authentication token has been invalidated. Please try signing in again.',
'Your access token could not be refreshed because your refresh token has expired. '
'Please log out and sign in again.',
])
def test_codex_auth_refresh_failure_is_classified_without_leaking_text(diagnostic):
e = cli_failure('', diagnostic, 1, provider='openai-codex', model='gpt-5.6-sol')
assert e.kind == 'key_rejected'
assert e.fallback_allowed is False
assert diagnostic not in str(e)


def test_unrelated_exit_one_remains_unknown():
e = cli_failure('', 'unrelated local process crash', 1,
provider='openai-codex', model='gpt-5.6-sol')
assert e.kind == 'unknown'


@pytest.mark.parametrize('backend', ['claude', 'hermes'])
def test_probe_timeout_never_exposes_the_subprocess_prompt(tmp_path, monkeypatch, backend):
import subprocess
Expand Down
Loading