๐Ÿก


  1. October 13, 2026
    1. ๐Ÿ”— syncthing/syncthing v2.1.7-rc.2 release

      Major changes in 2.1

      • Devices and folders can now be grouped in the GUI by setting the new
        group attribute.

      • HTTP and HTTPS proxies with support for CONNECT can now be used, in
        addition to the existing support for SOCKS proxies (the environment
        variable all_proxy=https://...).

      • Block indexing can be turned off for folders where it's more desirable to
        optimise for reduced database size and overhead than minimal transfer
        size (the blockIndexing attribute on folder configuration).

      • GUI login session duration can be configured to be longer or shorter than
        the default one week, or set to infinitely long. The cookie path can also
        be adjusted. (The sessionCookieDurationS and sessionCookiePath
        attributes in the GUI configuration.)

      This release is also available as:

      • APT repository: https://apt.syncthing.net/

      • Docker image: docker.io/syncthing/syncthing:2.1.7-rc.2 or ghcr.io/syncthing/syncthing:2.1.7-rc.2
        ({docker,ghcr}.io/syncthing/syncthing:2 to follow just the major version)

      What's Changed

      Fixes

      • fix: handle missing max-sequence file entries by @calmh in #10912
      • fix(sqlite): avoid early garbage collection of deleted recv-enc files by @calmh in #10916
      • fix(sqlite): do not generate unbounded prepared statements (ref #10913) by @calmh in #10915
      • fix(discover): skip unnecessary identical global announce updates; obey retry-after by @calmh in #10918

      Other

      Full Changelog : v2.1.6...v2.1.7-rc.2

    2. ๐Ÿ”— smol-machines/smolvm smolvm v1.27.3 release

      What's Changed

      • Preserve macOS machine layer mounts across peer operations by @kcosr in #1738
      • Clean up after an SDK machine delete the way the CLI does by @BinSquare in #1746
      • Return 409 for branching a machine that was not started branchable by @BinSquare in #1748
      • Hand a named machine's layers lease to its VMM by @BinSquare in #1747
      • Shut a VM's guest down cleanly when its owner process exits by @BinSquare in #1749
      • Fix guest stalls on machines booted from a pack under heavy file and mmap load by @BinSquare in #1743
      • Bump version to 1.27.3. by @BinSquare in #1751

      New Contributors

      Full Changelog : v1.27.2...v1.27.3

    3. ๐Ÿ”— r/LocalLLaMA Anthropic is doing free publicity for GLM again rss
    4. ๐Ÿ”— muffinman Show page titles on Firefox's pinned tabs rss

      I love vertical tabs. I used Tree Style Tab for years, then switched to Sidebery and recently to Firefox's native vertical tabs. I like them, but I was annoyed how pinned tabs looked. By default they are collapsed, side by side, with only their favicon visible:

      Firefox's pinned tabs displayed side by side without
titles

      Luckily, there is a way to change that by adding some custom CSS. After applying it, my tabs looked like this:

      Firefox's pinned tabs stacked vertically with
titles

      CSS

      I couldn't find an existing snippet anywhere, and it took me some trial and error to get it right. Here is the CSS. I hope you find it useful.

      /* Show title */
      #pinned-tabs-container[orient='vertical'] .tab-label-container {
        display: flex !important;
        margin-right: 1.5rem;
      }
      
      /* Change tabs layout to be stacked under each other */
      #pinned-tabs-container[orient='vertical'] {
        --pinned-slot-display: block;
      }
      
      slot[part~='items-wrapper'] {
        display: var(--pinned-slot-display, flex) !important;
      }
      
      /* Remove extra vertical padding */
      #pinned-tabs-container > .tabbrowser-tab {
        padding-block: 0 !important;
      }
      
      /* Move the green status dot to the right */
      #pinned-tabs-container .tab-content:is([titlechanged], [attention]) {
        background-position: right 1.25rem center !important;
      }
      
      /* Make space for the green status dot */
      #pinned-tabs-container .tab-icon-stack {
        margin-inline: 0.5rem;
      }
      

      Tested on Firefox 157 on macOS.

      How to use userChrome.css

      To customize Firefox's UI via CSS, you'll need the following:

      • In Firefox, open the about:profiles page and open your profile's Root Directory in your file manager.
      • Inside your profile folder, create a folder named chrome.
      • Inside it, create userChrome.css (if it doesn't already exist).
      • Add your custom CSS to it.
      • Open about:config, find toolkit.legacyUserProfileCustomizations.stylesheets and set it to true.
      • Restart Firefox.

      If you need more details, there is a great website that explains it in detail.

  2. October 12, 2026
    1. ๐Ÿ”— smol-machines/smolvm smolvm v1.27.2 release

      What's Changed

      • Bump the Nix package to 1.27.0 by @BinSquare in #1728
      • Share one extraction across concurrent SDK checkpoint restores by @BinSquare in #1727
      • Let machine update replace the egress allow list exactly with --reset-allow-list, and show the list in machine ls and status JSON by @BinSquare in #1731
      • Fetch a registry image on the host whenever the guest's network cannot reach the registry, not only when it has none by @BinSquare in #1732
      • Fetch a cache disk base over parallel ranged requests and share one fetch among concurrent creates by @BinSquare in #1733
      • Name GHCR's blob host in registry_pull_hosts so an allow list built from it can pull ghcr.io images in-guest by @BinSquare in #1734
      • Let a machine with staged mounts be branched: the branch keeps the working copies and never synchronizes them back by @BinSquare in #1736
      • Bump quinn-proto to 0.11.19 for RUSTSEC-2026-0338 through 0342 by @BinSquare in #1742
      • Bump version to 1.27.2. by @BinSquare in #1730

      Full Changelog : v1.27.1...v1.27.2

    2. ๐Ÿ”— earendil-works/pi v1.2.0 release

      New Features

      • Per-key OpenRouter model lists : with an OpenRouter key, Pi lists only the models that key may use, with the key's context size, max output, and prices, including regional endpoints set in models.json. See OpenRouter.
      • Published configuration schemas : add $schema to settings.json, models.json, keybindings, and themes for editor validation and completion. See Settings, Models, Keybindings, and Themes.
      • Clipboard copies over remote sessions : PI_CLIPBOARD_OSC52=1 sends copied text to a remote client's clipboard when Pi cannot detect the remote session, such as a multiplexer attached from another machine. See Pi Process Configuration.
      • Codemode improvements : tool declarations show input constraints such as integer, minimum/maximum, and default, and codemode rows show elapsed and total time. See Codemode.
      • before_agent_start for extension-triggered runs: runs started by pi.sendMessage(..., { triggerTurn: true }) go through the same setup as prompts. See Events and concurrency.

      Breaking Changes

      • Published generated configuration schemas for models, settings, keybindings, and themes at https://pi.dev/schemas/*.schema.json. The theme schema moved to https://pi.dev/schemas/theme.schema.json; themes loaded during startup now receive the same schema validation as later reloads. Update theme $schema references, define reusable colors under vars, and remove unsupported metadata (#9880, #10751 by @christianklotz)
      • Changed before_agent_start to also fire for runs started by pi.sendMessage(..., { triggerTurn: true }) while idle. BeforeAgentStartEvent is now a union on messageType: "user" events carry prompt and images, and "custom" events carry the starting message and no prompt. Messages returned by handlers are added to both kinds of run, and pending deliverAs: "nextTurn" messages are delivered with the custom-message run. Handlers that should act only on user prompts must check event.messageType === "user" (#10267, #5581, #10739 by @davidbrai)
      • Changed the session to count as busy while a run starts, including during before_agent_start handlers: ctx.isIdle() is false, pi.sendMessage() queues into the starting run instead of starting a second run that failed with "Agent is already processing", pi.sendUserMessage() requires deliverAs, and an abort requested meanwhile aborts the run once it starts (#10739 by @davidbrai)
      • Changed pi mcp list --json to report resources: true for servers that offer resources instead of resources and resourceTemplates counts; Pi no longer lists resources when connecting (#10526)

      Added

      • Added reachesTools to tool definitions, so tools that reach other tools (such as codemode and tool_search) declare which tools a call may reach; the MCP extension uses it to wait for the servers a call needs and to decide whether a replacement codemode or tool_search tool can reach MCP tools
      • Added aliases to tool namespaces; codemode's describeNamespace() and the namespace option of searchTools() match them, and MCP namespaces use the server name
      • Added per-key OpenRouter model lists: with an OpenRouter key, Pi lists only the chat models that key may use, with the key's context size, max output, and prices, including guardrails and regional endpoints set as the base URL in models.json. The list is saved and used offline (#10353, #10672 by @davidbrai)
      • Added PI_CLIPBOARD_OSC52=1 to send copied text to the terminal with OSC 52 after the local clipboard write, so copies reach a remote client's clipboard when Pi cannot detect the remote session, such as multiplexer attaches from another machine or remote IDE daemons (#10826, #10835, #10114)
      • Added elapsed time while a codemode script runs and its total time once finished to the codemode tool row, like bash rows (#10708)

      Changed

      • Changed the showHardwareCursor setting to use only the terminal cursor instead of also drawing Pi's reverse-video cursor
      • Changed codemode tool declarations to show input constraints such as integer, minimum/maximum, length, pattern, and default as @ tags on property comments, so scripts see them without the tool repeating them in descriptions (#10707)
      • Changed codemode declarations of MCP tools to spell out the result type (content, structuredContent, isError) instead of referring to CallToolResult<T>, which describeTool(), searchTools(), and ALL_TOOLS showed without defining it; the codemode description no longer includes the shared MCP types
      • Changed serializeConversation() (compaction, branch summaries, bug reports) to omit thinking blocks; replayed thinking is often not in the live context, so including it could make a summarization request larger than the context it summarizes and fail

      Fixed

      • Fixed codemode ignoring a // @options: line that is not the first line of the script, which ran the script without the requested timeout_ms; the call now fails with an error before the script runs (#10631)
      • Fixed Mistral streams being aborted mid-generation (e.g. during long thinking) after the request timeout; the timeout now applies only to waiting for response headers (#10609)
      • Fixed a symlinked AGENTS.md in a git worktree nested inside its main repo causing no project context file to load (#10681)
      • Fixed the code mode tool description claiming every failed tool call rejects; a tool that declares an output schema resolves with its value on failure too (e.g. bash with a nonzero exit)
      • Fixed runs started by pi.sendMessage(..., { triggerTurn: true }) removing system prompt sections added in before_agent_start after their first tool call, which changed the prompt mid-run and broke the provider prompt cache twice per run (#10267, #10739 by @davidbrai)
      • Fixed codemode blocking the process for seconds to minutes after scripts with many text() calls; joining the output items was quadratic (#10678)
      • Fixed print mode (-p) exiting 0 without a warning when the final response was cut off at the model's output token limit; it now prints the partial text, writes a warning to stderr, and exits 1 (#10799)
      • Fixed pi mcp login --help and the CLI docs describing --timeout as only the wait for the browser; it limits the whole sign-in (#10636)
      • Fixed ~ not being expanded in !pattern, +path, and -path entries of the extensions, skills, prompts, and themes settings, so entries like !~/skills/pdf matched nothing (#10765)
      • Fixed MCP servers with resources registering no tools until every resource was listed; Pi no longer lists resources when connecting, so /mcp and pi mcp list show that a server offers resources instead of counting them (#10526)
      • Fixed MCP tool calls failing when the server returns structured content that is not an object (an array, null, or a primitive, as MCP 2026-07-28 allows); codemode declarations of MCP tools without an output schema now type structuredContent as unknown instead of an object (#10416)
      • Fixed reading or writing auth.json on Windows failing with EPERM when the previous lock folder was still being deleted; Pi now retries briefly before reporting the error (#10801)
      • Fixed OpenRouter router models such as openrouter/auto showing a cost of -$1,000,000 per 1M tokens; OpenRouter's negative placeholder prices are now 0 (#10672 by @davidbrai)
      • Fixed Anthropic requests failing when the provider rejects the strict tool set for grammar size, tool count, or union limits; Pi now retries once with preferred tools non-strict (#10409)
      • Fixed "The upstream provider returned an error" not being retried as a transient provider error (#10842)
      • Fixed focused fullscreen overlays blocking mouse-wheel scrolling of the transcript (#10769)
      • Fixed fragmented terminal color replies leaking hex values into the prompt and opening the external editor (related reports: #10256, #10657)
      • Fixed inline images not rendering in Herdr since 1.1.0 (#10774 by @ogulcancelik)
      • Fixed key bindings that name a shifted symbol, such as + or ctrl++, not matching under the Kitty keyboard protocol or modifyOtherKeys (#9880 by @christianklotz)
      • Fixed the compaction status indicator embedded in a custom editor using the default muted colors instead of the editor border or thinking-level color, as the working indicator does (#10809, #10810 by @Jay-Madden)
      • Fixed MCP tool calls that were cancelled or timed out while waiting for an OAuth refresh still being sent to the server once the refresh finished (#10598)
      • Fixed MCP OAuth sign-in accepting an authorization response with an iss parameter that could not be checked because no authorization server metadata was discovered; sign-in now fails with an issuer mismatch. Reported by @AizenvoltPrime
      • Fixed codemode failing with a broken bridge error when Pi runs under node --watch on Node 24 or 26 (#10725)

      Removed

      • Removed the unreleased experimental server, client, and plugin stack (src/experimental, src/cli/experimental) and its source-only ./client and ./experimental/plugin exports; none of it was part of the published package. The @earendil-works/pi-client, @earendil-works/pi-protocol, and @earendil-works/pi-server packages it used are removed and no longer released
      • Removed the dependency on @earendil-works/chord
    3. ๐Ÿ”— hacker news ida pro references New comment by RachelF in "Reverse engineer anything with agents, from app behavior down to native binaries" rss

      It will be interesting to see if anyone reverse engineers IDA Pro!

    4. ๐Ÿ”— r/LocalLLaMA Once again anthropic doing free marketing for open weight models rss

      Once again anthropic doing free marketing for open weight models | submitted by /u/kubblegum
      [link] [comments]
      ---|---

    5. ๐Ÿ”— hacker news ida pro references New comment by eskibars in "Ask HN: Is there any defense against LLM-based reverse engineering?" rss

      I don't think anything new here is actually all that novel: the only thing that's changed is there used to be more of a skills and time gap than there is now.

      IANAL, but I've worked with a lot of lawyers in my life on software licenses on technical products and am also currently building a platform (ZeroQuarry) which uses some decompilation/disassembly tools (not for rebuilding source software, but rather to find underlying vulnerabilities).

      Tools for reverse engineering have existed for a long time (Ghidra, IDA Pro, cavaj, and a bunch of other language-specific tools), which is why most commercial companies producing non-OSS executables have put in caveats that you can't "reverse engineer or decompile, decrypt, disassemble or otherwise reduce the Software to human-readable form".

      Some of these tools and underlying source code/compilation mechanisms required more skill/time than others, and now with AI, just like in software development, multimedia creation and editing, etc, the barrier to entry and the skills needed to produce something have collapsed to the point that many novices can at least "get started" at virtually no cost. A lot of people on the "builder" side have reached for obfuscation to make it more difficult (a suite of tools has been available there for a long time as well), but all that does is raises the cost of decompilation, and that cost is on an exponentially decreasing cost curve: it was never really a viable defense against "advanced" actors: the only defense against them was legal guards.

      To me, I think the more interesting legal conundrum we're entering isn't pure decompilation/deobfuscation/disassembly, but rather the "clean room" carve out. Several big tech companies (Compaq vs IBM, NEC vs Intel, etc) have gotten away with using 1 team to decompile a piece of code and then have that team write a spec for a clean-room team to re-implement without looking at the decompiled software. That was deemed legal over several court cases, and now it's effectively trivial as well. Or just have an AI with vision capabilities click every button in a UI, see how they work, build the spec from there, and you don't even need decompilation tools, as we're now seeing with the Adobe suite of products: https://getartcraft.com/apps and many others

      I honestly can't think of a real protection for these companies/products except signed/encrypted software at the lowest level, but that only protects companies against non-interactive software (or the non-interactive components). Some people might be old enough to remember that some software used to ship with physical devices that were the physical keys used to allow encrypted software to run. Maybe some of that makes a return?

    6. ๐Ÿ”— r/LocalLLaMA It's been 2 months rss
    7. ๐Ÿ”— Simon Willison Hello Python 3.15, goodbye 3.10, and now I can use 3.11 rss

      Python 3.15 is here! Here's the essential What's new in Python 3.15 guide, this year curated by 3.14 and 3.15 release manager Hugo van Kemenade. As someone who builds open source software that works in every supported Python version, I get to say goodbye to Python 3.10 and start embracing features from Python 3.11.

      First, some highlights from Python 3.15.

      Explicit lazy imports

      I'm most excited about Explicit lazy imports from PEP 810. These let you import modules like so:

      lazy import json
      lazy from pathlib import Path

      The module will then be imported the first time those symbols are used in the code that follows.

      My LLM CLI tool implements plugins. I had to recommend manual lazy imports in the plugin author documentation, because simply installing plugins that used heavy dependencies such as sentence_transformers could add multiple seconds to every invocation of the llm command. Lazy imports directly address this startup cost.

      Unpacking in comprehensions

      The new [*sublist for sublist in lists] unpacking syntax is neat. Here's an illustration lifted from the documentation:

      lists = [[1, 2], [3, 4], [5]]
      [*L for L in lists]
      # [1, 2, 3, 4, 5]
      # equivalent to [x for L in lists for x in L]
      
      sets = [{1, 2}, {2, 3}, {3, 4}]
      {*s for s in sets}
      # {1, 2, 3, 4}
      # equivalent to {x for s in sets for x in s}
      
      dicts = [{'a': 1}, {'b': 2}, {'a': 3}]
      {**d for d in dicts}
      # {'a': 3, 'b': 2}
      # equivalent to {k: v for d in dicts for k,v in d.items()}

      PEP 798: Unpacking in Comprehensions by Adam Hartz and Erik Demaine proposed this as an extension of the unpacking syntax from PEP 448, which landed in Python 3.5 back in 2015.

      A sampling profiler

      Python's existing tracing profiler has been renamed from cProfile to profiling.tracing, and has been joined by an exciting new sampling profiler called Tachyon, aka profiling.sampling.

      Sampling profilers work by periodically capturing stack traces from running processes, then using those to calculate which functions have the most time spent inside of them. They're very low overhead and can provide a deep insight into running systems, without needing to instrument those systems first.

      I've previously used tools like py-spy for this. Now this capability is baked into the standard library.

      If you have the PID of an existing Python 3.15 process you can start gathering samples by running this (I had to use sudo on macOS):

      sudo uv run --python 3.15 python -m profiling.sampling attach 1234

      Interact with the main program a bit, then hit Ctrl+C to stop gathering and see a report, which looks something like this:

      Screenshot of terminal output from a Python sampling profiler with colored text on a black background. Header lines report 2,651 samples captured in 2.65 seconds at a sample rate of 999.98 samples/sec with an error rate of 0.19. A Profile Stats table with columns for nsamples, sample%, tottime, cumul%, cumtime and filename:lineno(function) shows that 99.9% of samples (2.644 seconds) were spent directly in selectors.py KqueueSelector.select, meaning the process was almost entirely idle waiting on the asyncio event loop. The rest of the table lists the call stack beneath it with zero direct time but 100% cumulative presence: asyncio base_events.py run_once, run_forever and run_until_complete, runners.py Runner.run and run, cli.py serve and sqlite_extensions wrapped, and several click core.py invoke, main and call frames. A legend explains each column, followed by a Summary of Interesting Functions section listing hot spots (KqueueSelector.select at 99.9% direct samples), the most frequently present functions on the stack (run_forever, run_until_complete and Runner.run at 100%), and the highest call magnification (2645.0x for BaseEventLoop._run_once).

      It can also produce flame graphs like this and heat maps like this, and can even output a format that can be viewed in the Firefox profiler UI.

      3.15 isn't much faster than 3.14

      Miguel Grinberg investigated How fast is Python 3.15? the other day against the 3.15.0rc3 release and found performance to be mostly the same as 3.14, with the exception of the experimental JIT. The JIT gave a 1.2x boost over the standard 3.15 interpreter (on a Fibonacci test), the first time Miguel observed a meaningful JIT performance increase.

      Miguel's explorations of 3.14 last year found significant boosts against Python 3.13 across many more categories.

      Upgrading to Python 3.15 with uv

      I used the following sequence of commands to get uv to use Python 3.15 on my Mac. First I had to upgrade uv itself to ensure it knew about the new release:

      uv self update

      Then I installed the stable 3.15 release:

      uv python install 3.15

      And told uv that I wanted that to be the default for every uv run command, unless the project itself pinned a different version:

      uv python pin --global 3.15

      Now the following reports 3.15 as the version:

      uv run python --version

      I already have a bunch of tools installed using uv tool install. I reinstalled them to use Python 3.15 like this:

      uv tool upgrade datasette --python 3.15

      Then I can confirm the version like this:

      datasette --get /-/versions.json | jq

      Highlights from Python 3.11

      The release of 3.15 means that Python 3.10 (released in 2021) is officially no longer supported.

      My policy for my main open source projects is to keep them working in every supported Python version. I can now drop 3.10 and start using features that were introduced in 3.11.

      Here's the What's new in Python 3.11 document. I finally get to rely on tomllib being available!

      Datasette makes extensive use of asyncio. 3.11 adds TaskGroup and timeout(), and several more new features.

      datetime.UTC is a new in 3.11 alias for datetime.timezone.utc.

      Python's SQLite support got some significant upgrades in 3.11, including:

      • setlimit() and getlimit() expose a mechanism for setting SQLite runtime limits from Python.
      • create_window_function() lets us create custom window functions in Python, as a class with step(), value(), inverse(), and finalize() methods.
      • blobopen() provides an efficient mechanism for partial reads and writes of large BLOB binary values stored in a SQLite row.
      • You can now call set_authorizer(None) to remove a SQLite authorizer. Datasette had a workaround for this!

      Plus a whole bunch of improvements to Python's typing system.

      I plan to land Python 3.11 improvements to a bunch of my projects over the next few weeks. Here's my first Datasette PR removing that set_authorizer(None) workaround.

      I've also updated my click-app, datasette-plugin, python-lib, and llm-plugin cookiecutter templates to test against Python 3.11 through Python 3.15.

      You are only seeing the long-form articles from my blog. Subscribe to /atom/everything/ to get all of my posts, or take a look at my other subscription options.

    8. ๐Ÿ”— r/LocalLLaMA Qwen released QwenGyre - RL framework for training AI agents on extremely long complex tasks rss

      Qwen released QwenGyre - RL framework for training AI agents on extremely long complex tasks | Introducing QwenGyre, bringing elastic RL to extreme-long-horizon (XLong) agent training. It launches with two core designs: - Elastic Scheduler: reallocates GPUs between rollout & training as demand shiftsโ€”live executions never interrupted. Up to 1.85ร— speedup over Colocate, 1.78ร— over Async. - Trajectory Processor: turns branching executions (compaction, sub-agents, retries) into prefix-shared trajectory trees with bounded, deduplicated training samples. Partial progress after timeout still gets scored. Scaled to Qwen3.8-2.4T-A95B with ~700K tokens per rollout, QwenGyre lifts NL2RepoBench from 52.5% to 58.5% in 48 steps, cutting end-to-end training time by ~44% vs Async. ๐Ÿ”— Read the paper: arxiv.org/abs/2609.33848 submitted by /u/ResearchCrafty1804
      [link] [comments]
      ---|---

    9. ๐Ÿ”— MetaBrainz MetaBrainz Summit 2026 rss

      Hi everyone! Sorry if we react slowly this week, that's because our brains are all slowed down digesting all of the chocolate! Which long term readers will know means we are in Barcelona at our yearly summit all week.

      Today Monday 12 we will have mostly an internal organizational day to figure out how to do things with our new Executive Director Silona.

      Tomorrow Tuesday 13 we will have the traditional presentations about how each project has been doing the past year. Those will be live-streamed on YouTube at https://www.youtube.com/live/OQzlSWMbX8I starting around 14:00 CEST, and we will take some questions from the community in the MetaBrainz room in Matrix/Discord after each presentation!

      More generally, we have a list of topics we are planning to discuss on our Summit wiki page. If you feel there's some other topic that we really should be discussing, please bring it up in our chat and we'll see if we can fit it!

      We will update this post with more info about the rest of the week as we figure things out - please forgive us for any organizational mishaps and slowness since we are still working to figure out the changes we need to the summit format for this year after the loss of Rob, who was always the main organizer of the event. And, of course, because of all the chocolate we are trying to digestโ€ฆ

      Planning:

      Monday 12|
      ---|---
      Morning| Org day
      Afternoon| Org day
      Tuesday 13| CEST_
      ---|---
      Morning| Hack-sessions
      11:00: Solr Test Environment (I)
      11:00: Clickhouse Stats
      12:00: Jira 11 upgrade
      12:00: Wikidata bot upgrade
      12:00: Harmony
      Afternoon| State of the Brainz (STREAMED)
      14:00: State of MetaBrainz
      14:10: State of MusicBrainz
      14:30: State of Instruments
      14:45: State of Picard
      โ€”
      15:30: State of BookBrainz
      15:45: State of ListenBrainz
      16:00: State of Apps
      16:30: State of the Community
      Wednesday 14| _CEST

      ---|---
      Morning| 11:00: AI Policy-Code
      12:00: AI & Infrastructure (+Funding)
      Afternoon| 14:00: Roles & Responsibilities
      15:15: Infrastructure Upgrades
      16:30: CRM
      17:00 Wed: Open Telemetry
      17:00 Wed: GDPR / privacy policy
      17:30 Wed: Events & Editations
      17:30 Wed: Synapse (Notifications)
      Thursday 15| CEST_
      ---|---
      Morning| Hack-sessions
      11:00: Solr Test Environment (II)
      11:00: Matrix Bridge Upgrades
      12:00: ListenBrainz infrastructure
      Afternoon| Sessions
      14:00: AI Policy: Editing
      15:00: Internal Documentation
      16:00: Video Call with Board
      17:30: Product Management (metrics)
      Friday 1 6| _CEST

      ---|---
      Morning| Visit Rob's memorial spot
      Afternoon| Sessions
      14:00: Application Security (Upgrade Policy, Check up)
      14:30: Staging Imports
      15:00:SaaS
      15:30: MusicBrainz Data Analysis
      16:00: Something will come up ๐Ÿ˜€
      17:00: Conclusion (STREAMED)

      Hack-sessions
      17:45: Solr Haproxy Logs
      17:45: Moods
      18:30: MB GraphQL

      *CEST: Central European Summer Time

    10. ๐Ÿ”— smol-machines/smolvm smolvm v1.27.1 release

      What's Changed

      • Branch concurrent requests with pinned ports from one source checkpoint by @BinSquare in #1725
      • Create machines from local images over the API under an opt-in local image directory by @BinSquare in #1707
      • Bump version to 1.27.1. by @BinSquare in #1726

      Full Changelog : v1.27.0...v1.27.1

    11. ๐Ÿ”— r/LocalLLaMA Decision 3.0: open, multimodal decision models from 0.6B to 27B. Ranks #1 on both Jev Decision Index boards rss

      Decision 3.0: open, multimodal decision models from 0.6B to 27B. Ranks #1 on both Jev Decision Index boards | With the vLLM Semantic Router team we released Decision 3.0 (d3) , our new SOTA decision model family ranging from 0.6B to 27B, Apache-2.0, all reading text, images and video. How it works - Built on Qwen3.5 (0.8B / 2B / 4B / 9B) and Qwen3.8-27B. The parameter counts include the vision encoder: 0.33B in the 4B, 0.46B in the 27B. - Three decision types: choice, yes/no, score. Probability for every answer, with no text generation. Several questions about the same input are answered in one call, each from its own forward pass over the input. - Images: multiple per request, read at up to 1.6 MP. - Video: multiple per request (MP4, WebM, MOV, MKV), sampled at 2 fps, at most 32 frames over the whole clip, each at up to 0.2 MP. - BF16 weights, load with Transformers (trust_remote_code=True), trained on AMD Instinct MI325X. Results (our evaluation, official Jev 0.3 kit on the released weights) - #1 on both boards: the 27B scores 64.7 text and 71.6 vision, ahead of every listed model, Jev's own included. - Every size leads its class: the 0.6B, 0.8B, 4B and 9B each lead their size class. The 9B (d3-flash) beats our previous-generation 27B (Decision 2.0). - Video zero-shot: no model saw video in training. On all 19,140 Perception Test validation questions, the 27B scores 77.4 and the 4B scores 70.3. HF collection: https://huggingface.co/collections/vllm-sr/decision-30 submitted by /u/henzy123
      [link] [comments]
      ---|---

    12. ๐Ÿ”— smol-machines/smolvm smolvm v1.27.0 release

      What's Changed

      • Retry removing a machine's data while something still writes into it, and log what was left by @BinSquare in #1679
      • Keep public HTTPS trust in credentialed minimal images by @BinSquare in #1697
      • Load the native root certificates once per process by @BABTUNA in #1692
      • Read only the data ranges of a VM disk when packing it by @BABTUNA in #1690
      • Run idle reclaim on Windows by @BinSquare in #1685
      • Prevent guest file reads from hanging on named pipes by @BinSquare in #1684
      • Bump libkrunfw to the Linux 6.18.55 guest kernel by @BinSquare in #1704
      • Preserve split UTF-8 characters in streamed exec output by @BinSquare in #1715
      • Forward stdin through streamed machine exec by @BinSquare in #1714
      • Keep streamed exec responsive to partial stdin frames by @BinSquare in #1716
      • Prepare file access without running commands from guest images by @BinSquare in #1700
      • Keep running VMs alive when serve startup fails by @BinSquare in #1717
      • Reuse a manifest pulled by digest instead of fetching it from the registry again by @BinSquare in #1718
      • Fix mirrored image cache keys and credential scoping by @BinSquare in #1686
      • Answer the readiness doorbell in pack run by @BABTUNA in #1720
      • Bound queued output for streamed API exec by @BinSquare in #1711
      • Report guest exec timeouts in direct and streaming responses by @BinSquare in #1703
      • Give each embedded control test its own database even within one clock tick by @BinSquare in #1677
      • Confirm macOS process exit events before reporting VM shutdown by @BinSquare in #1670
      • Bump libkrun to the Windows performance work by @BinSquare in #1722
      • Allow HTTP fallback for credentialed WebSocket clients by @BinSquare in #1698
      • Allow opt-in OAuth form credential substitution by @BinSquare in #1699
      • Accept pure OCI archives as local machine images by @BinSquare in #1710
      • Give credential interception leaves Authority and Subject Key Identifiers so strict TLS verification accepts them by @BinSquare in #1723
      • Bump version to 1.27.0. by @BinSquare in #1724

      Full Changelog : v1.26.1...v1.27.0

    13. ๐Ÿ”— Ampcode News First Things First, Faster rss

      The Changes pane now automatically puts files in an intelligent order. Amp reads the diff, identifies the files that are essential to the change, and puts them first.

      If the diff changes, Amp computes an updated order without rearranging the files while youโ€™re reviewing them. Instead, a blue dot will appear over the intelligent ordering button, which you can click to apply the updated order.

      The new automatic intelligent ordering is computed much more rapidly. Here is a comparison of the same diff ordered by both the old and new method:

      You can optionally go back to alphabetical file ordering by clicking the ordering button.

    14. ๐Ÿ”— Ampcode News You've Got Comments rss

      Amp now follows up on GitHub pull requests it opens. Comments, reviews, and CI results show up in the same thread.

      When Amp opens a PR, the agent can now subscribe to the PR's comments, reviews, and CI for its latest commit. A failing check or a reviewer's question shows up in the same thread, and Amp already has the context to deal with it.

      Amp opening a pull request, subscribing to its updates, then receiving the CI results and a review in the same thread

      This is enabled by our new first-class support for GitHub Webhooks. In contrast to our existing, more generic webhook support, the new GitHub Webhook integration centrally handles all requests on the Amp side and then lets you (and your agent) decide whether to forward them to a single orb or to a new one each time. An agent can subscribe to certain events or can set up a subscription that spawns new orbs.

      A New Orb for Every New GitHub Issue or PR

      Ask Amp to start a new orb for every new issue or PR in a repository. You can also limit it to ones opened with a certain label. You don't need to keep the thread where you set it up.

      A request to start a new orb for every new issue in acme/website, the subscription tool call, and Amp noting that the thread can be archived

      Each new issue or PR gets its own orb, which reads it and has a summary waiting when you open the thread. Later comments on that issue or PR go to the same thread, so the conversation stays in one place.

      A new Amp thread started for a newly opened pull request, summarizing what the pull request changes

      You manage these in Settings โ†’ MCP & Integrations โ†’ GitHub, where you can edit or pause them and see the orbs each one started.

      The GitHub Event Subscriptions table in Settings with two orb spawners and a pull request subscription

      Read the docs to find out how to watch CI when you push to main, follow an existing issue or PR, and ask Puck what Amp is following.

      Install the Amp GitHub App on your repository to get started.

    15. ๐Ÿ”— muffinman GB Pixel Art Jam 2026 - SpaceDeck Trio rss

      I participated in my first pixel art jam! It was a Game Boy themed one. It was a lot of fun to work with such a limited palette. The theme was Three , and I went with three player ships from SpaceDeck X. I was happy to see how well my sprites translate into the Game Boy's original colors.

      Once I finished drawing it, I had to animate it, so here is the animated version:

      Pixel art animation of three player ships from my game SpaceDeck X facing a
boss. Four colors, Game Boy palette.

      I even toyed with the idea of making a small demo game for it (not a real Game Boy cartridge), but due to the time limit, I went with a single animation (which has 48 frames).

      I use Aseprite to draw and animate. You can find my jam submission here. Hope you like it!

  3. October 11, 2026
    1. ๐Ÿ”— IDA Plugin Updates IDA Plugin Updates on 2026-10-11 rss

      IDA Plugin Updates on 2026-10-11

      New Releases:

      Activity:

      • agent-smith
        • dda54ffc: docs: reconcile publication gates and exact source provenance
        • 08a0e56a: fix: bound broker reply delivery only during shutdown
        • e0553bbb: fix: require scanner canary and finish broker start replies
        • 81539f6e: fix: preserve broker-host teardown failures
        • 7145d334: fix: join isolated broker lifetimes and drain pending starts
        • 58a5106e: fix: fit predictor identities within the real broker contract
        • 20cf02ac: fix: isolate predictor profiles with cryptographic identities
        • bc618b9d: fix: bind decoder reconciliation to native scan log context
        • 8c70a04a: fix: bind AppleDouble proof to the exact baseline archive lifecycle
        • fc7c316b: fix: bind Agent Smith runtime and scan reviews to exact owned content
      • diaphora
        • de0eb920: Merge pull request #389 from joxeankoret/joxeankoret-patch-16
        • a7e15949: Update README.md
        • f91e77f4: Enable again by default using the supplied ML model
        • 55ac08dd: Merge branch 'master' of ssh://github.com/joxeankoret/diaphora
        • 62844466: Re-trained model for supporting scikit-learn >= 1.4
        • 468f69c9: Merge pull request #370 from heinermann/patch-1
        • 75714da7: Adaptations for PR 373
        • a83b15c8: Multiple little bugs fixed
      • ida-free-mcp
        • fab05e67: fix(decompile): match Mach-O names without their leading underscore
      • ida-llm-explainer
        • f8bd284f: v1.15.0: fix agent tools for IDA 9.4/9.5 API drift, add type/analysisโ€ฆ
      • Luc-Nhan
        • 2f711220: fix(ui): isolate session state and repair native UX interactions
      • oh-my-pi
        • 0a2539b0: Merge upstream v18.9.1 into the fork (trial; conflicts resolved)
        • 1fd6f606: v18.9.1 upstream source
    2. ๐Ÿ”— HexRaysSA/plugin-repository commits sync plugin-repository.json rss
      sync plugin-repository.json
      
      No plugin changes detected
      
    3. ๐Ÿ”— r/LocalLLaMA Every Model That Can Be Run On 10-16GB VRAM Ranked rss

      It's been 4 years since c.ai first hallucination model, and yet, we're nowhere good enough at LLMs in terms of spontaneity/interesting hallucination features. Fortunately, last year brought new architecture that allow those within 10-16GB VRAM range to run something usable up to 64k Context Windows via Kobold or LLAMA.

      Requirements: 10-16GB VRAM - 26-32GB RAM.

      How I Evaluated:

      • Speed; If tokens per second are at least 10t/s.
      • Coherency: If dialogue/monologue/POV makes any internal sense asides from basic logic (robotic feeling) or behaviorism.
      • JP/PT-BR/US-EN: If it can handle/interpret typos, nuance or harsh verbiage.
      • Slop Patterns: From "casting long shadows" to "smells like ozone and burnt sugar" frequency.
      • MOE vs FULL: If rather pick a MOE instead of a FULL model.
      • Censorship; All these models have either none or too low refusal rates even at NSFL topics, worry not.
      • Instruction/Engineering: I've tested WITH and WITHOUT Pandora Instructions, if a model can handle 23 intertwined rules it can handle anything/not need a prompt at all.

      Side Note: I've ignored all CoT models, waste of tokens, slower, not needed, not at all. Do prompt nicely and it's the same. Just pick any quant higher than Q_4_K, size doesn't matter ( อกยฐ อœส– อกยฐ).

      The Catch: I've done a small knowledge test involving animes/manga/movies/music on 70B, 120B and 300B models and found out only models above 200B actually have this sort of data, even a 120B will rarely have the information about the media you're interest at. But who can even run it?

      The List (Best to Worse/Why):

      1. Gemma 4 26B-A4B: Qwen 35B-A3B but with better dialogue/monologue, directive, slightly smarter/precise and funnier.
      2. Qwen 3.6 35B-A3B (Abliterated): Fast, accurate, and decently fun, yet may overfit previous inputs/output format/patterns without proper directive instructions, or speak gibberish/ask too many questions because of directive.
      3. Gemma 4 Instruct 19B-A1B Heretic (Abliterated): 26B-A4B but a bit more rigid, plain, yet keeps accuracy and logic.
      4. The Omega Directive 14B: Follows instructions, has low slop pattern rate and writes nicely, yet might become predicable after some context fill.
      5. GLM-4.7-Flash 31B-A3B (Abliterated): Performs similar to Qwen 35B-A3B but more straightforward, less interpretative of nuance/verbiage.
      6. Qwen3 30B A1.5B 64K High Speed NEO MAX: Basically 35-A3B with increased reasoning.
      7. MN CaptainErisNebula Chimera Heretic Uncensored 12B (Abliterated): Its weird, a bit rushy trying to fill everything at once, full of patterns, but its the most proactive of them all, unlike to get stuck in a loop, has good dialogue/monologue yet ain't suitable for Q &A roles.
      8. Mistral Nemo Instruct 2407 HERETIC HI Claude Opus 12B: It's decent, slop seems to have been rephrased properly, yet may overfit impersonation POV, or try to rizz you up mostly, not suitable for Q &A roles.
      9. Gemma 3 12b GLM-4.7 Flash INSTRUCT Hybrid Heretic (Uncensored): Interestingly impersonative, accurate, yet may overfit previous inputs' formatting/style with frequent slop patterns or lack humour/too prim.
      10. Ministral Instruct 2512 Absolute Heresy 14B: Mistral sucks at following complex rules (regex, status panel, commands, lorebook, etc), or turn {{char}} into a rizzler, despite being the best one regarding dialogue/monologue/spontaneity, ironically.
      11. GLM 4.6V Flash Hybrid ?B: UD but with decreased slop frequency, even less refusals.
      12. GLM 4.6V Flash UD 9B: Can feel robotic/repetitive depending on the personality of your {{char}} as making too many questions, despite high accuracy at following all PI 23 rules + regex commands.
      13. Gemma 4 E4B UD: For the desperate, it's tiny, fast, accurate and smart, but will prolly repeat itself/have slop patterns.
      14. LFM2 12B A1B SpeedDemon The Deckard II HERETIC (Uncensored): Lighting fast, highly accurate and smart, but lacks sauce.

      Overall Review: GLM tends to be pessimist and too logical, Qwen tends to be too inquisitive and fancy, Gemma tends to be funny and creative, Mistral tends to be flirty and oddly specific, Llama tends to be sloppy and predicable, this happens across all of their finetunes regardless if Omega, Heretic, Deckard, Dark, Horror, RP, Style, etc.

      Settings: Kobold can't load these, use LLAMA for QWEN 35B (20,6GB) and GLM 31B (17,7GB). Other models all running at fastest speed possible with 40-64k - FlashAttention/FastFowarding/SWA/SmartCache + MMPROJ + TTS if any in Kobold.

      Models I'm aware but discarded after trial cuz either too slow (massive), poor or have better alternatives: Mistral 24B, GPT 20B OSS, Kimi K2, Phi-4, Skyfall, DeepSeek, Cydonia, Magistry, Magnus Cydons, etc.

      Not Tested: Goetia 26B-A4B v1.7, Gemma 4 26B-A4B StyleTune V2, Promethean Dawn 26B-A4B and Fenrir-X 26B-A4B.

      What if I have 24GB VRAM (e,g, RTX 3090)? If going lower try Omega Darker Gaslight The Final Forgotten Fever Dream 24B, Qwen3 24B-A4B Freedom HQ Thinking Heretic NeoMAX-D_AU, Cydonia 24B, Magistry 24B, Magnus Cydons 24B, Erebus 12B Instruct 2608, Mistral RP 24B, DeepSeek 33B, Velvet Eclipse 2x12B or Velvet Eclipse 4x12B.

      END

      submitted by /u/WEREWOLF_BX13
      [link] [comments]

    4. ๐Ÿ”— MetaBrainz Picard 3.0.2 released rss

      Picard 3.0.2 is a maintenance release for the recently released Picard 3.0 with fixes for reported issues and updated translations. This releases fixes a crash in the Setup Wizard if Picard was packaged with the automatic update check disabled and several color theme related fixes.

      The latest release is available for download on the Picard download page.

      The detailed changes for this maintenance release are below. For an overview of the new features since Picard 2.13 please see our detailed release announcement for Picard 3.0.

      Thanks a lot to everyone who gave feedback and reported issues.

      Whatโ€™s new?

      Bugfixes

      • [PICARD-3484] - Hardcoded link styling in Audio Player options
      • [PICARD-3485] - Sticky grey background in metadata pane
      • [PICARD-3490] - Program crash after wizard if build with --disable-autoupdate
      • [PICARD-3491] - Text color issues in dark mode in metadata pane and placeholder texts
      • [PICARD-3494] - Plugin manager "View Repository" fails silently when remote is a local path

      Download

      Picard 3.0.2 is available for download from the download page of the Picard website. For Windows 10 and 11 users installing from the Microsoft Store the update to Picard 3.0.2 is now available and can be installed from the Microsoft Store app. Linux users can get the latest Snap package. The Linux Flatpak package is maintained separately and will be updated soon.

      Picard is free software and the source code is available on GitHub.

      Get in touch

      Please use the MetaBrainz community forums and the ticket system to give feedback, suggest new features or report bugs.

      Acknowledgements

      Code contributions by Philipp Wolfer and Laurent Monin.
      Translations were updated by st.esser (German).

    5. ๐Ÿ”— r/LocalLLaMA Hereโ€™s why RTX 5090 costs $5,000: AI firms are buying gaming GPUs by the pallet rss

      Hereโ€™s why RTX 5090 costs $5,000: AI firms are buying gaming GPUs by the pallet | submitted by /u/chemist_slime
      [link] [comments]
      ---|---

    6. ๐Ÿ”— Stephen Diehl MLIR Part 14 - GPT-2 on the GPU rss

      GPU Target

      GPT-2 on the GPU

      Part 8 built the GPU path by hand: kernels in the gpu dialect, NVVM lowering, PTX, and the driver calls that allocate memory and launch a grid. Parts 9 through 13 built a tensor compiler whose output ran on the CPU. This chapter joins the two. The same traced tensor programs, with the same formulas and the same reference checks, run on an NVIDIA GPU.

      There are three pieces of work. The parallel loops that remain after bufferization have to become kernels. Matrix multiplication needs a schedule that uses shared memory, since a naive thread-per-output mapping wastes the hardware. And the boundary between host arrays and device memory has to be decided. All of it lives in tinymlir/gpu.py, a module of about two hundred and fifty lines that the CPU path never calls into.

      The chapter ends with a second way to compile the model. Rather than one function per sublayer, the whole NumPy reference forward pass is traced into a single module, and that module is handed to either target.

      You need Linux on x86_64, an NVIDIA driver and a card of compute capability sm_75 or newer. A Tesla T4 on Google Colab is enough; the repository includes a notebook that installs the CUDA build of the bindings and runs everything below. Nothing else in the series requires a GPU.

      Where the Targets Diverge

      Recall the shape of the pipeline from Part 12. Fusion runs on tensors. Bufferization assigns storage and inserts deallocations. The result is a module of linalg operations over memrefs, and that module is what each target receives:

      PassManager.parse(BUFFERIZATION_PIPELINE).run(lowered.operation)
      if target == GPU:
          gpu.lower(lowered)
      else:
          blas.rewrite(lowered)
          PassManager.parse(LOWERING_PIPELINE).run(lowered.operation)
      

      The GPU side has the same two-step structure as the CPU side, a substitution followed by a pipeline:

      def outline(module):
          tiled_matmuls(module)
          PassManager.parse(KERNEL_PIPELINE).run(module.operation)
          managed_allocations(module)
      
      
      def lower(module):
          outline(module)
          PassManager.parse(llvm_pipeline()).run(module.operation)
      

      outline is the part that is independent of hardware. It runs in the test suite on every platform, including machines with no GPU, and asserts that every loop in the module became a kernel launch. lower continues to PTX and needs the CUDA build of MLIR, which exists only for Linux.

      The order within outline matters. The matmul substitution has to come before the loop passes, otherwise the matmuls would be converted to parallel loops and nothing would be left to substitute. And both have to come after bufferization and buffer deallocation. The hand-written kernel contains gpu.barrier, whose memory effects the deallocation analysis can't see through. By the time the kernel is inserted, storage has already been assigned and released.

      Loops to Kernels

      The second step is a pipeline of existing MLIR passes:

      KERNEL_PIPELINE = (
          "builtin.module("
          "convert-linalg-to-parallel-loops,"
          "func.func(scf-parallel-loop-tiling{parallel-loop-tile-sizes=16,16 "
          "no-min-max-bounds=true}),"
          "func.func(gpu-map-parallel-loops),"
          "convert-parallel-loops-to-gpu,"
          "gpu-kernel-outlining,canonicalize)"
      )
      

      Each linalg.generic becomes an scf.parallel loop nest over its parallel iterators, with any reduction iterators as ordinary sequential scf.for loops inside. A softmax row reduction is therefore a parallel loop over rows containing a serial loop along each row. One thread handles one row. That is the right mapping for GPT-2's shapes, where the reduced dimension is at most a few thousand elements, and it is the only reduction strategy this backend has.

      Tiling splits each parallel loop into an outer loop over tiles of sixteen and an inner loop within the tile. The mapping pass annotates the outer loops as block dimensions and the inner loops as thread dimensions. Conversion turns the annotated nest into a gpu.launch, and outlining moves its body into a gpu.func inside a gpu.module, replacing it with gpu.launch_func. For the GELU of a (64, 256) matrix, the host function after this pipeline is:

      %memref = gpu.alloc host_shared () : memref<64x256xf64>
      gpu.launch_func @kernel_kernel::@kernel_kernel
          blocks in (%c4, %c16, %c1) threads in (%c16, %c16, %c1)
          args(%c16 : index, %c0 : index, %c16 : index, %c1 : index, %c0 : index,
               %arg0 : memref<64x256xf32>, %cst_2 : f32, %cst_1 : f32,
               %cst_0 : f64, %cst : f64, %cst_3 : f32, %memref : memref<64x256xf64>)
      memref.copy %memref, %arg1 : memref<64x256xf64> to memref<64x256xf64>
      

      A grid of four by sixteen blocks of sixteen by sixteen threads covers the matrix. The kernel's body is the fused GELU region from Part 10 with gpu.block_id and gpu.thread_id in place of loop induction variables:

      gpu.func @kernel_kernel(..., %arg5: memref<64x256xf32>, ..., %arg11: memref<64x256xf64>) kernel {
        %block_id_x = gpu.block_id x
        %thread_id_x = gpu.thread_id x
        ...
        %6 = memref.load %arg5[%4, %5] : memref<64x256xf32>
        %7 = math.powf %6, %arg6 : f32
        ...
        %12 = math.tanh %11 : f64
        ...
        memref.store %16, %arg11[%4, %5] : memref<64x256xf64>
        gpu.return
      }
      

      The no-min-max-bounds option tells the tiling pass not to clamp the inner loop with min expressions when a dimension is not a multiple of sixteen, and to use a conditional in the body instead. The clamped form produces loop bounds that the GPU conversion can't map to a fixed block size.

      The test suite checks the outcome structurally. For GELU, softmax, layer normalization, matmul, gather and attention, the host function after outline must contain gpu.launch_func and no scf, linalg or memref.alloc operations. Everything that iterated now runs on the device.

      A Tiled Matrix Multiplication

      Running linalg.matmul through the same pipeline would work, and would be slow. It becomes a parallel loop over the output with a serial loop over $K$ inside, so each thread reads a full row of $A$ and a full column of $B$ from global memory. Adjacent threads in a block read overlapping data and nothing is shared. Part 8 introduced shared memory precisely for this case.

      The backend therefore replaces every floating-point linalg.matmul and linalg.batch_matmul with a call to a kernel written by hand. The kernel is a textual MLIR template, formatted for the operand rank and element type, parsed with ir.Module.parse and moved into the module. Omitting the batch handling and some of the bounds checks, its structure is:

      func.func private @tiled_matmul_2d_f32(%a: memref<?x?xf32, ...>, %b: ..., %out: ...) {
        %m = memref.dim %a, %i0 : ...
        %k = memref.dim %a, %i1 : ...
        %n = memref.dim %b, %i1 : ...
        %gx = arith.ceildivui %n, %tile : index
        %gy = arith.ceildivui %m, %tile : index
        gpu.launch blocks(%bx, %by, %bz) in (%sx = %gx, %sy = %gy, %sz = %i1)
                   threads(%tx, %ty, %tz) in (%ux = %tile, %uy = %tile, %uz = %i1)
                   workgroup(%sa : memref<16x16xf32, #gpu.address_space<workgroup>>,
                             %sb : memref<16x16xf32, #gpu.address_space<workgroup>>) {
          %row = arith.addi (arith.muli %by, %tile), %ty
          %col = arith.addi (arith.muli %bx, %tile), %tx
          %sum = scf.for %k0 = %i0 to %k step %tile iter_args(%acc = %zero) -> (f32) {
            // each thread stages one element of the A tile and one of the B tile
            memref.store (load %a[%row, %k0 + %tx] or zero), %sa[%ty, %tx]
            memref.store (load %b[%k0 + %ty, %col] or zero), %sb[%ty, %tx]
            gpu.barrier
            %part = scf.for %kk = %i0 to %tile step %i1 iter_args(%s = %acc) -> (f32) {
              %x = memref.load %sa[%ty, %kk]
              %y = memref.load %sb[%kk, %tx]
              scf.yield (%s + %x * %y)
            }
            gpu.barrier
            scf.yield %part : f32
          }
          scf.if (%row < %m and %col < %n) {
            %old = memref.load %out[%row, %col]
            memref.store (%old + %sum), %out[%row, %col]
          }
          gpu.terminator
        }
        return
      }
      

      Each block owns a sixteen by sixteen tile of the output. It walks the reduction dimension in steps of sixteen. At every step each of the block's two hundred and fifty-six threads loads one element of the current $A$ tile and one of the current $B$ tile into the two workgroup buffers, out-of-range positions reading as zero. A barrier makes the tile visible to every thread. Each thread then accumulates sixteen products from shared memory, and a second barrier keeps the next step's loads from overwriting a tile still being read. Every global element is loaded once per block instead of once per thread, a factor of sixteen fewer global loads.

      Two details connect the kernel to the surrounding program. The final store adds to the output rather than overwriting it, because linalg.matmul accumulates into its destination; the builder's linalg.fill with zero runs first as its own small kernel. And the kernel takes memrefs with fully dynamic sizes, strides and offset. The substitution inserts a memref.cast for each operand, so a single kernel per rank and element type serves every shape in the model, and strided views from slicing and transposition work without copies:

      %cast = memref.cast %arg0 : memref<64x256xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
      %cast_0 = memref.cast %arg1 : memref<256x32xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
      %cast_1 = memref.cast %memref : memref<64x32xf32> to memref<?x?xf32, strided<[?, ?], offset: ?>>
      call @tiled_matmul_2d_f32(%cast, %cast_0, %cast_1)
      

      The batched variant adds a third grid dimension indexed by the batch, which attention's per-head products use.

      This is the classic shared-memory matmul from the CUDA programming guide, no more. There is no register tiling, no vectorized or asynchronous loads, no tensor cores, and the tile size is fixed. cuBLAS would be several times faster on these shapes. The point is that the kernel is sixty lines of readable IR, inserted at the one place in the pipeline where a matrix multiplication is still a matrix multiplication, and it is enough to run the model.

      Managed Memory

      Part 8 moved data with explicit copies to and from the device. This backend avoids that bookkeeping with CUDA managed memory, which both the host and the device address through the same pointer. The compiler-side change is small. Every memref.alloc left by bufferization becomes a gpu.alloc with the host_shared attribute, and every memref.dealloc becomes the asynchronous gpu.dealloc bracketed by gpu.wait, which is the form the runtime library implements:

      %memref = gpu.alloc host_shared () : memref<64x32xf32>
      ...
      %0 = gpu.wait async
      %1 = gpu.dealloc async [%0] %memref : memref<64x32xf32>
      gpu.wait [%1]
      

      The runtime side is a Python class wrapping the same allocator. It calls mgpuMemAlloc from MLIR's CUDA runtime library with the host-shared flag and exposes the pointer through the NumPy array interface:

      class Managed:
          def __init__(self, shape, dtype):
              self.pointer = runtime().mgpuMemAlloc(size, None, True)
              self.__array_interface__ = {
                  "shape": tuple(shape), "typestr": dtype.str,
                  "data": (self.pointer, False), "version": 3,
              }
      

      np.asarray on such an object is an ordinary NumPy array backed by managed memory. The JIT's call path places each input in managed memory, skipping arrays that already live there, and allocates the output there too. Since the output of one compiled sublayer is the input of the next, the residual stream never leaves the device during a forward pass. The model places its weights in managed memory once at load time.

      The cost is that the driver, not the program, decides when pages migrate. A first touch from the host after a kernel writes faults the page back. For this model, where the host reads one row of logits per step, that is the right trade. A latency-sensitive backend would want explicit transfers and streams, and the gpu dialect's async tokens are how it would express them.

      The execution engine loads the CUDA runtime library alongside the usual runner utilities. The PTX for each gpu.module is embedded in the host module as a gpu.binary, and a global constructor loads it into the driver when the engine initializes. Launching a kernel from the host function is then a call into the same runtime library that Part 8 called by hand.

      From NVVM to PTX

      The last pipeline carries the outlined module to LLVM on both sides of the launch boundary:

      builtin.module(
        expand-strided-metadata,lower-affine,convert-scf-to-cf,
        nvvm-attach-target{chip=sm_75 O=3},
        gpu.module(convert-gpu-to-nvvm),
        gpu-to-llvm,finalize-memref-to-llvm,
        convert-arith-to-llvm,convert-func-to-llvm,convert-cf-to-llvm,convert-index-to-llvm,
        reconcile-unrealized-casts,
        gpu-module-to-binary{format=isa toolkit=<path to nvidia-cuda-nvcc>})
      

      The passes are the ones from Part 8. The target attribute names the chip. convert-gpu-to-nvvm rewrites the body of each kernel into NVVM intrinsics for thread indices, barriers and shared memory. gpu-to-llvm rewrites the host side, turning allocations, launches and waits into calls into the runtime library. gpu-module-to-binary serializes each kernel module to PTX, with format=isa keeping the result as text rather than assembling it to SASS, which the driver does at load time for whatever card is present.

      The toolkit option points the serializer at libdevice. math.tanh and math.exp inside a kernel aren't single PTX instructions; they link against NVIDIA's bitcode library of math routines. The project gets libdevice and ptxas from the nvidia-cuda-nvcc package on PyPI, so no system CUDA installation is needed, and finds them by importing the package and asking where it lives.

      Having ptxas available means the PTX can be checked without a GPU. A test lowers each of the six cases above, extracts every gpu.binary, and assembles it for sm_75. Continuous integration runs this on an ordinary Linux runner. Malformed PTX from a bad conversion or a missing libdevice link fails the build long before anyone has hardware in hand. The test that compares GPU results with CPU results for the same six functions runs only when a device is present.

      Running It

      Pass --gpu to the example or to the verification script:

      uv run python example.py "Alan Turing theorized that computers would one day become" --tokens 10 --gpu
      uv run python verify.py --gpu
      

      Nothing in model.py changed for this. The functions embed, attend, feedforward and project are the ones from Part 13, and the target is a keyword passed through to the JIT. On a Colab T4, with compilation included, the ten-token generation took about half a minute and produced the same completion as the CPU and the NumPy reference. The verification script compared embeddings, every block's residuals, logits and token IDs at all ten steps. All ten tokens matched, with a largest absolute difference across the captured arrays of about $1.1\times10^{-5}$, against about $8\times10^{-6}$ on the CPU. The difference is the accumulation order: the tiled kernel sums sixteen products at a time in a fixed order, and the BLAS does something else.

      That number is the whole claim. The GPU target produces the reference's required output and agrees with its intermediate values to within tolerance on one card. It isn't fast by the standards of a production runtime.

      The Whole Model as One Kernel

      The per-sublayer design compiles four small functions and calls them in a Python loop over blocks. That was a deliberate choice for the series: each compiled function is small enough to print and read. The compiler itself doesn't require it. With the array protocols from Part 9 and the tree-structured arguments from Part 12, a traced function can take the entire parameter record and contain the entire forward pass.

      The fused.py module does exactly that with the NumPy reference. Its gpt2 function is the one from tiny-gpt2, pasted in and decorated:

      @jit
      def gpt2(inputs, params, *, n_head):
          x = params.words[inputs] + params.positions[range(len(inputs))]
          seq_len, embedding_dim = x.shape
          head_size = embedding_dim // n_head
      
          for block in params.blocks:
              ln1_mean = np.mean(x, axis=-1, keepdims=True)
              ln1_variance = np.var(x, axis=-1, keepdims=True)
              ln1_normalized = (x - ln1_mean) / np.sqrt(ln1_variance + 1e-5)
              ln1_output = block.attention_norm.weight * ln1_normalized + block.attention_norm.bias
      
              qkv_proj = ln1_output @ block.attention_in.weight + block.attention_in.bias
              q_proj, k_proj, v_proj = np.split(qkv_proj, 3, axis=-1)
              ...
              causal_mask = np.triu(np.ones((seq_len, seq_len), dtype=x.dtype) * -np.inf, k=1)
              attention_scores = attention_scores + causal_mask
              ...
      

      Every NumPy call dispatches to our symbolic value. params is the model's named tuple of weights, flattened to arrays by the JIT and reassembled inside the trace. The np.triu mask is evaluated by NumPy itself, because none of its arguments is symbolic; the resulting array is captured as a constant and lifted to a trailing kernel argument. There are twelve of them, one per block, each a (T, T) matrix. This implementation masks with -np.inf where Part 11's mask used $-10^{10}$; after the softmax both give the future positions exactly zero weight.

      Tracing produces one graph for the twelve blocks. Before optimization the module holds six hundred and fifty-two linalg.generic operations; elementwise fusion reduces them to two hundred and nine. The forty-nine linalg.matmul and twenty-four linalg.batch_matmul operations pass through untouched, which is what the tensor.reshape decision in Part 11 was protecting. On the CPU every one of them becomes a GEMM call. On the GPU every one becomes a launch of the tiled kernel.

      A separate specialization per sequence length would mean a compilation per generated token, and compiling this module is not cheap. The fused mode pads the token sequence to the next power of two and reads back the row of logits for the last real token:

      def logits(ids, weights, config, target):
          padded = np.zeros(min(1 << (len(ids) - 1).bit_length(), config.context), np.int32)
          padded[: len(ids)] = ids
          output = gpt2(padded, weights, n_head=config.heads, target=target)
          return output[len(ids) - 1 : len(ids)]
      

      The causal mask guarantees that positions after the last real token don't influence it, so padding changes nothing in the row we read. A ten-token prompt generating ten tokens needs lengths sixteen and thirty-two, two compilations instead of ten.

      uv run python example.py "Alan Turing theorized that computers would one day become" --tokens 10 --fused
      uv run python verify.py --fused
      uv run python example.py "..." --tokens 10 --gpu --fused
      

      All three produce the same sentence. In the fused mode the forward pass is one function with no intermediate values to capture, so the verification script compares only the final logits and the selected tokens. On a laptop the fused run took roughly three times as long as the per-sublayer run, nearly all of it LLVM compiling two large modules. On the T4 the two modes took about the same time.

      What the fused mode demonstrates is a property of the compiler rather than a performance result. The program that was compiled is the reference implementation, unmodified. The series spent four chapters building a frontend with its own operator set so that each piece could be examined in isolation. The same frontend, given an existing NumPy program, traces it whole.

      What the Structure Bought

      Look back at what didn't change to add the GPU target. The tensor language, the builder, the optimization pipeline, bufferization and every formula in ops.py and model.py are the ones from the CPU chapters. The target is a keyword argument. The additions are a loop-to-kernel pipeline assembled from existing passes, one hand-written kernel, and a hundred lines of memory plumbing.

      That was possible because the pipeline preserved structure for as long as it could. Matrix multiplication stayed a named operation through fusion and bufferization, so each target could substitute an implementation. Parallel iterators stayed parallel, so a pass could map them to threads. Allocations stayed explicit, so they could be redirected to managed memory. Each decision deferred in the earlier chapters became a seam here.

      The limits are equally visible. There is one reduction strategy, one tile size, one element type for the kernel, no key/value cache and no attention schedule that avoids materializing scores. A production compiler would decide each of these per shape and per device. This one makes them readable, and checks the result against the reference on real hardware.

      External Resources

      Previous: Part 13 - Running GPT-2 ยท Series contents

    7. ๐Ÿ”— r/LocalLLaMA Qualcomm CEO reveals AI companies want phones running 100-billion-parameter models continuously by 2028. rss
    8. ๐Ÿ”— r/LocalLLaMA Building a 4x R9700 setup for a 10 person startup rss

      Building a 4x R9700 setup for a 10 person startup | Just wanted to share a build I am doing for a client. $18k. Specs: Threadripper 9970x 128gb DDR5 ECC 5600 4x AMD Radeon R9700 AI Pro 32gb(128gb total VRAM) 1600W PSU(GPUs are undervolted and under 210w each) Engine : using a fork of Radiance to serve Qwen 3.8 Next flash/27b and DSV4 Flash Results: 16 concurrent sessions Qwen 3.8 27b MXFP4 6.3-6.8k aggregate prefill tok/s
      900 t/s - 80t/s aggregate decode(range: 4k - 128k context each) Qwen 3.8 Next flash int4fp8 48K/user | 6,880 tok/s | 538.5 tok/s aggregate prefill/decode 128k/user | 3,050 tok/s | 365 tok/s aggreate prefill/decode BF16 kv for all. submitted by /u/sayamss
      [link] [comments]
      ---|---

  4. October 10, 2026
    1. ๐Ÿ”— IDA Plugin Updates IDA Plugin Updates on 2026-10-10 rss

      IDA Plugin Updates on 2026-10-10

      New Releases:

      Activity:

    2. ๐Ÿ”— HexRaysSA/plugin-repository commits sync repo: +1 release, -1 release rss
      sync repo: +1 release, -1 release
      
      ## New releases
      - [IDASQL](https://github.com/allthingsida/idasql): 0.0.19
      
      ## Changes
      - [IDASQL](https://github.com/allthingsida/idasql):
        - removed version(s): 0.0.10
      
    3. ๐Ÿ”— r/LocalLLaMA Open-source Mac app that runs EmbeddingGemma 2 locally to search your files by whatโ€™s in them rss

      Open-source Mac app that runs EmbeddingGemma 2 locally to search your files by whatโ€™s in them | DigUp is a free Mac app that runs Google DeepMindโ€™s new EmbeddingGemma 2 locally over your own files. The model puts text, images, audio and video in one space, so you describe what you remember and land on it:

      • โ€œzebra in a videoโ€ opens the clip at the moment it shows up
      • โ€œwhere they talk about sleepโ€ jumps to that minute of a podcast
      • โ€œthe clause about pets in the leaseโ€ shows the PDF page, your words marked
      • โ€œa dog on the beachโ€ finds the photo, and the same search in Bengali or Arabic finds it too
      • with code search on, code: retry with backoff opens the function in your editor

      Itโ€™s ggml-orgโ€™s Q8_0 GGUF (865 MB, downloaded once) on llama.cpp with Metal, inside a native Swift app; no Python. Searching loads only the text encoder (~250 MB) and shows results about a tenth of a second after you stop typing. Indexing peaks under 2 GB, and the helper exits when itโ€™s done. Audio and video of any length go in as 30 s windows and a frame per shot. Everything runs locally; it goes online only for the model download and an update check you can turn off. Free, MIT. Apple Silicon, macOS 14+. Repo & Download (signed and notarized): https://github.com/ARahim3/DigUp I'd really appreciate any feedback on this. submitted by /u/A-Rahim
      [link] [comments]
      ---|---

    4. ๐Ÿ”— smol-machines/smolvm smolvm v1.26.1 release

      What's Changed

      • Reap a child after its exit event so a stopped VM is not left a zombie on macOS by @BinSquare in #1675
      • Bump version to 1.26.1. by @BinSquare in #1676

      Full Changelog : v1.26.0...v1.26.1

    5. ๐Ÿ”— smol-machines/smolvm smolvm v1.26.0 release

      What's Changed

      • Seed host-fetched and local image archives so no-network machines skip re-flattening by @BinSquare in #1635
      • Keep compression admission test stable under Windows CI load by @BinSquare in #1642
      • Keep a TSI guest off a host resolver the egress floor blocks by @BinSquare in #1641
      • Write a large upload into the guest as it arrives instead of holding all of it first by @BinSquare in #1640
      • agent: stop spinning on a child that closed its stdout by @BABTUNA in #1644
      • pack: flatten qcow2 disks on the host, writing only their data by @BABTUNA in #1646
      • Encode streaming exec errors as valid JSON by @BinSquare in #1649
      • Return 404 when a guest file does not exist by @BinSquare in #1648
      • Close guest stdin for streaming exec without input by @BinSquare in #1650
      • Reject incomplete streamed uploads and enforce declared byte counts by @BinSquare in #1647
      • Kill whatever is left in a machine's scope when its VM is torn down, and stop export helpers whose creator is gone by @BinSquare in #1638
      • Remove partial host files after interrupted guest streams by @BinSquare in #1639
      • Explain guest agent version skew during pack export by @BinSquare in #1636
      • Count SSBS that KVM gives guests on hosts that hide it from themselves by @BinSquare in #1657
      • Bump libkrun so a branchable child shares its source's memory by @BinSquare in #1660
      • Embedders register bundle paths in-process, not through the environment by @BinSquare in #1658
      • Let credential bindings set a header, match wildcard hosts, and be created by an embedder by @BinSquare in #1436
      • Avoid dropping virtio-net connections during parallel workloads by @BinSquare in #1661
      • Seed machine run from a local image archive by @BABTUNA in #1656
      • api: skip the create time seed for machines that fetch on the host by @BABTUNA in #1654
      • process: wait on the exit event instead of a polling tick by @BABTUNA in #1652
      • Reject invalid published ports in embedded machine creation by @BinSquare in #1662
      • Reclaim Kubernetes pod state after container and sandbox deletion by @BinSquare in #1666
      • Bump version to 1.26.0. by @BinSquare in #1673

      Full Changelog : v1.25.4...v1.26.0

    6. ๐Ÿ”— r/LocalLLaMA NVIDIA reportedly discontinuing RTX 5090, GB202 GPUs to be reserved for RTX PRO series rss

      NVIDIA reportedly discontinuing RTX 5090, GB202 GPUs to be reserved for RTX PRO series | No..... submitted by /u/chemist_slime
      [link] [comments]
      ---|---

    7. ๐Ÿ”— r/LocalLLaMA big or small? rss

      big or small? | what size do you want? tell them on X: https://x.com/QwenDevs/status/2108764909798641737 submitted by /u/jacek2023
      [link] [comments]
      ---|---

    8. ๐Ÿ”— hacker news ida pro references New comment by methou in "REA Reverse โ€“ Engineer Anything" rss

      I'm using IDA Pro's MCP (Well worth of money in the past), it may hit the infamous artificial cyber wall at any time.

      Try GLM-5.3, it worked pretty for me. It also worked well with Radare2 or binary ninja if you don't have the muscle memory for idapro.

    9. ๐Ÿ”— Ampcode News Use Your Claude Plan in Amp rss

      You can now use your Claude Pro/Max subscription in Amp. It's free and available for everyone now.

      When creating a new thread, just pick Mode > Claude Code. It'll ask to link your Claude sub if you haven't already done that.

      The web mode dial with the Claude Code position selected, using a Claude Pro/Max plan. The model is Opus 5.5 and the effort is High.

      Under the hood, this mode uses the Claude Agent SDK instead of Amp's own agent. But we made it all work: orbs and runners, thread sharing, portals, multiplayer, thread-to-thread messaging and orchestration, etc.

      See the Claude sub docs for more information.

    10. ๐Ÿ”— Baby Steps Why 'externalized' proofs of cyclic trait impls does not work rss

      For this post, I wanted to talk about two different approaches to handling supertraits. I'm calling them modular proofs vs external proofs. The key idea of this post is that, if we want to have cyclic trait impls, we really need to use a modular proof strategy, where the impl establishes all supertraits hold. Previously we had considered an external strategy, where the piece of code using the impl has the obligation to prove the supertraits hold. Modular proofs always seemed better but I did not think they were workable in the past. But I have become convinced that external proofs are incompatible with Rust as designed, and hence modular proofs are really the only option1. This post dives into that reasoning, and also gives a bit of explanation of what I mean by proofs in the first place.

      Traits and supertraits

      So what do I mean by modular vs external proofs? Well, it all comes down to who is responsible for proving that supertrait obligations hold. Consider a trait like Magic:

      trait Magic: Copy { }
      

      The supertrait declaration means that, whenever X: Magic for some type X, it should be true that X: Copy. We make use of this in generic functions:

      fn is_copy<T: Copy>() {
      }
      
      fn is_magic<T: Magic>() {
          // Legal, because `T: Magic` implies `T: Copy`
          is_copy::<T>();
      }
      

      The trick is that the compiler has to make sure that this implication holds - i.e., for every type X that implements Magic, X also implements Copy. So how does it do it?

      Modular proofs: the impl must show supertraits hold

      The obvious answer is to make proving supertraits part of deciding whether an impl is valid. For any impl of Magic, we can require that the Copy supertrait holds. So an impl like this would be illegal:

      // In a modular system, this impl is *illegal*
      impl Magic for String { }
      

      This impl is illegal because it would require that String: Copy, and that does not hold. Seems good.

      Modular proofs are a bit tricky

      I am calling these proofs modular because the idea is that we can prove an entire program is valid by proving each part of it separately. In "programming language" theory, this is typically called a "modular" check, as it works by breaking up the entire program into modules that can be independently checked.

      The idea with a modular proof is that we can trust impls to show that the supertrait relationships hold , we don't have to go and re-prove them over and over. If the impl is wrong, the impl will be invalid, but our code is fine. So if we have impl Magic for String, that implies the rest of the program can prove that String: Magic:

      fn string_is_magic() {
          // Legal, because there is an impl for `String: Magic`:
          is_magic::<String>();
      }
      

      In fact, since we know that Magic implies Copy, the rest of the program can even rely on impl Magic for String to conclude that String: Copy:

      fn string_is_copy() {
          // Legal, because there is an impl for `String: Magic`,
          // and `Magic` implies `Copy`:
          is_copy::<String>();
      }
      

      So long as impl Magic for String is invalid, none of this poses a problem to soundness, since the program overall doesn't type-check.

      Comparison with functions

      An easy way to understand the idea of modular checks is to think of functions. Imagine you have a function like this one:

      fn compute_sum(a: i32, b: i32) -> i32 {
          format!("{a} + {b}") // <-- Error
      }
      

      Clearly, this function is not legal. It takes two integers and promises to return a third integer, but in fact it returns a String. So the function is illegal. But if you have a call to that function from elsewhere, we consider that other call to be legal:

      fn use_sum() {
          let c: i32 = compute_sum(2, 20); // OK
      }
      

      Here, use_sum is relying on compute_sum to obey its contract. It's not the job of use_sum to check that, it can just assume it is true.

      The catch: how do we decide the impl is invalid

      There is a bit of a catch though. How do we decide if the impl is invalid? The basic idea was that impl Magic for String would have to prove that String: Copy. But we just saw that it could, in fact, do that by using itself. In other words, if we aren't careful, we can provide a proof that String: Copy likeโ€ฆ

      • String: Copy because Magic implies Copy and
        • String: Magic because impl Magic for String exists

      and then we would (incorrectly) conclude that the impl is valid. So clearly we need to do something to rule that out. We need a rule that says, when we are proving that an impl is valid, that proof cannot recursively rely on the impl itself.[^termination] I'll come back in a future post to ways we might do that, but for now, I want to explore another alternative.

      External proofs: the user of the impl must show supertraits hold

      When we first looked at this problem, way back in 2018 or so, we thought of another approach. What if we said that an impl is not responsible for proving supertraits. Instead, the idea would be that impl Magic for String is not enough to say that String: Magic. It only says that Shallow(String: Magic) - i.e., String implements Magic in a shallow way, but not in a deep way that includes the full supertraits. To prove thatString: Magic, we have to show that Shallow(String: Magic) and Shallow(String: Copy):2

      Shallow(String: Magic)
      Shallow(String: Copy)
      ---------------------------- Magic fully implemented
      String: Magic
      

      This has the somewhat counterintuitive implication that impl Magic for String is actually legal in an "external proof" approach:

      // In an external system, this impl is LEGAL
      // (but unusable)
      impl Magic for String { }
      

      The saving grace is that, while this impl is legal, you can't actually use it. This function for example does not compile:

      fn string_is_magic() {
          // NOT legal in an external system:
          // * We can prove that `Shallow(String: Magic)`
          // * We CANNOT prove that `Shallow(String: Copy)`.
          is_magic::<String>();
      }
      

      Here, String: Magic doesn't hold even though there is an impl of Magic for String, because the caller also has to check that String: Copy is implemented, and it is not. Huh, interesting.

      Comparison to functions: external is awkward

      the "external proof" approach for impls is clearly a bit awkward. If we make the comparison to functions, it's as if the caller has to double check that the callee's body matches its return type, it can't actually trust the declared signature. But, awkward or not, it does resolve our problem: given impl Magic for String, we cannot prove String: Copy, and hence we cannot prove that String: Magic. We can only prove that Shallow(Magic: String), which doesn't imply that the supertraits hold.

      But external doesn't work with unsafe traits

      Based on the above, for a long time, I was working with the assumption that, weird as they are, we would go with the "external proof" approach. However, as Ralf Jung and lcnr pointed out to me recently, this is very challenging to reconcile with unsafe traits. Consider an unsafe trait like Nullable:

      // A type that can be safely transmuted from `0_usize`.
      unsafe trait NullWord { }
      

      The way that Rust works, when we write an unsafe impl, it is the job of that impl to prove that the unsafe conditions hold. Other parts of the program get to trust the impl. So if I write a function like this one, it should be considered safe:3

      fn foo<T: NullWord>() -> T {
         std::mem::transmute(0_usize)
      }
      

      Now imagine that I wrote an invalid impl like this one:

      // INVALID: We are asserting that `Box` can be null,
      // which is not true!
      unsafe impl<T> Nullable for Box<T> { }
      

      Given this program I could clearly call foo::<Box<u32>>(), but that would "go wrong" (cause "undefined behavior"). I think we would all agree that the fault lies in the impl. And yet, that is inconsistent: we say that the impl alone cannot be trusted to figure out if the supertraits are implemented, but it can be trusted to figure out if the unsafe impl is valid?

      Conclusion

      I definitely believe that we want to treat the "extra conditions indicated by unsafe" as a more general version of the other obligations that an impl has to establish to show that the trait holds- and therefore that we must have modular proofs. That's kind of a relief, because something always felt wrong about external proofs, but it was hard to put my finger on a concrete problem. In the next post in this series (whenever that may beโ€ฆ), I expect to cover the approach to coinductive modular proofs that I landed on. Then I expect to talk about an alternative that was proposed to me that I find quite appealing.


      1. I think this was obvious to Ralf Jung from the start. But it took me a bit. โ†ฉ๏ธŽ

      2. This notation is called an inference rule. The conditions above the line are the premises and the bottom line is the conclusion. It says that, if you know the premises are true, you can infer that the conclusion holds. โ†ฉ๏ธŽ

      3. In point of fact, I believe this will not compile because of special rules about unsafe, but that's not relevant to the point I'm trying to make. โ†ฉ๏ธŽ