sync fork with upstream - #15
Merged
Merged
Conversation
Generate a short GPT-backed title when the first user message is appended. Store titles on sessions and expose them in session context responses.
Closes paradigmxyz#640 Co-authored-by: Amp <amp@ampcode.com>
* fix: default sandbox timeout policy * fix: rely on sandbox max lifetime reaping * docs: clarify sandbox lifecycle timers * fix: prune stale warm sandboxes before replenishing * fix: prune stale warm sandboxes across workloads * fix: preserve idle pause deadlines after restart * refactor: simplify idle cleanup candidate query
Co-authored-by: Centaur AI <ai@centaur.local>
…aradigmxyz#862) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: restrict non-observability sandbox egress * fix: whitelist observable cluster egress explicitly * fix: allow in-cluster database egress * fix: tighten restricted sandbox egress review gaps * fix: use configured control plane network peer * fix: keep restricted blocklist observability scoped * fix: allow direct victoria observability egress * fix: configure sandbox observability egress explicitly * fix: derive observability egress from endpoints * fix: avoid hardcoded observability endpoints * fix: allow sandbox egress to api pods
…digmxyz#870) Replayed the summary pipeline over five real threads (stg + prd) and found the deployed prompt produces one vague goal-restating status per thread: it steers the model toward the session goal, and the specific summaries it does write usually land at 46-52 characters, where sanitize_summary silently discards them (19 of 35 attempts). Two prompt changes, validated by replaying the same threads: - Describe the current step or latest finding instead of the overall session goal, with concrete example phrasings. - Target 40 characters and state the 45-character hard limit so the model cuts words instead of overflowing. Published summaries went from 14/35 attempts to 27/35, too-long discards from 19 to 3, and the output narrates actual progress ("I found forge-std is vendored, not submodule", "I'm blocked on tempo-obs metrics 502") instead of repeating "I'm checking X". Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat: add MCP tool host sandboxes * chore: bump chart version * fix: address MCP tool-host review findings - Always validate the requested method against the parsed client method list; previously tools with zero public methods (methods == [help]) skipped validation and shipped unknown methods to the sandbox - Keep the timed_out result when the sandbox-id lookup fails instead of masking the timeout with a store error - Serialize register_mcp_tool_host_principal under the same per-principal lock as run_tool_host_call so concurrent registrations cannot interleave with session setup, and evict idle lock entries after each call - Cache the discovered tool catalog for 10s so bursts of MCP requests do not redo directory scans and metadata parsing; drop the redundant client.py re-read in the help path - Extract tool_host_session_metadata and reuse tool_host_thread_key instead of duplicating both constructions - Derive SandboxBootMode inside ensure_session_sandbox from the thread key and iron-control principal instead of threading it as a parameter Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: improve MCP tool errors and method discoverability - tools/list and method=help now expose full method signatures parsed from the tool's client.py (e.g. search_tweets(query, limit=10)) so agents pass correct keyword arguments instead of guessing - CALL_RUNNER binds keyword arguments against the target signature before invoking and returns a short 'invalid arguments for method(signature): ...' error instead of a TypeError traceback - Failed tool calls reduce Python tracebacks to the final exception message and append a hint to call method=help for usage Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * [codex] Add console MCP OAuth JWT auth for tool hosts (paradigmxyz#842) * feat: add console MCP OAuth JWT auth * fix: revoke MCP OAuth tokens for inactive users * fix: require approval for MCP OAuth clients * fix: harden MCP OAuth issuer and loopback checks * fix: address MCP OAuth review findings - Fail closed in resolve_requested_resource: reject authorize requests when no canonical MCP resource URL is configured instead of minting tokens bound to caller-supplied audiences - Validate JWT iat is not unreasonably in the future per RFC 0004 - Add missing apiRs.mcpPublicUrl / slackbotv2.mcpPublicUrl entries to values.schema.json - Share header_value between routes.rs and mcp.rs instead of duplicating - Extract HashedTokenLookup concern for the OAuth code/refresh-token models' SHA-256 hash-and-lookup pattern - Cache static env configuration (signing secret, public URLs) in OnceLock instead of re-reading per request Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * chore: bump chart version Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat: add console threads view * fix: stabilize console threads ci * fix: center console thread content * fix: make console threads read-only * fix: scope console thread direct-selection to the owner (paradigmxyz#854) * fix: harden console markdown rendering and thread-title metadata (paradigmxyz#855) * fix: remove passwordless ?auth= console sign-in backdoor (paradigmxyz#857) * fix: transcript ordering, sidebar query scope, and session DB fallback (paradigmxyz#856) * fix: relax console Slack thread scope to team-when-present (paradigmxyz#861) * feat(slackbotv2): link first Slack message to Console session (paradigmxyz#860) * feat: console threads split view and thinking traces (paradigmxyz#863) * feat: always show the model on Console session links and thread header (paradigmxyz#865) * style: show model before harness and uppercase model names (paradigmxyz#867) * feat: console chats naming, empty state, and chat-not-found 404 (paradigmxyz#866) * chore: bump chart version to 0.1.86 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat: hand off in-flight executions on shutdown api-rs runs as PID 1 in its container and installed no SIGTERM handler, so Kubernetes pod terminations never reached the graceful shutdown path: every rollout burned the full termination grace period and ended in SIGKILL, killing stdout pumps mid-turn. The orphaned executions' stdout-owner leases then lingered until their 45s TTL expired, and nothing before the next deploy re-scanned to adopt them. Changes: - Handle SIGTERM (alongside Ctrl-C) as a shutdown signal. - On shutdown, wait up to --shutdown-execution-drain-timeout-secs (default 20, under the chart's 35s grace period) for this process's in-flight executions to finish naturally — pumps keep running while we wait — then release the remaining stdout-owner leases in one statement and record a session.stdout_owner_released event per execution. A peer control plane's adoption scan can then claim the executions immediately instead of waiting out the lease TTL; turn output produced after the release is recovered from the sandbox backend's recorded output during adoption. Verified end to end: the built server exits cleanly on SIGTERM and logs the handoff, where main hangs until SIGKILL. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: address review findings on the shutdown handoff - Fence new stdout-owner claims once the handoff begins (new SessionRuntimeError::ShuttingDown, mapped to 503): an execution accepted mid-drain would otherwise claim a lease that outlives the process and strand the turn until the lease TTL expires. - Clamp the drain deadline against Instant overflow, bound the flag to 0..=600 seconds, and put a 5s timeout on the handoff's count/release queries so a hung database cannot push the release past SIGKILL silently. - Pin the release's owner scoping with a bystander lease in the sqlx test, assert the drain-wait test's completer actually terminalized the execution, and cover the claim fence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: retry workflow host database connections * fix: hardcode workflow host database retry settings
* feat: periodically re-scan for orphaned executions The orphaned-execution adoption scan ran once at process startup, and its lease-deferral path retried only 'on next startup' — i.e. at the next deploy. That misses the common rollout race: the new pod's startup scan runs while the old pod is still alive and pumping (stdout-owner lease active), then the old pod hits its termination grace period mid-turn. The execution is orphaned seconds after the only scan that could have rescued it, and the finished answer sits unread in the sandbox pod logs until the next deploy. This exact sequence lost a completed turn in stg (thread orphaned 25s after the startup scan). Changes: - Re-run the adoption scan on an interval (default 60s, --session-execution-adoption-interval-secs / 0 disables). The stdout-owner lease (45s TTL, renewed every 10s) already makes adoption safe against live owners: scans defer while the lease is active and claim it atomically once it expires. - Skip queued executions younger than a 120s grace window instead of failing them. Executions are queued only for the instant between create_execution and the running transition, but a periodic scan (or a startup scan racing another pod's live execute_session during rollout overlap) could observe that window and kill a healthy row. - Record the session.execution_adoption_deferred event and info log only on the first deferral per execution, so a long turn owned by a live peer does not accumulate one event per tick. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: address review findings on the periodic adoption scan - Check the stdout-owner lease before touching the session row or the sandbox backend: executions owned by this process are skipped silently (no spurious adoption-deferred events on healthy turns, no per-tick kube status calls), and live peers' executions defer without any backend probes. The conditional claim remains the sole authority on ownership. - Restrict the queued-row grace window to periodic scans. A one-shot scan (interval 0) has no later tick to revisit skipped rows, so it fails queued orphans immediately as before — otherwise a young queued orphan could wedge its thread until the next deploy. - Keep deferral-dedup entries across transient per-execution scan errors so kube/DB flaps do not re-emit the deferred event. - Make the lease-expiry test deterministic (force expiry in SQL instead of racing a 200ms TTL), cover the self-owned-execution skip and the spawned periodic loop, and assert the backdate helper touches a row. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * feat: default the adoption re-scan interval to 15s The interval bounds how long a turn handed off by a terminating pod stays frozen before a peer adopts it: leases released at SIGTERM+drain (~20s) wait for the next tick, so 60s meant a worst case of ~80s of stalled thread during every rollout. Since the scan skips lease-held executions before any session or sandbox reads, a steady-state tick is a single SELECT over the handful of active executions — scanning at 15s is negligible load and cuts the worst case to ~35s. Crash recovery stays bounded by the 45s lease TTL either way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…aradigmxyz#875) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…digmxyz#876) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
feat: search oauth google docs in company context
…yz#1194) * refactor(console): centralize permission snapshot assembly * test(console): move snapshot assembly coverage * fix(console): revalidate stale permission snapshots
* feat(console): add role Slack channel permissions * fix(console): address role Slack permission review * fix(console): make Slack channel IDs immutable * fix(console): preserve historical Slack migration * test(console): run Slack backfill with historical index * test(console): remove out-of-order backfill tests * fix(console): show Slack channel names * refactor(console): remove stored Slack channel names * refactor(api-rs): clarify Slack DM permission guard * fix(console): handle Slack permission updates safely
* fix: add direct Slack channel permission deletion * refactor: centralize Slack channel permission deletion
* fix: always run console workers when enabled * chore: bump chart version
* refactor: deduplicate Slack permission handling * fix: skip unchanged Slack permission saves * fix: keep Slack permission no-op notice consistent
* fix: use Turbo delete for Slack permission rows * fix: route Slack permission deletes by opaque id * test: remove redundant Slack permission id rejection case
* refactor: centralize console http requests * refactor: hide optional json body sentinel * refactor: treat nil json bodies as empty requests * refactor: use shared http response type * refactor: initialize console http transport upfront * refactor: return normalized http responses from transport * fix: preserve form request content type headers * refactor: use configured http client timeouts * refactor: rename configured http timeouts
* test: use minitest mocks in console tests * test: assert mock requests inline * test: share HTTP mock helper
Ignore unmentioned subscribed Slack replies, including stop commands, while retaining intervening thread context for the next explicit mention.
…ith 2 updates (paradigmxyz#1191) chore(deps): bump the api-rs-dependencies group Bumps the api-rs-dependencies group in /services/api-rs with 2 updates: [jiff](https://github.com/BurntSushi/jiff) and [jsonwebtoken](https://github.com/Keats/jsonwebtoken). Updates `jiff` from 0.2.34 to 0.2.35 - [Release notes](https://github.com/BurntSushi/jiff/releases) - [Changelog](https://github.com/BurntSushi/jiff/blob/master/CHANGELOG.md) - [Commits](BurntSushi/jiff@jiff-static-0.2.34...jiff-static-0.2.35) Updates `jsonwebtoken` from 10.4.0 to 11.0.0 - [Changelog](https://github.com/Keats/jsonwebtoken/blob/master/CHANGELOG.md) - [Commits](Keats/jsonwebtoken@v10.4.0...v11.0.0) --- updated-dependencies: - dependency-name: jiff dependency-version: 0.2.35 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: api-rs-dependencies - dependency-name: jsonwebtoken dependency-version: 11.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: api-rs-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* fix: skip unchanged secret replacements * test: isolate sync config invalidation coverage * test: simplify sync config invalidation fixture * fix: harden secret replacement comparison * fix: pin secret replacement fields * refactor: remove secret replacement reflection * refactor: clarify replacement collection ordering * refactor: compare secret replacements as model instances * test: assert cache versions and cover replacement guard edges
* fix: update console rails security patch * fix: add console vips binding
* fix: require explicit Slack reasoning intent * fix: validate reasoning against model support * fix: validate nanocodex reasoning by model * refactor: avoid revalidating default reasoning --------- Co-authored-by: Perry Dime <260989497+svc-paradigm@users.noreply.github.com> Co-authored-by: Matthew Slipper <me@matthewslipper.com>
…1209)" (paradigmxyz#1232) This reverts commit 4de19db.
Resolves the conflicts in #14. Fork PR #11 was squash-merged, which dropped the merge ancestry and made 156 files look conflicted. Every conflict was noise: the fork's tree matched upstream 3cf4b35 exactly, so this takes upstream wholesale and reapplies the only real fork change (read-only sentry client commands, #13).
mihoward21
approved these changes
Jul 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings the fork up to date with upstream, replacing #14.
That PR showed conflicts across a hundred and fifty files, but none of them were real. The previous sync was squash merged, which threw away the shared history and made every upstream change since then look like a fork edit. The fork's contents were in fact identical to a known upstream point, so this takes upstream as-is and puts our one genuine change back on top.
Worth merging this one rather than squashing, otherwise the next sync hits the same wall.