Commit Graph
114 Commits
Author SHA1 Message Date
Alexandre Teixeira 57fe9946c2 refactor(runtime): one compact-runtime selection rule for route and dispatch
The chat route repeated the compact (clean v3) eligibility decision inline
to prepare the turn's context resolution, while the agent loop dispatched
on the contract stamp set by a separate, later condition. The two could
drift, and already disagreed for a user whose privileges demote the turn
to plain chat: the route prepared a compact resolution that no compact
runtime used.

src/agent_runtime/runtime_selection.py (no imports) now owns the rule:

- uses_compact_preview_runtime(): clean route requested, contract policy
  enabled, agent mode, agent permitted, not an image generation session.
- is_compact_preview_contract() and COMPACT_PREVIEW_MODE for the stamp.

The route evaluates the rule once, before context preparation, where all
of its facts are final (the agent privilege is read through the same
_request_privileges helper the later enforcement uses). That one value
gates the typed context resolution and is the _clean_v3_preview flag that
stamps the contract; inside the agent-contract branch it equals the
previous condition, so stamping behavior is unchanged. The agent loop
dispatches through is_compact_preview_contract(), and the compact runtime's
MODE is the shared constant.

A route-level matrix drives the real agent loop and asserts that route
preparation and compact dispatch agree for compact, escalated, configured
compact/full, regular, TUI, privilege-denied and image-generation turns.
2026-10-01 22:46:08 +01:00
Alexandre Teixeira 0054557027 fix(runtime): resolve compact-turn context once at the chat route
The first checkpoint removed terminal-metrics discovery, but a normal
compact chat turn still ran two context systems: build_chat_context's
legacy untyped lookup (directly or inside maybe_compact) and the typed
resolver inside stream_preview.

Resolve the typed ContextResolution once, at the chat route, before
build_chat_context, using the session's provider credentials. The
predicate mirrors _clean_v3_preview; every input it needs is known at
that point and the native-workspace term cannot veto a requested clean
route. The same object then:

- sizes legacy history shaping in build_chat_context through a new
  maybe_compact(context_length=...) override, so no legacy probe runs;
  an unknown window still shapes with DEFAULT_CONTEXT but gains no
  provenance;
- crosses stream_agent_loop (one new parameter, forwarded only at the
  compact dispatch) into stream_preview, which reuses it and probes only
  for callers that arrive without one or with one bound to another
  route.

ContextResolution now records the endpoint and model it describes
(endpoint URL excluded from repr and metrics). The bare legacy
context_length is never converted into typed evidence.

Credential scoping: origins compare with default ports normalized, an
empty host is never trusted, and the probe client never follows
redirects. Tests cover the configured origin, the server-resolved
Tailscale form, scheme/port/lookalike/userinfo/path origins, redirects,
and secret-free errors, logs and metrics.

The conftest guard now replaces only the resolver's I/O edges (HTTP
client and DNS-capable URL building) instead of the whole probe, and
exposes a context_probe_ledger fixture, so route integration tests run
the real resolver offline and can count metadata requests.
2026-10-01 22:31:21 +01:00
Alexandre Teixeira 837fbfd0ea feat(runtime): resolve compact-runtime context window at turn preparation
The compact (clean v3) runtime had no effective context window: it learned a
limit only reactively from a provider 400/413 and its terminal metrics carried
no context_length. PR #41 addressed the reporting gap by probing provider
metadata between the last model byte and [DONE], unauthenticated, and folded
known-table and endpoint evidence into one "known" flag.

Resolve the window once, before the first model request, instead:

- src/agent_runtime/context_resolution.py adds a typed ContextResolution
  (effective value, evidence class, source, all observations, conflicts,
  provider_io, cached, secret-free probe errors). Evidence classes stay
  distinct: runtime_confirmed (llama.cpp /slots, /props, or a limit the
  provider stated this turn), provider_advertised (models catalog),
  operator_declared (client_runtime_context.model_context_window),
  known_table, unknown (0, never a default).
- Selection is deterministic: runtime beats provider beats table; an
  operator declaration caps measured evidence and replaces weaker evidence.
  Disagreements are recorded as conflicts; a declaration below a measured
  value is a cap, above it a contradiction.
