Compiled entirely from public activity on meta.discourse.org, X, and GitHub.
💬 meta.discourse.org
This week Sam was vocal about Discourse’s open-source commitment, posting a direct response to Cal.com’s announcement that it was closing its codebase. On the bug-fixing front, he diagnosed a persistent RTL text-direction issue with the new-topic title input, noting it requires a markup-level fix rather than a CSS workaround, and linked the in-progress resolution. He also triaged several community-reported issues — including tag permission inconsistencies, category security resets, and RSS feed filtering — and helped troubleshoot a real-time post delivery problem by probing whether a proxy like Cloudflare was interfering.
🐦 On social
On social
Activity this week was light, with one notable post on X serving as a public correction to a prior claim — digging up session data via term-llm to clarify cached context figures (123M cached vs 500M) and noting the unusually high 500K context window involved. The post had no engagement, suggesting it landed as a niche technical clarification rather than a conversation starter. The theme of transparency and self-correction around AI tooling benchmarks stood out as the week’s social focus.
- 1 posts and 0 replies captured in the last 7 days
- Top by engagement: I do want to post a correction here, I just dug up the…
Most engaged tweets:
- post — I do want to post a correction here, I just dug up the session and found a screenshot in my clipoard, and via term-llm resume, so this was actually 123M cached vs 500M, context wa…
0 likes · 0 reposts · 0 replies
🛠️ GitHub — Sam’s Commits
samsaffron/term-llm
Sam’s week was dominated by two major themes: polishing the model selection experience and improving the serve UI. He built out a chip-based model picker with MRU ordering, added a reasoning effort selector, and added Claude Opus 4.7 support — clearly investing in making model switching faster and more intuitive. In parallel, he overhauled the media lightbox (richer display, safer handling, smoother transitions), added a pending interjection banner, and tightened file serving behaviour. Rounding things out were a handful of reliability fixes — a deadlock on Anthropic stream close, session context not persisting across resumes, and centralised stream event sending to clean up the LLM layer.
Key commits:
4f60c1d— fix(serve): serve index files without redirectea3bd5c— feat(serve): pending interjection banner and state tracking46e891e— feat(ask): add JSONL event stream output34bfff7— feat: add chip-based model picker1935de3— feat(serve): tighten file serving and partial persistence
discourse/discourse
Sam’s week split across two themes: AI infrastructure and UX polish. On the AI side, he updated LLM preset definitions to newer provider model versions, added an xhigh effort level for Anthropic and Bedrock, and aligned the admin UI to match. On the UX front, he refreshed the AI share page visuals (spacing, typography, dark mode), added a submenu for post bookmarks, and fixed a subtle RTL/text-direction bug where neutral-content fields weren’t inheriting the site locale’s direction correctly.
Key commits:
3b13aaa— DEV: update preset model versions (#39342)702953a— FIX: preserve site dir for neutral text (#39213)bdf6274— UX: refresh share page layout (#39214)e019b97— UX: add submenu for post bookmarks (#39172)
discourse/discourse-kanban
Sam’s work this week on discourse-kanban centered on making cards smarter about tags and assignments. The main feature — FEATURE: support tag creation and assignment carryover — allows cards to accept new tag names (not just existing tag IDs), creating missing tags on the fly at save time. He also wired up assignment carryover when promoting floater cards to full topics, respecting board/column-level rules and permission checks. The change touched both backend services and frontend card/detail components, and came with substantial spec coverage for the new flows.
Key commits:
ca99eb6— FEATURE: support tag creation and assignment carryover
discourse/dv
Sam’s focus this week was on hardening the dv sync mechanism. He fixed a correctness bug in the extract/sync pipeline — switching to NUL-delimited git status output to safely handle file paths with spaces or renames, and refactoring shared logic into a helper. He also improved sync resilience by preserving host-local edits across container syncs and keeping both sides aligned after a git reset. To validate these changes, he added a stress-test script for the sync workflow.
Key commits:
rubyjs/mini_racer
This past week Sam shipped a single focused feature: binary data bridging between Ruby and JavaScript. He introduced MiniRacer::Binary, a new wrapper type that allows Ruby callbacks to return raw bytes that V8 deserializes as a Uint8Array on the JS side. The work touched both the C extension (serialization logic) and TruffleRuby’s compatibility layer to keep both runtimes in sync, and shipped with docs, tests, and a patch version bump to 0.20.1. The changes landed in FEATURE: add Ruby-to-JS Uint8Array support (#406).
Key commits:
40d83a3— FEATURE: add Ruby-to-JS Uint8Array support (#406)
🤖 Jarvis — Public Repo Work
Agent-authored public commits, typically guided by Sam during implementation work.
SamSaffron/term-llm
The past week was dominated by hardening term-llm’s concurrency and session reliability — a wave of fixes addressed race conditions and deadlocks across the Gemini provider, runtime shutdown, chat completions history access, and session persistence, suggesting a focused audit of the system’s concurrent internals. Alongside that, ChatGPT authentication got a meaningful UX uplift with device-code flow and graceful Ctrl-C handling, and the web UI was tightened so provider/model/effort settings lock correctly at conversation start. Rounding it out were a handful of correctness fixes: cron timezone handling, Telegram history deduplication, a read_url redirect-bypass security fix, and cleaner error surfacing from OpenAI-compatible endpoints.
Key commits:
319ee83— fix: extract error message from JSON body on non-200 OpenAI-compat responses (#411)2b13af1— feat: prefer device-code flow for ChatGPT sign-in (#408)2f34b3c— feat: ChatGPT auth — print URL fallback and honor Ctrl-C (#407)abd1704— feat: leave no shell-tool descendants behind + make web Stop button responsive (#406)d99ded3— fix: Skill allowed-tools filtering runs before skill-declared tools are registered (#388)
sam-saffron-jarvis/go-bench
This week’s activity was entirely a single focused session on Sunday April 19, launching a brand-new LLM benchmarking project from scratch. Sam (via Jarvis) built go-bench — a framework for evaluating AI models across two task types: a strict-custom-agent benchmark (building a kanban board to a precise spec with automated verification) and a vague-developer benchmark (an open-ended app-building task with looser criteria). The tooling was rapidly iterated on — switching to JSON telemetry, pinning the vague-developer agent template, and adding summary generation — before running a broad model matrix across Claude Haiku/Sonnet, Ollama Gemma4-26b, and a slate of Venice-hosted models including Grok-4-20, Kimi K2.5, GLM-5-1, Minimax M27, Qwen 3.6 Plus, Qwen3-coder-480b, and Claude Opus 4.7. The net result is a populated results directory with screenshots, telemetry, and a summary comparing model performance across both bench types.
Key commits:
a7e7b81— Add Venice benchmark resultsc6e6385— Remove stray GPT-5.4 Pro referencea155619— Tighten README and add Minimax M27 + Qwen 3.6 Plus17ebfee— Pin vague bench agent, switch to JSON telemetry, and add modelsd3040e1— Initial go bench scaffold and results
sam-saffron-jarvis/jarvis-browser-proxy
The week’s activity in jarvis-browser-proxy was light but focused: a single targeted fix to keep the status endpoint responsive during browser recovery, ensuring the proxy server remains observable while the browser is recovering from a crash or restart. The change refactored proxy/server.go and added test coverage, suggesting the issue had previously caused the proxy to appear hung or unresponsive during recovery windows. This is reliability hardening work — keeping the system observable even when things go wrong.
Key commits:
c024efb— fix: keep status responsive during browser recovery
⤴️ GitHub — Pull Requests
26 PRs this week:
- ✅ SamSaffron/term-llm#409 (diff) — fix: retry without tools when Ollama model doesn’t support tool calls closed
When an Ollama model doesn’t support tool calls (e.g.
qwen36-q4:latest), the API returns a 400 error:{"error":{"message":"registry.ollama.ai/library/qwen36-q4:latest does not support tools",...}}This PR adds a test covering the fix alread… - ✅ SamSaffron/term-llm#412 (diff) — fix: remap retired Venice model kimi-2.7 to kimi-k2-5 closed
Add a
veniceModelRenamesmap ininternal/llm/venice.gothat remaps the retired model IDkimi-2.7to its current replacementkimi-k2-5at provider construction time. Venice renamedkimi-2.7tokimi-k2-5. Users who hadkimi-2.7configured… - ✅ SamSaffron/term-llm#387 (diff) — fix: Resetting a Responses conversation can be undone by a late stream completio closed
Add generation-guarded synchronization around
ResponsesClient.LastResponseIDsoResetConversationcannot be undone by a lateresponse.completedevent from an older stream. Also add a regression test that resets the conversation mid-stream and v… - ✅ SamSaffron/term-llm#389 (diff) — fix: Stale previous_response_id is accepted after runtime eviction, branching th closed
- track the latest response ID per session outside the runtime so chaining validation survives runtime recreation - use that server-wide latest response ID as a fallback when a recreated runtime has no in-memory lastResponseID yet - clear the cached …
- ✅ SamSaffron/term-llm#390 (diff) — fix: Persisted serve sessions omit the effective system prompt closed
Persist the effective serve runtime system prompt whenever it is injected into a run. This updates the runtime snapshot builders so the injected system message is included in in-memory history, the initial persisted snapshot, and the final persisted …
- ✅ SamSaffron/term-llm#391 (diff) — fix: Partial streamed assistant output is lost on agentic-loop stream errors closed
Persist partial assistant output from the agentic loop before returning stream errors. This adds a small error-path callback in
internal/llm/engine.goso already-streamed assistant text/reasoning is saved whenstream.Recv()fails or when the prov… - ✅ SamSaffron/term-llm#400 (diff) — fix: Claude CLI conversation state survives resets and leaks old history into ne closed
Add a
ResetConversation()hook toClaudeBinProviderthat clears the persisted Claude CLI resume state (sessionIDandmessagesSent) so fresh conversations do not reuse the previous Claude session. Also add a regression test covering the reset … - ✅ SamSaffron/term-llm#401 (diff) — fix: Telegram history carryover can reload huge image payloads despite a tiny ca closed
- sanitize restored Telegram carryover history before storing it in
sess.history- replace carried-over user image parts with the existing[image uploaded]placeholder text - strip image payloads from carried-over tool results while preserving th…
- sanitize restored Telegram carryover history before storing it in
- ✅ SamSaffron/term-llm#402 (diff) — fix: Tool-reported file paths are blindly republished as web-accessible files closed
- stop
ensureImageServeablefrom copying arbitrary tool-reported image paths into the web-served image directory - tightenensureFileServeableso it only republishes files already inside the configured files dir or the configured image output dir…
- stop
- ✅ SamSaffron/term-llm#403 (diff) — fix: Claude multimodal support leaks temporary image files indefinitely closed
Track Claude CLI temp image files created from multimodal prompt/tool-result data and remove them when the turn or provider session finishes. Without cleanup, every uploaded image or tool-result image materialized into
/tmpis leaked indefinitely. … - ✅ SamSaffron/term-llm#404 (diff) — fix: Stale OpenRouter cache triggers unbounded background refresh fan-out closed
- guard stale OpenRouter cache refreshes so only one background refresh goroutine can run at a time - clear the in-flight flag when the refresh completes so later stale-cache reads can trigger a new refresh if needed - add a regression test covering …
- ✅ SamSaffron/term-llm#393 (diff) — fix(web): avoid duplicate effort label in header closed
Stop the web UI header from rendering a duplicate reasoning-effort badge when the selected model name already includes the same effort tier. Example:
gpt-5.4-medium · mediumnow renders as justgpt-5.4-medium. The header is meant to be a compact … - ✅ SamSaffron/term-llm#385 (diff) — fix: retry without tools when Ollama model doesn’t support tool calls closed
When an Ollama model doesn’t support tool calls, the API returns a
400error:{"error":{"message":"registry.ollama.ai/library/qwen36-q4:latest does not support tools","type":"invalid_request_error"}}This caused the session to fail immediat… - 🟢 discourse/discourse#39343 (diff) — FEATURE: add crypto utilities to AI tool runner opened
Adds a
cryptoAPI to the JavaScript tool runner exposing HMAC (SHA1/SHA256), hashing (MD5/SHA1/SHA256), RSA PKCS1v15 signing, base64 and base64url encoding, and cryptographically secure random bytes. All functions are synchronous bridges to Ruby… - ✅ discourse/discourse#39342 (diff) — DEV: update preset model versions merged
Refresh several AI model presets to newer provider versions and adjust pricing/capacity metadata accordingly. Also add support for the new
xhigheffort level across Anthropic and Bedrock request handling and update the LLM admin UI/specs to match t… - ✅ SamSaffron/term-llm#380 (diff) — fix: Serve runtime mutates persisted history from callback goroutines without sy closed
Guard serve runtime callback-produced state with a local mutex and stop mutating
rt.historyfrom engine callback goroutines. Callbacks now append/persist under synchronized local state, and the request goroutine snapshots that state before final/er… - ✅ rubyjs/mini_racer#406 (diff) — FEATURE: add Ruby-to-JS Uint8Array support merged
Introduce MiniRacer::Binary for attached Ruby callbacks that need to return raw bytes to JavaScript. The C extension now serializes this wrapper as a Uint8Array, and TruffleRuby is updated to mirror the same conversion path. Also add documentation, t…
- ✅ SamSaffron/term-llm#369 (diff) — fix: Venice streaming uses blocking event sends that can wedge cancellation closed
- replace Venice’s raw blocking stream event sends with context-aware sends - return promptly when cancellation happens while emitting text, reasoning, tool-call, usage, or done events - add a regression test covering Close() with a full event buffer…
- ✅ SamSaffron/term-llm#370 (diff) — fix: Copilot provider can hang forever when a stream consumer goes away closed
- make Copilot chat-completions streaming emit events through a context-aware helper instead of blocking channel sends - stop the producer loop cleanly when the stream context is cancelled while emitting text, tool-call, usage, or done events - add a…
- ✅ SamSaffron/term-llm#371 (diff) — fix: xAI streaming can deadlock permanently on client disconnect or cancellation closed
- make both xAI streaming paths use a context-aware event emitter instead of plain blocking channel sends - return early when the stream context is cancelled while emitting text, tool execution, usage, or done events - add regression tests covering b…
- ✅ discourse/message_bus#388 (diff) — fix: subscriber thread never self heals after half open tcp connection closed
Closes #387 When a Unicorn/Puma worker logs:
Global messages on timed out, message bus is no longer functioning correctly the process never recovers. Real-time features silently break for all users on that worker until the app server is restart…
- 🟢 discourse/discourse#39251 (diff) — FEATURE: load liked users incrementally opened
Allow showing a large amount of likers on a single post by incrementally loading.
- ✅ discourse/discourse#39213 (diff) — FIX: preserve site dir for neutral text merged
Use the site’s direction as the fallback
dirvalue for mixed-direction text fields until the user enters a strong LTR or RTL character. This keeps empty and neutral input aligned with the current locale while still switching toautowhen the fiel… - ✅ discourse/discourse#39214 (diff) — UX: refresh share page layout merged
Tighten the AI share page visuals with updated page background, borders, spacing, and typography. Also add table and heading styles so shared content reads more cleanly across light and dark themes. examples:
- ✅ discourse/discourse#39215 (diff) — FIX: retain focus for dynamic field types closed
Cache the resolved control component by field type so fields whose
@typedepends on yielded form data do not get recreated on every render. Add coverage for both top-level fields and nestedform.Objectfields to verify focus stays on the active i… - ✅ discourse/discourse#39172 (diff) — UX: add submenu for post bookmarks merged
Split post bookmark actions into a dedicated submenu so topic footer bookmarks can show a clearer hierarchy and keep topic-level actions separate. This also preserves the topic bookmark button when only post bookmarks exist and updates the bookmark m…
🐛 GitHub — Issues
No issue activity this week.
👀 GitHub — Reviews
2 reviews this week:
- discourse/discourse#39213 — FIX: preserve site dir for neutral text commented
- discourse/discourse#39213 — FIX: preserve site dir for neutral text commented