Skip to content

Release/1.26.0 - #1424

Merged
philmerrell merged 3256 commits into
mainfrom
release/1.26.0
Oct 3, 2026
Merged

philmerrell merged 3256 commits into
mainfrom
release/1.26.0

Conversation

@philmerrell

@philmerrell philmerrell commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Release 1.26.0

The first token arrives sooner. The turn path is now mapped and timed end to end, and the largest stages we own are off the critical path. Dev figures:

  • cold agent build: 869 → 372ms
  • per-turn history count: 388 → 0ms on long conversations
  • external MCP servers pre-flight concurrently
  • the knowledge-base search runs alongside the agent build
  • the long-term-memory lookup overlaps the message writes

Also in this release:

  • Voice: priced per modality, and users can choose the Nova 2 Sonic voice and microphone.
  • Models: Claude Opus 5.5, GPT-6 Sol, GPT-6 Luna and GPT-5.5 join the catalog.
  • Managed KBs: imports count against the byte caps, and changed synced files are re-ingested.
  • Testing: a turn-path smoke and regression pass now runs nightly.
  • Dependencies: Strands 1.57.2 with bedrock-agentcore 1.24.0.

Full write-up: RELEASE_NOTES.md (v1.26.0) and CHANGELOG.md.

Pre-merge checks

  • GSI update limit: check-gsi-update-limit.mjs PASSED. 29 tables compared, and no existing table needs more than one GSI operation. There are no index changes at all.
  • Backfills: check-pending-backfills.mjs found no backfill_*.py added in this range.
  • Version sync: sync-version.sh --check PASS. The lockfile diffs change only the version.
  • Smoke and regression pass on dev: run by Phil after perf(kb): read the KB record once per search, on a cached table #1416 deployed, all green.
  • Nightly: 2026-10-03 run green.

Operator steps (also in the Deployment notes)

  1. CDK deploy (platform.yml → backend.yml → frontend-deploy.yml). The only infrastructure change is new widgets on the turn-latency dashboard.
  2. Add the Nova 2 Sonic catalog row in each environment (Admin → Models → catalog). Until it exists, voice stays unmetered.
  3. Optional: for a managed KB the 1.25.0 repair left for review, run repair_managed_kb_byte_counters.py --settle-unexplained --agent <id>, after the deploy.
  4. Six new default-on rollout kill switches, all runtime-only. They're listed in the notes and tracked for retirement in Retire rollout kill switches once they meet their retirement condition #1422.

CodeQL

  • Fixed: alert 904. The voice agent logged the client-supplied sample_rate, a log-injection risk. Fixed on develop by fix(voice): don't log the client-supplied sample rate #1425 and merged into this branch.
  • Dismissed as false positives, with the reason on each alert: 903 (name heuristic on requires_oauth_provider), 869 (json.dumps escapes CR/LF), 905–912 (Protocol stub bodies) and 891 (import used in quoted annotations).

Behaviour change

After merge

  • Backmerge main → develop as a PR, using a merge commit.
  • Prod follow-ups:
    • add the Nova 2 Sonic row;
    • settle the one KB left from the 1.25.0 repair;
    • confirm OTel "Failed to detach context" drops to 0 per turn;
    • watch first-turn timings on the new dashboard widgets.

🤖 Generated with Claude Code

philmerrell and others added 30 commits September 25, 2026 11:34
Adds backend/scripts/compaction_quality_harness.py and the
compaction_quality package: a seeded corpus of long editing sessions with
planted, exactly-scorable facts (constraint, decision, reference,
superseded), replayed through the production TurnBasedSessionManager under
each arm (full, model_relative, legacy, floor_50) and pace (restore, cold,
warm). Only I/O is stubbed; the cut, the deferred apply, the restore slice,
anchor truncation and bound_summary are the real code.

Steps: cut (free, writes probe-time histories plus a plant-availability
table), records and ask (Bedrock spend, estimate-first, --yes to run, a
cachePoint after the shared history), score (exact match, paired per family
against the full-history control, exact McNemar, n on every row).