- The provider probe forwards the turn's credentials only to the provider's
  own origin, runs URL resolution off the event loop, is bounded by one
  deadline, never raises, and caches remote results per credential
  fingerprint (shorter TTL for failures; local servers are re-probed).
- stream_preview resolves at preparation (or accepts a supplied resolution),
  seeds the proactive trim budget from it when evidence is not unknown, and
  terminal metrics report only the stored resolution plus any limit the
  provider stated during the turn. Metrics perform no discovery.

src/agent_loop.py and the regular runtime's legacy model_context probe are
unchanged. A conftest guard keeps tests that drive the compact runtime with
placeholder endpoints from performing real DNS/HTTP lookups.
2026-10-01 21:59:53 +01:00
Alexandre Teixeira 9d0257134f feat(runtime): enforce server request authority 2026-10-01 18:35:41 +01:00
Alexandre Teixeira f74a262f73 merge: reconcile PR 40 with current lab
Integrate lab fff55a78 into PR #40 (cc25d5ba). Lab's modular email
backend/frontend, modular settings, split stylesheets (static/style.css
stays deleted), procfs compatibility, and request-scoped TurnContract
authority win; PR #40's routing classifiers, editor/email/task features,
and style.css changes are ported into lab's module and stylesheet homes.

Integration fixes:
- settings/api.js imports ui.js under its canonical versioned URL
- browser observations keep legacy CAPTCHA/access-block evidence
- artifact turns do not re-trigger broad-web research recovery
- env reference documents PR test-tool variables; page regenerated

PR #40 defects surfaced by lab gates and fixed here:
- web_fetch generic schema drops top-level anyOf (OpenAI contract);
  the compact preview contract still requires url or urls
- get_weather registered as a brokered network read
- new lazy editor modules precached for offline use
- SearXNG pin mirrored into GPU standalone compose files
- image model picker again skips offline endpoints

