Commit Graph
2537 Commits
Author SHA1 Message Date
dependabot[bot] d52e992394 chore(deps): bump the actions group across 1 directory with 7 updates
Bumps the actions group with 7 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [github/codeql-action/init](https://github.com/github/codeql-action) | `4.37.7` | `4.38.2` |
| [github/codeql-action/analyze](https://github.com/github/codeql-action) | `4.37.7` | `4.38.2` |
| [hadolint/hadolint-action](https://github.com/hadolint/hadolint-action) | `3.4.0` | `3.5.0` |
| [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `4.3.0` | `4.4.1` |
| [docker/build-push-action](https://github.com/docker/build-push-action) | `7.3.0` | `7.4.0` |
| [github/codeql-action/upload-sarif](https://github.com/github/codeql-action) | `4.37.7` | `4.38.2` |
| [actions/deploy-pages](https://github.com/actions/deploy-pages) | `5.0.0` | `5.0.1` |



Updates `github/codeql-action/init` from 4.37.7 to 4.38.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)

Updates `github/codeql-action/analyze` from 4.37.7 to 4.38.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)

Updates `hadolint/hadolint-action` from 3.4.0 to 3.5.0
- [Release notes](https://github.com/hadolint/hadolint-action/releases)
- [Commits](https://github.com/hadolint/hadolint-action/compare/2a66e89f53d0771bb131a7fa31f3136336094aa6...06be81baf89a55ffd0e24b8f04a4185738dd3387)

Updates `docker/setup-buildx-action` from 4.3.0 to 4.4.1
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/37fe631027851001ddb9b187196cc803df7f5f0e...f87e5991a6d7451dcb8d9637bfbc97413f497069)

Updates `docker/build-push-action` from 7.3.0 to 7.4.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/53b7df96c91f9c12dcc8a07bcb9ccacbed38856a...c3c9e263c25d99ce0380d002d59b67737d91b0dc)

Updates `github/codeql-action/upload-sarif` from 4.37.7 to 4.38.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)

Updates `actions/deploy-pages` from 5.0.0 to 5.0.1
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](https://github.com/actions/deploy-pages/compare/cd2ce8fcbc39b97be8ca5fce6e763baed58fa128...368f82528645a54fb793d4d04e342629a3f51346)

---
updated-dependencies:
- dependency-name: actions/deploy-pages
  dependency-version: 5.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: docker/build-push-action
  dependency-version: 7.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: docker/setup-buildx-action
  dependency-version: 4.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.38.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: github/codeql-action/init
  dependency-version: 4.38.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.38.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: hadolint/hadolint-action
  dependency-version: 3.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-08 17:40:38 +00:00
Robert Vind-Gardoș a8c147b238 fix(reminders): retry failed note delivery through the configured channel (#6566) 2026-10-07 15:38:41 +02:00
Léo ec5bcd2b9a perf(tools): take one control-plane snapshot per grep/glob/ls scan (#6551)
The #6503 merge added _control_plane_path() to _is_denied_tool_path(),
which grep, glob and ls call per enumerated entry. Without a snapshot
argument every call rebuilt _control_plane_snapshot() and stat'ed every
protected state file again. A 5,000-file grep went from 0.75 s to ~7 s,
and around 20k files it hits the grep timeout.

Thread an optional snapshot through _is_denied_tool_path() and
_can_traverse_tool_path(), and build it once per scan, the way
process_resources already does for its launch-boundary walk. Root
resolution and bound-resource resolution still observe fresh state.
2026-10-07 12:57:40 +01:00
Léo 137daab16e fix(preview): return validator-authored tool errors to the model (#6554)
The compact preview reduces every pre-execution tool error to a fixed
allowlist so exception text cannot reach the client. Messages our own
validators build per call are not on that list, so the model got "The
tool call could not be validated..." instead of the pdf_extract path
hint, the email uid provenance error, the artifact-Python target
message, or which schema argument was wrong. That is the default path
for the tool-profile models, Qwen3.5-9B included.

Each validator site now records its message in a per-call
validator_error before raising, and only that text is returned
verbatim. A schema failure gets a hint rebuilt from the offered schema
and the call's own arguments (missing property, expected type, allowed
values), never from the caught ValidationError. Everything else,
including all execution failures, still goes through
_public_preview_tool_error.
2026-10-07 12:52:39 +01:00
Léo 41cace1337 test(confinement): give user-content carve-out cases stable ids (#6555)
test_allows_user_content_the_app_hands_to_the_model is parametrized on
UPLOAD_DIR and friends, which sit under the per-worker data dir. pytest
used those paths as test ids, so every xdist worker collected different
names and `pytest -n 4` (documented in tests/README.md) aborted at
collection. CI shards with --shard and never saw it.
2026-10-07 12:51:58 +01:00
Léo 10377f0c95 ci: cut per-shard setup time in the pytest matrix (#6557)
Each of the four pytest shards spends ~84 s on setup before pytest
starts, and repeats all of it: pip resolves and installs ~108 packages
(~24 s, even with the pip cache hit), Playwright downloads Chromium and
the headless shell with no cache (~11 s), and three separate
apt-get update calls run.

- Install requirements with uv (astral-sh/setup-uv, pinned) and cache
  its downloads keyed on requirements.txt. uv resolves the same 108
  pins as pip for this requirements.txt.
- Cache ~/.cache/ms-playwright keyed on package-lock.json so a hit
  skips the browser downloads; --with-deps still installs system libs.
- Install FFmpeg and bubblewrap in one apt pass. The containment step
  keeps its bwrap probes unchanged.
- Add --durations=25 so the slowest tests per shard are visible; the
  shard planner only weights the slow marker, and shard times vary
  from 154 s to 296 s within one run.
2026-10-07 13:07:40 +02:00
Alexandre Teixeira 2c8e00ca05 fix(publication): restore project-origin branding and demo assets (#6561)
* chore(publication): restore cleared first-party assets

* fix(branding): restore publication asset integrations

* fix(publication): tighten restoration provenance
2026-10-07 02:08:34 +01:00
Léo ed0c8d877d fix(docs): cite files, not line numbers, in the generated env reference (#6538)
website/configuration-reference.md pinned every ODYSSEUS_* read to a
`path:line`, and test_env_reference fails when the committed page differs from
the generator output. So any change that adds or removes a line above an env
read in any scanned file has to regenerate the page, even when no variable
changed. Since the page landed on 2026-09-30, 24 of the 34 commits touching it
changed nothing but line numbers, and all three open PRs that touch it today do
the same - which also makes them conflict with each other on that file.

The Read in column now names the file, and "+N more" counts other files rather
than other read sites. The page still goes stale, and the test still fails,
when a variable is added, removed, moves to another file, or changes default.
check_notes still reports path:line on stderr, where it is useful and never
committed.
2026-10-07 00:39:19 +02:00
Adam Älgamo 430c2718aa Merge pull request #6532 from Adamact/fix/windows-pwd-import
fix(platform): resolve the service home through platform_compat so native Windows can start
2026-10-07 00:12:27 +02:00
Léo 2cd02da7fc Merge pull request #6503 from odysseus-dev/release/pre-ajax-freeze2
chore(release): publish qualified pre-Ajax migration
2026-10-06 20:14:01 +02:00
Léo ee13ed1eee fix(security): keep the post-external-context approval gate on by default
Request authority admits whole tool families from the user's request, so a
request to read email also admits send_email, delete_email and bulk_email,
and agent processes inherit the host network. With the gate defaulting to
off, an instruction injected through an email or a fetched page reaches those
tools with no other check; dev refuses them today.

Default the gate on, keep ODYSSEUS_TOOL_APPROVAL_GATE=0 as the opt-out, and
pin the production default with a test that imports the module in a fresh
interpreter. Four routing tests written for the opt-out posture now set it
explicitly.
2026-10-06 19:49:15 +02:00
Alexandre Teixeira 8f0a28c05e docs(config): refresh generated environment reference 2026-10-06 18:46:02 +01:00
Alexandre Teixeira dfd1f7e7cb fix(network): honor loopback policy for ipv6 localhost 2026-10-06 18:31:22 +01:00
Alexandre Teixeira 9aa58b218a fix(tasks): recover registered endpoint runtime credentials 2026-10-06 18:31:16 +01:00
Alexandre Teixeira 622738bda7 fix(endpoints): accept registered canonical chat urls 2026-10-06 18:31:13 +01:00
Alexandre Teixeira 82cfd7d69a fix(security): enforce delegated authority in local web fetches 2026-10-06 18:31:08 +01:00
Alexandre Teixeira c7961d178f fix(security): confine workspace existence checks 2026-10-06 15:18:34 +01:00
Alexandre Teixeira ee48c9c51e fix(security): eliminate induced regex denial-of-service paths 2026-10-06 13:36:01 +01:00
Alexandre Teixeira 2e4ad7c383 docs(config): refresh generated environment reference 2026-10-06 03:40:32 +01:00
Alexandre Teixeira 3d91ad82cb fix(security): harden Python service boundaries 2026-10-06 03:16:54 +01:00
Alexandre Teixeira da3800b662 fix(security): eliminate parser denial-of-service paths 2026-10-06 03:16:53 +01:00
Alexandre Teixeira ab6f52d30c fix(security): harden host bridge request boundaries 2026-10-06 03:16:53 +01:00
Alexandre Teixeira f2b72e8a9a test(security): strengthen browser boundary regressions 2026-10-06 03:16:53 +01:00
Alexandre Teixeira 61b63c9ce3 fix(security): isolate session cost ledger keys
Use Map-backed cost ledgers so externally derived session and run identifiers never cross ordinary object prototype semantics. Preserve the existing JSON storage format and extend browser and isolated ledger regressions for replay, overflow, legacy data, and reserved keys.
2026-10-06 00:25:24 +01:00
Alexandre Teixeira 232249eb09 fix(security): harden browser security boundaries
Reject unsafe metric ledger keys, keep email HTML inspection inert, and construct gallery thumbnails structurally. Add adversarial browser regressions for the remaining CodeQL security boundaries.
2026-10-05 23:48:14 +01:00
Alexandre Teixeira 0d97651686 fix(security): avoid SVG title DOM reparsing
Extract strict text-only SVG titles without reparsing model output as DOM, preserving sandboxed SVG rendering and safe accessibility labels.
2026-10-05 22:33:25 +01:00
Alexandre Teixeira 9ee614e2ac fix(security): enforce registered endpoint authority
Require caller-supplied model endpoints to resolve through enabled owner-visible registrations, harden session path encoding, and remove the SVG title HTML parsing sink.
2026-10-05 22:24:15 +01:00
Alexandre Teixeira 481726acf2 fix(security): address CodeQL findings in migration candidate 2026-10-05 20:48:12 +01:00
Alexandre Teixeira 851d3dcea2 test(ci): stabilize public CI shard validation 2026-10-05 19:21:50 +01:00
Alexandre Teixeira 2cc4b8a4b1 Merge commit 'refs/phase3/pre-ajax/publication-tip' into integration/pre-ajax-release
# Conflicts:
#	routes/chat_routes.py
#	routes/session_routes.py
#	src/agent_loop.py
#	src/agent_tools/filesystem_tools.py
#	src/teacher_escalation.py
#	src/tool_capabilities.py
#	src/tool_execution.py
#	tests/test_mcp_add_server_args_validation.py
#	tests/test_token_cache_atomic_swap.py
2026-10-05 15:59:59 +01:00
Alexandre Teixeira dab660543b chore(publication): close pre-integration release blockers 2026-10-05 01:37:49 +01:00
Alexandre Teixeira 3d3aee2093 Merge pull request #64 from pewdiepie-archdaemon/integration/wave6-on-wave4
test(wave6): isolate test runtime for opt-in xdist and preserve explicit no-web intent
2026-10-03 05:00:57 +01:00
Alexandre Teixeira 0ab6fc102c docs(env): refresh generated configuration reference
Regenerate website/configuration-reference.md with
scripts/generate_env_reference.py. The negative-web correction in
96e82562 inserted five lines in src/agent_loop.py ahead of the
ODYSSEUS_MAX_VISUAL_EVIDENCE_IMAGES and _FRAMES reads, so their recorded
locations move from 15329/15361 to 15334/15366. No variable, default or
description changed.
2026-10-03 04:47:25 +01:00
Alexandre Teixeira 80adeda937 fix(agent): honor explicit no-web requests 2026-10-03 04:02:59 +01:00
Alexandre Teixeira 18996588ff docs(tests): record Wave 6 parallel test measurements
Document opt-in local workers and the per-process runtime ownership model.
Record the two parallel-only failures found and fixed in test
infrastructure. Record the measured results on the final code: serial
oracle 496.3s, -n 2 267.6s (1.85x), and two green -n 4 runs at 155.6s mean
(3.19x), all with identical skip and xfail sets and no leaked processes,
listeners, state, or runtime roots. Recommend -n 4 locally and explain
why -n auto was not run. The full serial run remains the release oracle.
2026-10-03 03:46:53 +01:00
Alexandre Teixeira 77b61c222e test: serve browser assets without head-of-line blocking
The shared static server handled one connection at a time. Chromium can
open a speculative connection and never send a request, so every queued
request waited behind it. Under parallel load a computed-style capture's
navigation stalled for 30s and failed. Under CPU saturation, 4 of 12
captures stalled for about 29s each.

Serve each connection on a daemon thread. The existing serve-this-worktree
test now holds a silent connection open while it fetches, and times out
against the serial server. The configuration reference's recorded source
lines are unchanged.
2026-10-03 03:46:52 +01:00
Alexandre Teixeira 256beebb3d test: keep pytest basetemp within the AF_UNIX path limit
Moving TMPDIR into the private runtime root left pytest's default
<TMPDIR>/pytest-of-<user>/pytest-<n> beneath it. With xdist's popen-gw<n>
the real-tmux witness bound a 110-byte socket path, over Linux's 107-byte
sun_path limit, so it failed under every worker count while passing
serially.

The controller now roots basetemp at the private root's pytest directory;
xdist hands workers popen-gw<n> beneath it. An explicit --basetemp wins.
A tmux-independent witness binds a socket at the same path budget.
2026-10-03 03:46:52 +01:00
Alexandre Teixeira e1bc13b634 test: retain ownership of sockets and subprocess groups 2026-10-03 03:46:52 +01:00
Alexandre Teixeira 6eb0bbfe70 test: isolate pytest runtime defaults across workers and runs 2026-10-03 03:46:52 +01:00
Alexandre Teixeira a52c657150 test(web): repair negative security witnesses 2026-10-03 03:46:52 +01:00
Alexandre Teixeira decfab12f9 fix(tests): preserve bootstrap reference locations 2026-10-03 03:46:52 +01:00
Alexandre Teixeira 9fd6919ee9 fix(tests): isolate database and module state 2026-10-03 03:46:52 +01:00
Alexandre Teixeira 3468ad36d7 Merge pull request #62 from pewdiepie-archdaemon/feature/effects-provenance-wave4
feat(runtime): add durable effect provenance and truthful completion
2026-10-03 03:10:58 +01:00
Alexandre Teixeira 7563d859bc fix(effects): close independent review correctness gaps 2026-10-03 02:55:31 +01:00
Alexandre Teixeira da4bf3531f Merge frozen lab b1666951 (Wave 3) into Wave 4 effects provenance
Integrates the merged and frozen Wave 3 lab commit
b1666951faf8285054e1ca90f11533b0fb53fb57 with a normal merge, preserving
every Wave 4 commit unchanged.

Conflict: src/agent_runtime/resources.py. Wave 3's _control_plane_snapshot()
/ _control_plane_path(path, *, snapshot=None) split is kept. The snapshot adds
the effect-store directories to its prefix set after the recursive job-dir
inventory and no longer references path (the auto-merged prefix check would
have raised NameError there). _control_plane_path calls _aliases_effect_store
after its os.stat, only for multiply linked files, so single-link files never
list the store.

Semantic reconciliation (no textual conflict): bg_monitor keeps launch
settlement right after the first successful validate_job and before the
authority check, with Wave 3's post-drain revalidation intact. The
deleted-session branch, terminal before linkage validation, now settles a
validated launch too: that job is later pruned and its publication retired,
which would otherwise leave its effect RUNNING. Regression tests cover the
snapshot form of the effect-store check and both deleted-session linkage
outcomes.
2026-10-03 01:13:36 +01:00
Alexandre Teixeira 3e43809ed6 docs(effects): record corrective pass and Wave 3 rebase checklist 2026-10-03 01:00:18 +01:00
Alexandre Teixeira 4d07e2da2d test(effects): close Wave 4 adversarial regressions
Real-seam coverage for each corrective fix, each checked by mutation:
requested edit/patch states (CRLF-exact, unrelated change contradicts,
partial read and underivable targets stay unverified, superseded effects are
history); directory and launch-index fsync order observed via real fsync
targets; dispatch refused when the directory fsync fails; independent
objects, threads and processes never reuse positions; settle-once and
recovery against another writer; torn-tail repair; unbound tools cannot
manufacture RUNNING/cleanup/facts or settle launches; external effects never
complete as satisfied, are always disclosed, and passing tests stay test
facts; verifier staleness and RUNNING launches without obligations;
known-scope child effects leave unrelated parent evidence fresh; browser page
refusal survives a matching approval and child authority with no claim, no
execution id and no producer call; effect-store hardlinks are caught without
scanning the store.

Replaces the uncommitted tests that asserted a CONTENT_CHANGED predicate and
blocking on any RUNNING effect.
2026-10-03 00:58:32 +01:00
Alexandre Teixeira 7267341d49 fix(effects): protect provenance control state efficiently
A hardlink into the effect store was protected only by the log's own nlink
refusal, which an agent could undo by removing the alias after writing
through it. Adding the store to the recursive control-plane inventory would
make every path check cost grow with accumulated runs. _aliases_effect_store
instead uses the store's invariants: logs and launch indexes refuse
st_nlink != 1 and the store is flat, so only a multiply linked regular file
on the store's device is compared by inode against one non-recursive listing.
Single-link files cost nothing and the store is never rglob-inventoried. The
helper takes a stat result so it plugs into Wave 3's scan-local snapshot after
the rebase.
2026-10-03 00:58:32 +01:00
Alexandre Teixeira b23c6d40b3 fix(effects): require evidence for external completion claims
Effect obligations were consulted only for declared artifacts, and reported
external success could be presented as done. Now, regardless of declared
artifacts:

- the latest effect on any changed file contradicted by a fresh readback
  fails the run (a superseded earlier effect is history, not a contradiction);
- a passing verifier followed by an effect that may have changed state
  without settled evidence is stale (BLOCKED);
- executed external effects that are not VERIFIED cap the decision at
  UNVERIFIED, and the answer always carries server-authored facts for them
  ("reported success; any external change it made was not independently
  verified", "reported failure", "unknown outcome").

The disclosure is structural and does not depend on recognizing the model's
wording. When it is the only change, the model's answer events are released
unchanged and the disclosure follows as one delta (and in round_texts).
Prose filtering is also tightened (remote verbs are mutation claims, an
unnamed "I updated it" cannot borrow the single required artifact, bare
"Done." is a terminal claim beside unverified external effects). A passing
verifier still supports test claims; it never speaks for the external effect.

Replaces the uncommitted attempt that blocked every run with any RUNNING
effect: a background launch with no declared obligations completes
UNVERIFIED.
2026-10-03 00:58:32 +01:00
Alexandre Teixeira 682b44a3ec fix(effects): preserve producer trust boundaries
Result-dictionary keys could set lifecycle state for any producer: a dynamic
or registry tool returning bg_job_id/detached became RUNNING, teardown became
verified cleanup, and timed_out/failure_kind/mutation_attempted/containment
were copied from untrusted results. Facts are now scoped to the producer the
dispatcher actually bound. An unbound tool contributes its exit status alone.
RUNNING requires a bound process producer (and an exact launch reservation
for bg_job_id), cleanup is attested only by a bound process producer, and job
observations and launch settlement only by a bound manage_bg_jobs operation
on exactly one Wave 3-validated job. External/remote-acknowledged facts come
from the captured ExternalResource, not from the result.
2026-10-03 00:58:32 +01:00