The clock stub stamps real time on save and inserts the pace gap only
between turns; backdating every save hid the restore-path missed free
apply, which a tripwire test now pins until it is fixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec §5 gains a status note above the waiver: the harness exists, the
control is full history rather than the kill switch, and the first full run
waits for the missed-free-apply fix. The scoping doc marks slice 1 built,
answers its open questions, and records the aggregate prod readout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every _save_compaction_state stamps updated_at. On a restore,
_apply_compaction advanced the truncation anchor (a save) before the
coordinator called apply_pending_compaction, which then read a ~0s gap and
left a parked cut waiting on a cache that was already cold; it landed only
at the paid hard-ceiling apply, after the session had also paid the anchor
re-write. apply_document_offload had the same defect after any apply that
itself saved.

The restore slice now captures the previous turn's stamp before the anchor
advance (_restore_turn_stamp); apply_pending_compaction consumes it every
turn into _turn_start_stamp, and _document_offload_reason reads that first.
Both stamps are cleared at turn end so an old stamp can never make a warm
turn look cold.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The quality harness's restore pace pinned the missed free apply; with the
turn-start gap fix it applies the parked cut on cache_expired. Spec §5 and
the scoping doc record the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n actions

- kb_migration teardown passes its own 780 s poll window to the delete
  saga. Managed KBs on dev took ~10 minutes to delete, so at the shared
  480 s every teardown needed two worker runs (~30 min). The shared
  default stays 480 s for the reconciler, which deletes several per run.
- Agents page Chat/Edit/Share/Delete icon buttons (grid and list) get
  aria-labels naming the agent; the tooltip only set aria-describedby.
- Kaizen queue: the production orphaned-agent cleanup chore, blocked on
  #1293 and #1301 reaching main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…skills-from-tool-result-offload

fix(compaction): never offload skill instructions from the skills tool
…t-model-text

fix: keep streamed model text out of runtime logs and EMF lines
…ll-and-agent-button-labels

fix: one-run KB teardown, named Agents page actions; kaizen chore for the prod orphan cleanup
…ion-quality-harness

feat(compaction): offline quality-veto harness (slice 1)
…ion-apply-turn-gap

fix(compaction): read the head-of-turn cache gap from before any save
…d Projects 2.3a)

Pure library for the canonical memory-file format (spec §4.2) and the
manifest-aware save checks (§4.3 steps 1-4), plus a bounded CountTokens
counter in apis.shared for save-time token accounting. No callers yet;
2.3b wires these into the save path.

- format.py: system-rendered frontmatter (YAML subset, no new dependency),
  items with ULID anchors, links, aliases, slug rules, reserved MEMORY.md.
- validation.py: locked-field echo rule, name/alias collisions, anchor
  known/unique/minted, link resolution incl. archived targets; only new
  dead links fail.
- tokens.py: one-attempt, 2 s CountTokens with a labelled chars/4
  fallback; MEMORY_TOKEN_COUNT_MODEL_ID="" turns it off (tests do).
- Hypothesis properties for round trips, anchor stability and link
  resolution.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wires the 2.3a format and validation into every Memory Space write path
and adds per-file version history.

- MemorySpaceService.save_entry: validate, count tokens once
  (CountTokens), write the object, conditional manifest swap, then the
  FILEVER row. The swap is the commit point, so version numbers cannot
  collide; replaced objects are kept because history references them.
- fileFormat freeform|canonical on the space, set at create. Existing
  spaces stay freeform (stored as written; warnings only). Canonical
  spaces enforce items, anchors, links, collisions and the 8,000-token
  hard cap; a concurrent save of the same file is a 409.
- Pre-history entries get a baseline version on first replacement.
  delete_entry purges its history (dedup-aware); delete_space pages its
  rows and purges every object; consolidate never collects history.
- MEMORY.md is reserved in the service on every path.
- API: PUT entries returns version/tokens/warnings/anchors; new
  GET /memory/spaces/{id}/history?slug= and /history/{n}?slug=.
- memory_write records reason "save" and no longer sends an empty
  description (tool spec text unchanged, so toolConfig is unchanged).
- app-api task role gains bedrock:CountTokens.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Under AgentCore, ADOT writes every prompt and reply into the runtime log
group's otel-rt-logs stream from two scopes:

- strands.telemetry.tracer: Strands puts messages on span events and
  ADOT's LLOHandler re-emits them as log records. Setting
  OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_unredacted_attributes= turns on
  Strands' redaction with nothing exempt.