Tests updated where PR #40 changed behaviour on purpose, and PR tests
moved onto lab's document_source helpers.
2026-10-01 05:03:58 +01:00
pewdiepie-archdaemon 2e8413a54a Preserve preview harness, editor, email and task improvements
Snapshot current maintainer-preview application changes and regression fixtures for integration into lab. Excludes local runtime data, evaluation outputs and source backups. Focused Python regression selection: 140 passed; full suite not certified.
2026-10-01 01:34:26 +00:00
pewdiepie-archdaemon 86f376ac3a Show provider failures as inline chat stream errors 2026-09-23 01:13:46 +00:00
Alexandre Teixeira 822ceaaac4 fix(ci): make maintainer harness contract self-contained and portable 2026-09-22 11:31:45 +01:00
pewdiepie-archdaemon 297ad19248 Harden maintainer-preview harness and review fixes
Unify conversational domain routing, preserve artifact completion evidence, replace provisional tool-round prose with terminal synthesis, and resolve verified maintainer review findings across search, frontend module identity, path policy, configuration, and built-in skill startup.
2026-09-21 06:54:03 +00:00
pewdiepie-archdaemon d7cad0621f reserve wall time for artifact completion 2026-09-19 12:45:09 +00:00
pewdiepie-archdaemon efe8dbeab3 preserve research tools through artifact completion 2026-09-19 09:24:22 +00:00
pewdiepie-archdaemon 3f9ff9d580 trust runtime materialization evidence 2026-09-19 02:44:36 +00:00
pewdiepie-archdaemon e0c21b28d5 validate executable artifact completion code 2026-09-19 02:33:33 +00:00
pewdiepie-archdaemon f5e3119b10 bind directory completion to output descendants 2026-09-19 02:25:27 +00:00
pewdiepie-archdaemon 27affcdb58 use native python for directory artifact completion 2026-09-19 02:14:13 +00:00
pewdiepie-archdaemon b4cd39657d recover mixed artifact tool payloads 2026-09-19 02:07:04 +00:00
pewdiepie-archdaemon 2308ff9b80 recover concatenated artifact writes 2026-09-19 01:53:12 +00:00
pewdiepie-archdaemon b32fa31b37 bound malformed artifact recovery loops 2026-09-19 01:37:46 +00:00
pewdiepie-archdaemon fbaa184a7b recover required artifacts after tool suppression 2026-09-19 00:28:08 +00:00
pewdiepie-archdaemon 75b2420239 constrain directory completion to child files 2026-09-18 20:51:04 +00:00
pewdiepie-archdaemon ceb79d072a handle directory artifact completion safely 2026-09-18 20:43:51 +00:00
pewdiepie-archdaemon 0865e0e8da require content in directory artifact outputs 2026-09-18 20:17:19 +00:00
pewdiepie-archdaemon 27e53e857c recover boundedly from action-only replies 2026-09-18 18:22:34 +00:00
pewdiepie-archdaemon d550bc0e74 bind binary completion code to required path 2026-09-18 18:16:12 +00:00
pewdiepie-archdaemon 7b5288f097 route binary artifact completion through Python 2026-09-18 18:08:32 +00:00
pewdiepie-archdaemon 43e50185f9 normalize named tool choice for Kimi thinking mode 2026-09-18 17:00:54 +00:00
pewdiepie-archdaemon 3985172885 recover empty artifact writer turns through body handoff 2026-09-18 16:33:30 +00:00
pewdiepie-archdaemon 629bd32d03 preserve output budget for artifact body recovery 2026-09-18 16:29:04 +00:00
pewdiepie-archdaemon a394ea25d3 drop provider-invalid reasoning-only history turns 2026-09-18 16:22:59 +00:00
pewdiepie-archdaemon 508e017d89 preserve DeepSeek reasoning across clean tool rounds 2026-09-18 16:16:09 +00:00
pewdiepie-archdaemon a453b71651 count artifact handoff once per response batch 2026-09-18 16:10:02 +00:00
pewdiepie-archdaemon 60de3b951f retry invalid artifact body immediately 2026-09-18 16:07:34 +00:00
pewdiepie-archdaemon a09acc43a6 retry bounded artifact body handoff 2026-09-18 16:02:26 +00:00
pewdiepie-archdaemon 3443b706a5 recover artifact body after repeated off-contract calls 2026-09-18 15:56:17 +00:00
pewdiepie-archdaemon afbf8cc266 bind artifact completion to required output path 2026-09-18 15:47:13 +00:00
pewdiepie-archdaemon 50a86bc650 reject off-contract calls during artifact completion 2026-09-18 15:37:49 +00:00
pewdiepie-archdaemon dff88f4fb0 preserve artifact request contract in native traces 2026-09-18 15:31:57 +00:00
pewdiepie-archdaemon afbab148f2 trace artifact phase provider contract 2026-09-18 15:27:11 +00:00
pewdiepie-archdaemon a46b742515 expose artifact phase state in agent steps 2026-09-18 15:23:12 +00:00
pewdiepie-archdaemon 26f387e719 fix repeated invalid tool argument loops 2026-09-18 14:59:34 +00:00
pewdiepie-archdaemon e220a14895 expose required artifacts in turn audit 2026-09-18 14:58:57 +00:00
pewdiepie-archdaemon 2f42c7fe2f fix repeated equivalent search loops 2026-09-18 14:57:10 +00:00
pewdiepie-archdaemon 54ae8e1a0c fix repeated successful evidence call loops 2026-09-18 14:52:42 +00:00
pewdiepie-archdaemon 99b18469f6 fix bounded recovery after repeated failed calls 2026-09-18 14:44:13 +00:00
pewdiepie-archdaemon 9e505ef341 fix distinct evidence retries after duplicate calls 2026-09-18 14:32:41 +00:00
pewdiepie-archdaemon 7b79117fbf fix(agent): reserve artifact budget after scratch writes 2026-09-18 14:29:59 +00:00
pewdiepie-archdaemon 225194bac3 fix(routing): keep media review out of editor and web paths 2026-09-18 14:16:58 +00:00
pewdiepie-archdaemon 9e72d8ef75 fix(agent): infer outputs from empty runner contract 2026-09-18 14:09:10 +00:00
pewdiepie-archdaemon fb9558439c fix(agent): preserve tool evidence through final synthesis 2026-09-18 13:29:54 +00:00
pewdiepie-archdaemon 951060e4d4 Unify compact runtime core tools with shared contract inventory 2026-09-18 05:43:20 +00:00