- botocore bedrock-runtime: ADOT defaults
  OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT to true with
  setdefault, so the image sets it to false first.

Both are image ENV rather than Runtime variables, because the Runtime's
50-variable cap is nearly spent. A Runtime variable still overrides them.
The new test drives a Strands turn through the real tracer and
LLOHandler, and the botocore event builders, against the Dockerfile's
values. Each case has a capture-on control.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#1314)

Adds the CDK plumbing so the platform self-service flag can be turned on per deployed environment (it was code-only before, readable from os.environ but never set on the runtime).

- config.ts: PlatformSelfServiceConfig + opt-in parse (CDK_PLATFORM_SELF_SERVICE_ENABLED, only literal 'true' enables; mirrors projects).
- inference-agentcore-construct.ts: sets PLATFORM_SELF_SERVICE_ENABLED on the AgentCore Runtime (read only there). 47->48 of 50 env slots; guard test reports 2 free.
- platform.yml: forwards the CDK var from the GitHub environment.
- mock-config.ts: default off.

Default OFF everywhere; prod stays dark unless its own env var is set. Not wired into app-api (it never reads the flag). Verified: tsc clean, env-var-limit + config tests pass (198).
…format-validation

feat(memory): canonical memory-file format and save validation (Shared Projects 2.3a)
…t-capture

fix(observability): keep conversation content out of runtime OTEL logs
…ce type

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- raw_summary arm: the production cut with the summary budget lifted, so
  comparing it with model_relative isolates what bound_summary's Nova Micro
  compression costs, separately from the cut.
- records: --record-words sets the per-record word cap, and --workers runs
  transcripts in parallel. One record per turn at 600 words reproduces
  prod's ~20k-token LTM records at cut time, which is what makes the
  compression run.
- ask: --workers parallelizes the questions on one history after its first
  call has written the cache.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…window (#1319)

The alb-unhealthy-hosts alarm paged on any single App API target failing one health check for 10 min (evaluationPeriods:2). ECS self-heals such a target in ~5 min while the other targets keep serving, so this fired ~daily on benign, zero-impact blips. Require 4 consecutive 5-min periods (20 min) instead. Threshold stays 0 and treatMissingData stays BREACHING, so a stuck target and a total outage both still page. Window-not-threshold per observability.md section 11.
…documents

Agent icons live in the RAG documents bucket at
assistants/{id}/icons/{digest}.{ext}. The legacy ingestion parser read that
4-part key as document_id="icons" and left a failed DOC#icons row on the
agent. Both ingestion paths now parse strictly and skip (info log, success,
no row written) anything that is not assistants/{id}/documents/{docId}/{file}.
The managed-KB EventBridge rule is narrowed to assistants/*/documents/*.

Adds backend/scripts/cleanup_stray_doc_rows.py (report-only by default) to
remove the stray rows already written on live agents.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ~1,300 retrieval failure lines in the production runtime log are 745
events (each logged twice) and none is a throttle. 476 turns lost
retrieval to dead pooled connections on cached agents after ~6 min idle,
masked by a handler bug that discards every namespace's results; 84 more
sent a query over the 10,000-character limit. Documents the evidence and
a recommended fix (not implemented).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The daily reconciler snapshots every KB_Record and then walks AWS. A teardown
that finished in between left the run holding a record whose knowledge base
was gone, and mark_vector_state_missing's unconditional UpdateItem recreated
it as a ghost KB# item holding only vectorState/updatedAt. That's the orphaned
row the teardown exists to remove. refresh_stored_bytes had the same upsert
hazard, and both run in report-only mode too.

- records.update_if_present: an update_item guarded on attribute_exists(PK)
  that returns False (logged at info) instead of creating a removed record.
- reconciler: both record-side writes go through it and are only counted
  when they land. Records in migrationState=teardown are neither marked
  missing nor refreshed, and are listed in ReconcileReport.tearing_down
  (tearingDown in the serialized report).
- Same guard on the other unconditional KB# writes that could outlive a
  teardown: set_resource_policy_state (both branches; REMOVE-only upserts
  too), byte_cap commit/release/reserve (reserve tells "record gone" apart
  from "over the cap" via ReturnValuesOnConditionCheckFailure), and the
  worker's _set_retain_until and _record_progress.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
appTooltip only sets aria-describedby, so the icon-only buttons on the
connector list and form were announced as just "button" (axe button-name,
critical). Add aria-labels following the Agents page pattern: row actions
name their connector ("Delete Example Drive"), the secret toggle names its
current action, and the callback-URL copy buttons say what they copy. Also
names the row Edit link (same defect, axe link-name) and adds type="button"
where missing. Specs assert every icon-only control has an accessible name.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ion fails

Spec §5's waiver is replaced by the first full harness result (Haiku 4.5, 12
transcripts x 9 planted facts, k=3, prod-sized LTM-style records). The
model-relative cut with an uncompressed summary matches the full history;
the same cut with bound_summary's Nova Micro compression (~15k -> ~730
tokens, reproducing prod's ~20k -> ~760) loses standing instructions
(1.00 -> 0.72, p=0.002) and exact identifiers (0.96 -> 0.58, p=0.004).
The tuning rule's FLOOR_RATIO lever is scoped to retained-turn loss. The
scoping doc's §8 records method, spend (~$16) and the candidate levers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…save-pipeline

feat(memory): save pipeline and FILEVER history (Shared Projects 2.3b)
…ingestion-skip

fix(ingestion): skip agent icon uploads instead of ingesting them as documents
…-ups

Adds a "Dev-validated 2026-09-25" entry to the 2.3b as-built notes with
the observed numbers (counted tokens, versions, rejections, purge), and a
"Carried from 2.3" list under 2.4: canonical project spaces, the
anchor-stripping decision for injected memory, the counter cold start,
and the deferred items.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1325)

The platform self-service set_default_model tool calls UserSettingsRepository.update_settings (PutItem + conditional UpdateItem), but the inference/AgentCore runtime IAM role granted only GetItem on the user-settings table. The write AccessDenied'd and the tool swallowed it into a generic error.

- inference-api-iam-roles.ts: broaden the user-settings grant to GetItem + PutItem + UpdateItem (renamed sid to UserSettingsTableReadWriteAccess), scoped to the one table ARN, no DeleteItem, no wildcard.
- security-policy.test.ts: update the regression guard to assert read+write (no delete, no wildcard).
- account_tools.py: set_default_model now surfaces the real error type (e.g. AccessDenied) instead of a generic 'try again', so a hidden infra gap is diagnosable from the tool result.
Arm gains an optional summarizer with bound_summary's signature, patched
into turn_based_session_manager for that arm only and restored after, so a
candidate runs behind the production cut. summarizers.py adds two
prototypes:
- compress_only: production's prompt, temperature only. Production's
  compress_with_model also sends topP, which Claude 4.5+ rejects.
- extract_then_compress: a verbatim pinned block of instructions,
  decisions, identifiers and changed values, then the narrative compressed
  into the rest of the budget.

New arms: nova2lite_compress (production code, other model id),
haiku_compress, extract_nova_micro, extract_nova2lite and extract_haiku.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
philmerrell and others added 20 commits October 2, 2026 11:20
The agent-binding rules ask whether a thread already has messages, on an
agent conversation's first turn and on every @-mention, before the stream
opens. `_session_has_messages` answered with get_messages(limit=1): a full
history read plus metadata, interrupts, UI resources and tool summaries, to
keep one message — ~540ms on a new conversation on dev, growing with
history — and constructing the Memory session manager behind it wrote a
SESSION event into sessions that had none.

`session_has_messages` is now one ListEvents: maxResults=1, no payloads,
filtered server-side to events without the SDK's reserved `stateType` key
(its SESSION/AGENT records carry it; messages never do). 91ms median on
dev, same answer as the old semantics on 42 sampled conversations and on all
14 that hold only a SESSION record. Fails open on a failed read, as the old
path effectively did.

Also records the #1411 (KB search ahead of the build) dev readout in the
turn-path spec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-turn-smoke

ci(nightly): run the turn-path smoke matrix after the E2E step
The nightly stack never runs the bootstrap data seeding, so its default role
grants no tools and the turn-smoke rows for calculator and ask_user_question
could only fail. seed-e2e-users.sh now puts the regular E2E user in a Cognito
group (e2e-users) and seeds an e2e_user app role mapped to it through the
shared AppRoleRepository (backend/scripts/seed_e2e_role.py), so the
DEFINITION, JWT_MAPPING, TOOL_GRANT and MODEL_GRANT rows the resolver reads
land together and effective_permissions mirrors the grants. Idempotent:
create on first run, update after. The uv setup moves ahead of the E2E step
so the seed can run inside e2e-test.sh.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…-messages-existence-check

perf(agents): make the binding history check an existence check
#1411 overlapped an agent turn's knowledge-base search with the agent build,
but two DynamoDB reads still ran on the event loop after the search returned
— the document-status filter and resolve_context_cap's record read — so they
waited for a cold build to release the loop: ~120ms of residual rag_wait on
every agent first turn on dev, classic and managed alike.

The facade now runs the backend search and the status filter together on one
worker thread with a private loop (_search_then_filter); everything that
schedules onto the caller's loop (dual-read observational read, observation,
activity touch) stays on it, and legacy_ms still times the search alone. The
context cap is read on a worker started alongside the search. What reaches
the model is unchanged.

test_kb_dual_read's fail-closed case asserted the managed read never
*started*, which held only because the stub legacy backend never yielded; it
now asserts the read is cancelled and never finishes (mutation-checked).

Also records the #1413 and managed-KB dev readouts in the turn-path spec.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…arch-off-loop

perf(rag): keep the KB search's follow-up reads off the event loop
A managed agent's follow-up turn spent ~896ms in the knowledge base search
(rag_wait 786ms of a 1254ms turn_prelude on dev). The Runtime's botocore
spans split it as Retrieve 660ms plus ~230ms of our own DynamoDB: the
KB_Record was read three times (load_record, ManagedKbBackend._locate,
resolve_context_cap) and the document statuses once more, each on a fresh
boto3.resource paying ~45-55ms for its first request against ~4ms reused.

- The facade reads the record once and passes it across the seam
  (search(..., record=)); the managed backend takes awsKbId from it and
  falls back to its own lookup when the record has none.
- search_assistant_knowledgebase_with_cap returns the engine's context cap
  with the results, decided from the same record; the inference route uses
  it instead of reading the record again. The augmented message is
  unchanged.
- records._table() and the status lookup use the process-cached
  aws_clients table on one shared connection pool. The kb-migration,
  kb-sync and rag-ingestion images now ship aws_clients.py (and hash it).
- A root conftest fixture resets the aws_clients cache around every test;
  Hypothesis tests that patch boto3.resource per example isolate the cache
  per example.

Expected: ~215ms off a managed follow-up's rag_wait (~150ms on classic),
and first-turn rag_wait ~120ms -> ~10ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1415)

#1415 moved the search and the status filter onto a worker thread and read
the context cap on a second worker. This branch reads the KB_Record once and
returns the cap with the results, so the cap worker is removed and the record
is passed through _search_then_filter to backend.search. The off-loop test's
two cap-worker cases are replaced by the new contract: the route takes the
returned cap and never reads it again, and a failed search still fails open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
reviews/2026-09-25.md and reviews/2026-10-02.md both recommended these
and drafted them verbatim; decisions.md had not changed since 09-21.

- Declined as kaizen items: docling #405 and Guardrails #480. Both
  issues stay open as product backlog; the docling bump alone remains
  welcome as a PR-sized slice.
- Declined: the standing "do derived execution contexts re-evaluate
  RBAC" audit. Re-open on a named context with the check it skips.
- Accepted: bedrock-agentcore #629 (TracerProvider not flushed before
  microVM freeze, last-turn telemetry under-reports).
- Declined as scoped: reversing the Astra 272K cap. The cap is
  load-bearing pricing until CuratedModel carries a per-tier rate.

review-queue.md: the Astra, docling and two Guardrails entries move
from Open to Resolved. The RBAC audit and #629 had no entry of their
own, so nothing else moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sions-2026-10-03

chore(kaizen): log the four decisions carried since the 09-25 review
…single-record-read

perf(kb): read the KB record once per search, on a cached table
One KB_Record read per search at ~4ms, the status filter at ~4ms per
document, no cap read: ~180ms of DynamoDB around Retrieve is now ~20ms.
Normalised by Retrieve, a managed follow-up's rag_wait lost ~100ms against
#1415; it is now the managed Retrieve itself. Stored augmented messages are
byte-identical to the pre-change conversations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…read-readout

docs(specs): record the KB single-read readout on dev (#1416)
Spec for "Rewind to here" and "Fork from here" on user messages, written
around the prompt-cache question: when a cut reuses cached history, why a
warm rewind is cache-safe while a fork (a cold rebuild) is best-effort, and
the storage, compaction and observability rules that follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Default-on flags come in two kinds and only one is permanent. A feature
switch turns off a capability a deployment may not want; a rollout switch
guards a change meant to be invisible and exists only for a fast undo.
Rollout switches now carry a retirement condition (default: one prod
release plus two weeks clean) and are removed in a per-release cleanup
with a CHANGELOG Removed entry.

The flag reference gains a Kind column that classifies every runtime-only
flag, plus the two that were missing from it
(INLINE_ATTACHMENT_PERSIST_ENABLED, COMPACTION_SUMMARY_EXTRACT_ENABLED).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…h-retirement

docs(flags): feature switches stay, rollout switches retire
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ation-rewind-fork-spec

docs(specs): conversation rewind and fork
The first token arrives sooner: the turn path is mapped and timed end to end, and the largest stages we own are off the critical path (cold agent build 869 -> 372ms, the per-turn history count 388 -> 0ms on long conversations, concurrent MCP pre-flight, the knowledge-base search overlapped with the build, the long-term-memory lookup overlapped with the message writes). Voice is priced per modality and users can choose the Nova 2 Sonic voice and microphone. Claude Opus 5.5, GPT-6 Sol, GPT-6 Luna and GPT-5.5 join the catalog. Managed KBs cap imports and re-ingest changed synced files. A turn-path smoke and regression pass runs nightly. Strands 1.57.2 with bedrock-agentcore 1.24.0.

- CDK deploy required (turn-latency dashboard widgets only); no GSI changes, no backfill
- Operator step: add the Nova 2 Sonic catalog row per environment, or voice stays unmetered
- Optional: repair_managed_kb_byte_counters.py --settle-unexplained for a KB the 1.25.0 repair left for review
- Six new default-on rollout kill switches, tracked for retirement in #1422

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@philmerrell
philmerrell requested a review from a team October 3, 2026 15:45
Comment thread backend/src/agents/main_agent/integrations/external_mcp_client.py Dismissed
Comment thread backend/src/agents/main_agent/voice_agent.py Fixed
Comment thread backend/scripts/smoke_turns.py Dismissed
Comment thread backend/scripts/smoke_turns.py Dismissed
Comment thread backend/scripts/smoke_turns.py Dismissed
Comment thread backend/scripts/smoke_turns.py Dismissed
Comment thread backend/scripts/smoke_turns.py Dismissed
Comment thread backend/scripts/smoke_turns.py Dismissed
Comment thread backend/scripts/smoke_turns.py Dismissed
Comment thread backend/scripts/smoke_turns.py Dismissed
finished.append(True)
return result

managed = managed_registered(_Tracked([_chunk("doc-managed-1")], delay=0.2))
import inspect
import pathlib

import agents.main_agent.voice_agent as va
"""The usage-detail subclass only exists with the bidi extra installed."""

def test_subclass_overrides_the_converter_the_provider_still_has(self):
import agents.main_agent.voice_agent as va
"""
import inspect

import agents.main_agent.voice_agent as va
assert ours == theirs

def test_converter_keeps_the_split_on_the_usage_event(self):
import agents.main_agent.voice_agent as va
assert d["modality_details"][0]["input_tokens"] == 1_000

def test_converter_leaves_other_events_to_the_provider(self):
import agents.main_agent.voice_agent as va
reaches the model.
"""

import asyncio
path.
"""

import asyncio
import threading
from concurrent.futures import ThreadPoolExecutor
from typing import Any, List
from unittest.mock import MagicMock, patch
philmerrell and others added 3 commits October 3, 2026 10:00
CodeQL py/log-injection on the release PR: send_audio logged the
sample_rate the voice WebSocket passes through unvalidated, so a
crafted value could forge a log line. Log only the configured rate.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@philmerrell
philmerrell merged commit 8565b58 into main Oct 3, 2026
18 checks passed
@philmerrell
philmerrell deleted the release/1.26.0 branch October 3, 2026 16:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants