- ↔
- →
- September 21, 2026
-
🔗 Simon Willison Jev introduces a new shape of LLM - System One, aka Decision Models rss
Last week TypeSafe AI unveiled Jev, their first example of a new category of model that they are calling "System One models" (I'm with Maggie Appleton, I think "decision models" is a better name for these). Jev is an interesting variant on the usual LLM format: it still accepts text inputs, but instead of text output it returns floating point numbers corresponding to categories, yes/no questions, ratings, and associated confidence scores.
TypeSafe describe Jev like this:
Think of Jev as a frontier-intelligence function call: unstructured state in, typed probabilistic decisions out.
It's also very fast, and really cheap. Regular LLMs are priced in terms of input and output tokens, with output generally charged at significantly higher rates. Jev charges only for input - output is free - and the input price of their first model is $0.042 per million tokens - cheaper even than OpenAI's GPT-5 Nano ($0.05/million).
Jev lets you ask questions about text or semi-structured data. You compose a "state" object containing a string, array of strings, or set of name-value pairs - this might describe an article, or a customer, or any other kind of record. You then send that to their API with one or more questions, and get a reply back for each.
You can ask three kinds of questions:
- Yes/No questions, which Jev calls "Noul" questions - their CEO confirmed on Hacker News that this is short for Bernoulli, from the Bernoulli distribution. You pose a statement and get back a floating point number between 0 and 1 for how confident the model is that the statement is true.
- Choice questions, where the model picks one from a set of provided options - actually a confidence score plus a probability distribution across all of the options.
- Score questions, where you provide sequence of numeric levels with descriptions and it provides a floating point score somewhere along that range.
The Jev API can accept a single document ("state") and as many questions as you can cram into the context window. Questions are evaluated in parallel, so sending many questions should take a similar time to sending just one.
I think the decision model framing is useful for understanding where to use Jev. It's great for anything that can be expressed as a classification task - think spam detection, suggesting labels, prioritization and ranking.
I've also been experimenting with it for search reranking, where you fetch 100 likely matches using an inexpensive algorithm like BM25, then have Jev score those 100 candidates for relevance against the original query.
Black boxes are back in fashion
Something I've found a little uncomfortable about Jev is how it very much represents a regression even further towards black box machine learning systems.
LLMs are black boxes already - you can ask them to justify their decisions, but you can't guarantee that what they say is useful or accurate.
Jev doesn't even give you that: put in all the text you want, the only thing you're going to get back is a floating point number. If Jev marks something as spam, which content signals tipped it off?
This also means that concerns about bias should be front and center. I really hope nobody uses Jev to rank job applicants - that floating point number could conceal all manner of unseen bias baked into the models, and experimentally picking that bias apart is going to be a tricky business.
(I tried one experiment where I had Jev score every city in the San Francisco Bay Area on a yes/no answer to whether they were a "Good city?" - it rated Cupertino top and East Palo Alto bottom. Huh.)
In practice, this all means that evals and structured experiments are even more important than they are for regular LLM projects. Thankfully, Jev is so cheap that running hundreds or even thousands of experimental prompts through it costs just a few cents.
Unconventional uses for Jev
It's been really fun watching the wider community come up with potential use-cases for Jev over the past few days. Here are some creative ones that caught my eye:
- jevchat by Kyle Pena turns Jev into a (terrible) chat model. "At every step it asks Jev one question: Given the user's question and the reply written so far, which symbol comes next?". ericpruitt on Hacker News: "It's the digital equivalent of Morty speaking with the death crystal".
- jev-leftpad by Fatih Kadir Akın implements left-pad with the prompt "How many spaces are needed before value to reach targetLength?" and a choice query allowing options from "0 spaces are needed" to "10 spaces are needed".
- jev-2048 by Andy Gayton uses Jev to play the 2048 sliding puzzle game.
Open weight recreations
There's also been a flurry of projects attempting to create a model like Jev using on top of open weight models. Kev is one interesting example, using Qwen 3.5 to produce 0.8B, 4B, and 9B models. Here's the accompanying Hacker News thread, where someone linked to a JevBench benchmark that has already cropped up to compare "Jev-class decision models".
Given Jev was released just under a week ago, the amount of activity around it is extremely impressive.
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.
-
🔗 idursun/jjui v0.10.11 release
A point release with bug fixes, in-app Git credential prompts, and visual improvements to Annotation View.
Features
- Git credentials: Git credential requests now appear inside jjui, alongside existing SSH askpass support. Usernames remain visible, while passwords and passphrases are masked. Git and SSH askpass support is enabled by default; the old
ssh.hijack_askpasssetting is replaced byaskpass.enabled. Set it tofalseto disable jjui's credential prompts. (#746) - Evolog: Pressing
son a hidden entry in evolog splits the change into two: the original change is restored to the selected historical state, and the later edits become a new child change. This is particularly useful when you forget to start a new change before making unrelated edits, as you can separate them at the point they began without manually selecting files or hunks. The best part is that this feature ships in the default configuration using only Lua actions. (#686) - Describe: Press
ctrl+xto clear the entire description into the editor's yank buffer, thenctrl+yto restore it. (#749) - Details: Press
ito invert file selection. (#707) - Bookmarks: The interactive bookmark pane now supports
ctrl+clickto toggle selection andalt+clickto select a range. (#742)
Improvements
- Annotation View: Leaving with uncopied comments now asks for confirmation. Press
escto keep reviewing, or select Discard to leave. (#744) - Annotation View: Improved rendering and contrast so text is easier to read against highlighted backgrounds.
- Lua: Previously, Lua actions could read application state through the
contextmodule, for example withcontext.change_id(),context.file(), andcontext.checked_commit_ids(). In this release, I've added the first "read state" function attached to a feature:revisions.inline_describe.content(). It returns the current inline description draft, ornilwhen the editor is unavailable. It's only implemented for inline describe for now, but I'd like to extend this to the rest of the application. - Lua: Existing selection getters now read live UI state so scripts see the current selection after yielding actions and refreshes.
- Lua: Choice dialogues now show footer help and a visible
filter:prompt. (#743) - Describe: Pressing
escwith unsaved changes now asks for confirmation, replacing the previous draft-stashing behaviour. In the confirmation,enterdiscards the draft andesckeeps editing. (#523) - Command input: The
:and$inputs now appear above the status bar, giving them more room. (#683)
Bug Fixes
- Annotation View: Copying annotations now uses the system clipboard. (#741)
- Annotation View: Pressing
escwhile help is expanded closes help first. (#744) - Annotation View: Opening full-file views correctly handles paths containing spaces.
- Bookmarks: Moving bookmarks to hidden revisions now correctly targets the selected historical commit. (#748)
- Help: Expanded help stays within the viewport. (#574)
- Status bar: Restored footer mode labels.
- Diff range: Accepting a range without selecting another target now compares the starting revision against the working copy by omitting
--to. - Terminal: Fixed a crash when the terminal reports an empty background colour. (#745)
What's Changed
- feat: multi-select bookmarks with ctrl and alt click by @baggiiiie in #742
- lua: add footer help and prompt to choose filter by @baggiiiie in #743
- fix(bookmarks): move bookmarks to hidden revisions by @anandghegde in #748
- feat(describe): add clear action (ctrl+x) by @baptiste0928 in #749
- feat: add in-app git askpass credential prompts by @idursun in #746
New Contributors
- @anandghegde made their first contribution in #748
- @baptiste0928 made their first contribution in #749
Full Changelog :
v0.10.10...v0.10.11 - Git credentials: Git credential requests now appear inside jjui, alongside existing SSH askpass support. Usernames remain visible, while passwords and passphrases are masked. Git and SSH askpass support is enabled by default; the old
-
🔗 navidrome/navidrome v0.64.1 - Security Fixes release
This is a security release. It fixes five vulnerabilities reported through our GitHub Security Advisory program, covering Subsonic authentication, artwork fetching, playlist cover images, player ownership, and per-user library filtering. Upgrade as soon as you can. Thanks to the researchers credited below for reporting them privately.
The release also improves Jellyfin client support, with both Manet and JellyBox tested and validated against live servers. Manet used to abort its entire library sync on a single missing field and show an empty library. It now syncs end to end. JellyBox got stuck on the login screen. It now signs in and plays, confirmed on Android. Navidrome also reports itself as Jellyfin 12.1.0, accepts Quick Connect sign-in, and can announce itself on your local network so clients find it without you typing an address.
Smart playlists can reference another playlist by path, and the web UI now formats dates using the language you picked in Personal settings.
Security
- Unauthenticated password brute-force through the Subsonic API. Failed Subsonic logins were never throttled, so an attacker could guess passwords at full speed. Navidrome now rate limits failed authentication attempts. High, CVSS 7.4. (GHSA-p994-r776-mw52, #6185) Reported by @osageling.
- Authenticated SSRF through M3U external album artwork. A playlist could point
#EXTALBUMARTURLat a private or loopback address, turning the server into a probe for internal network services. Navidrome now blocks private and loopback addresses in remote image fetches. Medium, CVSS 6.5. (GHSA-8hjf-6h34-82hr, #6181) Reported by @kaardeco. - Cross-library file read through the M3U playlist cover.
#EXTALBUMARTURLalso accepted a local path, so a playlist could serve any file the server can read as its cover image. Only real image files are accepted as local artwork sources now. Medium, CVSS 6.5. (GHSA-vwq6-xrw5-phpg, #6180) Reported by @qrn12580. - Player takeover by any authenticated user. Creating a player could overwrite an existing record and reassign its owner, and device registration reused another user's player without an ownership check. Both paths now check the owner. Medium, CVSS 6.4. (GHSA-37h4-53gj-cw8m, #6184) Reported by @RealFakeAccount and @qrn12580.
- Library filter skipped on bookmarks, playlist tracks and now-playing. These three endpoints ignored the libraries a user is allowed to see, leaking track metadata from other libraries. The filter now applies to all of them. Medium, CVSS 4.3. (GHSA-pcjv-h48m-833g, #6179) Reported by @sondt99.
Configuration Changes
Status | Option | Description | Default
---|---|---|---
New |Jellyfin.AutoDiscovery| Answers Jellyfin's UDP discovery broadcasts, so clients find the server on the local network. (#6169) |false
New |Jellyfin.QuickConnect| Allows Quick Connect sign-in, where a client shows a code you approve from a session that is already signed in. (#6174) |trueFor a complete list of all configuration options, see the Configuration Options documentation.
Jellyfin API
- Add Quick Connect sign-in. The client shows a short code, and you approve it from a session that is already signed in, so the client never sees your password. (#6174 by @deluan)
- Add opt-in LAN auto-discovery, so Jellyfin clients find the server without you typing its address. Docker users need host networking for the UDP broadcast to reach the container. (#6169 by @deluan)
- Report Jellyfin 12.1.0 and add the 12.x features clients check for, including
fillWidthandfillHeightimage sizing. (#6163 by @deluan) - Match Jellyfin's item payloads, so clients that decode strictly can finish a sync instead of erroring out. (#6151 by @deluan)
- Match Jellyfin on login
SessionInfo, item types and universal streams. (#6161 by @deluan)
UI
- Format dates using the language selected in Personal settings, instead of always following the browser locale. (#6160 by @deluan)
Smart Playlists
- Reference another playlist by its path in a smart playlist rule, instead of by id. (#5187 by @davidvedvick)
Subsonic API
- Log a warning when a
nowPlayingscrobble sends more than one id, which the API does not allow. (6b3938b5b by @deluan)
Server
- Fix the ExtAuth logout redirect on unauthenticated page loads, and stop the warning spam from untrusted sources. (#6176 by @deluan)
- Return 404 instead of 500 when a native API resource does not exist. (#6131 by @deluan)
Artwork
- Report a failure when the Last.fm artist page has no image. Last.fm now answers non-browser clients with a bot challenge page, which Navidrome read as "this artist has no image" and recorded as final, with nothing in the log. It now logs a warning and retries, and the other image agents still get their turn. (#6198 by @deluan)
- Store artwork files as group-readable (mode
0640) instead of owner-only, so other services on the same host can read the image cache. (#6189 by @kwo)
Scanner
Scrobbling
- Double-encode plus signs in artist and track names sent to Last.fm, so tracks with a
+in the name scrobble correctly. (#6158 by @deluan)
Packaging
- Repair root-owned artwork and plugins folders on upgrade. Installs affected by this could not write their own cache. (#6143 by @deluan)
Translations
- Update Finnish and Dutch translations from POEditor. (#6148 by @deluan)
- Update missing German translations. (#6146 by @strecke)
- Improve the Swedish translation. (#6177 by @NickWick13)
- Update Chinese Simplified translations. (#6152 by @fxj368)
- Update Portuguese (Brazil) translations from POEditor. (#6197 by @deluan)
New Contributors
- @davidvedvick made their first contribution in #5187
- @strecke made their first contribution in #6146
- @NickWick13 made their first contribution in #6177
- @kwo made their first contribution in #6189
- @aerusso made their first contribution in #6190
Full Changelog :
v0.64.0...v0.64.1Helping out
This release is only possible thanks to the support of some awesome people!
Want to be one of them?
You can sponsor, pay me a Ko- fi, or contribute with code.Where to go next?
-
🔗 smol-machines/smolvm smolvm v1.17.0 release
What's Changed
- Let aarch64 Linux resume a branch source instead of freezing it by @BinSquare in #1327
- Attach host disks and vhost-user block devices to a machine by @BinSquare in #1326
- agent: refresh persistent DNS and retain shutdown receipts by @sgrove in #1328
- Return a directory listing when the files API is asked for a directory by @BinSquare in #1330
- Fail a delete that needs confirmation when stdin is not a terminal, instead of reading EOF as a decline and exiting successfully by @BinSquare in #1333
- Run the image's own entrypoint for a cached --oci-cache run instead of the bake's no-op placeholder by @BinSquare in #1335
- Provision the --oci-cache bake without launching a workload so images without /bin/true can be cached by @BinSquare in #1340
- Give a clone a host port the kernel will not reassign before it binds by @BinSquare in #1341
- Rebuild libkrun so aarch64 machines can branch again by @BinSquare in #1342
- Make incremental checkpoints reusable as a Rust crate by @BinSquare in #1344
- Reserve every recorded host port so a clone is never given a stopped machine's port by @BinSquare in #1345
- Forward CLI --secret-env/--secret-file secrets to the workload on the oci-cache and pack-ref run paths by @BinSquare in #1343
- Save checkpoints without staging a second RAM copy by @BinSquare in #1305
New Contributors
Full Changelog :
v1.16.2...v1.17.0 -
🔗 gildas-lormeau/single-file-cli v2.15.4 release
SingleFile CLI 2.15.4
Changes
- single-file-core is updated to 1.6.9, see https://github.com/gildas-lormeau/single-file-core/releases/tag/v1.6.9. For the CLI it means that a rule the capturing browser rejects, because one selector of its list is unsupported there, no longer hides a rule that browser actually draws: with
--browser-engine firefoxthe lists of a shared Gemini conversation kept their indent, where they used to fall back to the browser default
Co-authored by Claude (Claude Code)
- single-file-core is updated to 1.6.9, see https://github.com/gildas-lormeau/single-file-core/releases/tag/v1.6.9. For the CLI it means that a rule the capturing browser rejects, because one selector of its list is unsupported there, no longer hides a rule that browser actually draws: with
-
🔗 MetaBrainz MusicBrainz Server update, 2026-09-21 rss
Hi! It's been a while since our last release since we have been working on stability improvements for both website and search to better cope with all the load we are handling recently. The first related changes are part of this release, with more to come, including limiting searches to 500 results (if you need something further down the search, sorry but you probably need a better search!). Additionally, the very annoying bug that sometimes lost track times when parsing tracklists should hopefully be gone now (thanks dvirtz!), and a lot more aggregator and shortener links are now blocked; even when not yet blocked, remember to always add all the relevant destination links rather than redirects and aggregators if possible.
A new release of MusicBrainz Docker is also available that matches this update of MusicBrainz Server. See the release notes for update instructions.
Thanks to derat, dvirtz, ibmibmibm and mib for having contributed to the code. Thanks to DenizC, derat, dvirtz, HibiscusKazeneko, j.rohr, outsidecontext, Raman Sinclair, rinsuki and salo.rock for having reported bugs and suggested improvements. Thanks to AligFu, AndrejsD1718, BestSteve, blueday, Covium, Denatura, EmO686, Flavia Telcean, joao_over9k, Kolesteraw, Life4649, liilliil, mfmeulenbelt, naturbrilian, NorwayFun, Priit Jõerüüt, pXF, syntariavoxmortem, TheParaziT, Vaclovas Intas, vacuousVersifier and wileyfoxyx for updating the translations. And thanks to all others who tested the beta version!
The git tag is v-2026-09-21.0.
Fixed Bug
- [MBS-9526] - Parser removes times, despite "use track times" being unchecked
- [MBS-10767] - "more" and "less" on rel types list are not translatable
- [MBS-14386] - Series of series doesn't show parts as a list, only on relationships section
- [MBS-14398] - Collection checkbox in header doesn't work
- [MBS-14440] - Webservice requests can return authenticated data on unauthenticated requests
- [MBS-14448] - Memory leak in Data::Relationship::_new_from_row
Improvement
- [MBS-14192] - Require visiting tracklist tab when adding release
- [MBS-14399] - Accept new /a LibraryThing author URLs
- [MBS-14404] - Reject Facebook "share" URLs
- [MBS-14415] - Strip locale and mibextid in Facebook URL cleanup
- [MBS-14423] - Reject Google "share" URLs
- [MBS-14424] - Block Pinterest URL shortener
- [MBS-14439] - Block (yet) more smart links
- [MBS-14425] - Block smart links: drum.io
- [MBS-14426] - Block smart links: ffm.bio
- [MBS-14427] - Block smart links: social.tunecore.com
- [MBS-14428] - Block smart links: frontl.ink
- [MBS-14429] - Block smart links: gyro.to
- [MBS-14430] - Block smart links: paa.ge
- [MBS-14432] - Block smart links: linkin.bio
- [MBS-14433] - Block smart links: beacons.ai
- [MBS-14435] - Block smart links: fanbase.to
- [MBS-14436] - Block smart links: soundon.global
- [MBS-14437] - Block smart links: imusician.pro
- [MBS-14438] - Block smart links: musics.to
- [MBS-14443] - Support Boomplay’s new non-numeric URL format
- [MBS-14450] - Improve error / rejection messages for URL shorteners and aggregators
- [MBS-14455] - Limit the depth of search to 500 results
Task
- [MBS-14382] - Update the Amazon logo used in the sidebar
-
🔗 pydantic/monty v1.0.0-beta.2 - 2026-09-21 release
What's Changed
- bump to b2, fix
monty-proto's self dev-dependency by @samuelcolvin in #908
Full Changelog :
v1.0.0-beta.1...v1.0.0-beta.2 - bump to b2, fix
-
🔗 microsoft/markitdown Version 0.1.8 release
This release rolls up dozens of small patches and bug fixes. For typical inputs and use cases, we expect outputs and behavior to remain largely unchanged from version 0.1.7.
The markitdown-ocr plugin has also been refactored to simplify future maintenance.
What's Changed
- Mitigate UnicodeDecodeError due to wrong ASCII charset guess for long files by Fabio Catalano (@fcatalan92) in #2360
- fix: support extended content-disposition filenames by Rāna(Bass Ver.) (@cat0825) in #2045
- fix: fall back to plain text when RSS item content triggers RecursionError by Jeremy Schoemaker (@shoemoney) in #2333
- fix(cli): allow Content Understanding conversion from stdin by Tyyyy (@uczltw6) in #2318
- fix: correct \underleftarrow macro and map math italic h in equation conversion by Guillermo Dols (@gdols) in #2293
- feat(cli): support MARKITDOWN_CU_ENDPOINT / MARKITDOWN_DOCINTEL_ENDPOINT by Sinan Olsson-Pasic (@seenws) in #2358
- fix(csv): strip the UTF-8 BOM and skip blank rows before building the table by Ruiming Zhao (@uuzzrm) in #2303
- Preserve strikethrough from
and CSS line-through by Gyanu Mayank (@gyanu2507) in #2342 - Fix percent-encoded Windows drive paths in file URIs by Zhewen Tan (@tandede) in #2315
- fix: escape pipes and newlines in CSV values by Asjad Abbas (@asjad3) in #2266
- fix(epub): safely extract metadata text without crashing on None nodeValue or nested elements by Henry Su (@hsusul) in #2247
- fix: handle math run with no text child in OMML->LaTeX conversion by S1MS4 in #2189
- fix: IpynbConverter.accepts() catches UnicodeDecodeError on non-decodable content (fixes #1894) by hanhan761 in #1929
- fix(docx): ignore malformed styles missing type by S M (@gingerninja85) in #2190
- Preserve percent-encoded octets in href paths by Sonai Biswas (@Sonai124) in #2173
- fix: remove extra closing brace from caron and ring-above accent templates by Andrew Avery (@AndrewAvery7) in #2279
- fix: preserve strikethrough semantics for
, line-through CSS, and w:dstrike by MOHAMMED WASIM KHAN (@wasim-builds) in #2356 - fix: buffer CLI stdin before format detection on Windows by Mo Hui (@mohui666) in #2351
- fix(rss): preserve Atom XHTML content by will wang (@weivwang) in #2297
- fix: initialize md_text in _parse_rss_type to prevent UnboundLocalError by Sai Medavarapu (@smedavarapu1) in #2164
- fix: ZipConverter renders '(unknown)' instead of literal 'None' when stream has no source info by JSap0914 in #2134
- fix: truncate uppercase data image URIs by Lucas Ma (@pony-maggie) in #2122
- fix(doc-intel): default api_version to None in DocumentIntelligenceConverter by Nefelibata (@MeiSiristhebest) in #2267
- fix(outlook): read .msg string properties saved in the non-Unicode format by Guillermo Dols (@gdols) in #2295
- fix: handle URI schemes case-insensitively by Lucas Ma (@pony-maggie) in #2121
- fix: normalize data URI parameter case by Lucas Ma (@pony-maggie) in #2120
- fix(xlsx): tolerate legacy showZeroes sheet views by Yufeng He (@he-yufeng) in #2064
- docs: use canonical markdown result property by Sheroy Cooper (@CooperSheroy) in #2259
- fix(youtube): handle missing title metadata without raising AssertionError by Henry Su (@hsusul) in #2238
- fix(ipynb): preserve leading # in notebook heading titles by Cpthimself (@Alphaxiaoteng) in #2371
- fix(docx): preserve underlined text by Yufeng He (@he-yufeng) in #2017
- fix(pptx): ignore empty llm captions by Lubrsy (@Lubrsy706) in #1886
- fix: PptxConverter tolerates None shape.text and notes text by Alvin Tang (@alvinttang) in #2059
- fix(pptx): prevent crash in PptxConverter when chart title lacks a text frame by aoright (@aoright) in #2194
- fix: catch OSError when exiftool binary is missing (#1960) by 王艺霖 (@doitgo) in #2082
- Fix exiftool JSON decoding to use UTF-8 by Vedant (@Vedant43hh) in #2067
- fix: WikipediaConverter renders hash None heading when page has no title by hanhan761 in #1990
- fix: guard against missing oMath element in DOCX math converter (#1979) by hanhan761 in #1995
- fix: handle DOCX files with inconsistent ZIP filename casing (#1812) by liyrds (@lyydsheep) in #2016
- Support short YouTube URLs by Mukunda Rao Katta (@MukundaKatta) in #1882
- fix: suppress pydub RuntimeWarning when ffmpeg is missing (fixes #1685) by hanhan761 in #1985
- chore: remove unused mammoth import from PlainTextConverter (#1951) by hanhan761 in #1953
- fix(rss): treat Atom text content and summary as plain text by Lazizbek Ergashev (@lazerg) in #2374
- fix: ImageConverter gracefully handles LLM API failures (fixes #1942) by hanhan761 in #1948
- fix(docx): handle unknown math functions in OMML converter without crashing by Nefelibata (@MeiSiristhebest) in #2268
- Update README to help scope PRs. by afourney in #2376
- Be sure to run the proper Python version. by afourney in #2379
- fix(pptx): chart_title.text_frame is never None — use has_text_frame instead by kapil971390 in #2385
- Preserve all CSV columns by matching the widest row by afourney in #2430
- Fix CSV parsing for CR-only line endings by Kim Do Yeon (@tkv00) in #2412
- fix(rss): support namespace-prefixed Atom feeds by Xing Zheng (@Elysium-Seeker) in #2429
- fix(rss): drop layout whitespace from feed and entry titles by kevin (@kevin9327) in #2428
- fix(pptx): do not emit a Notes heading for a slide with no notes by kevin (@kevin9327) in #2427
- fix(ipynb): strip the UTF-8 BOM so a notebook is not emitted as raw JSON by kevin (@kevin9327) in #2425
- fix(rss): preserve complete feed content and resolve relative link by afourney in #2432
- fix(epub): forward conversion options to the HTML converter by kevin (@kevin9327) in #2426
- Update Docker images to Debian trixie (Python 3.13-slim-trixie) by Erwin Kersten (@erwinkersten) in #2421
- Fix Zip converter forwarding kwargs to nested conversions by SpongeBob (@As9xm) in #2409
- Do not convert an undecodable file to the word "None" by kevin (@kevin9327) in #2418
- Fix PPTX shape sorting treating top-zero as missing by SpongeBob (@As9xm) in #2408
- fix(epub): resolve percent-encoded manifest hrefs to ZIP entries by Sushant Lokhande (@sushantlokhande14) in #2413
- Fix --list-plugins help text to reference correct --use-plugins flag by freetg71527152-ui in #2381
- fix: prefer data-src over placeholder data URI in img src by Machen John (@macjayz) in #2417
- fix(zip): preserve content of entries with duplicate filenames by liyrds (@lyydsheep) in #2434
- fix(pptx): do not emit a heading for a slide with an empty title by kevin (@kevin9327) in #2442
- fix(mcp): migrate to MCP SDK 2.x so 2026-07-28 clients can connect by Çağdaş Yürekli (@cagdasyurekli) in #2363
- Reject UNC and Windows device paths (similar to how netlocks are alre… by afourney in #2452
- Expand test matrix to include windows-latest by afourney in #2453
- Added file paths tests. by afourney in #2454
- Add arm to matrix. Simplify matrix. by afourney in #2459
- Workaround for ARM CI tests. by afourney in #2460
- Fix ANSI Outlook MSG decoding for Japanese code pages and padded strings by afourney in #2462
- Trim CSV blank runs without repeatedly shifting the row list by dickbown (@ROTl24) in #2450
- Improve efficiency of escaping pipes in CSVs by afourney in #2464
- fix: avoid splitting UTF-8 characters during charset detection by afourney in #2466
- fix(docx): preserve namespaces when repairing stylesheets by afourney in #2467
- fix(youtube): fall back to HTML when no video content is extracted by afourney in #2469
- Throw an error when llm client fails with image converter. by afourney in #2476
- Preserve whitespace underlines by afourney in #2477
- Refactor Office OCR converters to reuse core conversion pipelines by afourney in #2506
- fix: bump youtube-transcript-api to >=1.2.3 for Python 3.14 support by Nithin Jambula (@nithin434) in #2407
New Contributors
- Dan Fiedler (@danfiedler-msft) made their first contribution in #2316
- Fabio Catalano (@fcatalan92) made their first contribution in #2360
- Rāna(Bass Ver.) (@cat0825) made their first contribution in #2045
- Jeremy Schoemaker (@shoemoney) made their first contribution in #2333
- Tyyyy (@uczltw6) made their first contribution in #2318
- Guillermo Dols (@gdols) made their first contribution in #2293
- Sinan Olsson-Pasic (@seenws) made their first contribution in #2358
- Ruiming Zhao (@uuzzrm) made their first contribution in #2303
- Gyanu Mayank (@gyanu2507) made their first contribution in #2342
- Zhewen Tan (@tandede) made their first contribution in #2315
- Asjad Abbas (@asjad3) made their first contribution in #2266
- Henry Su (@hsusul) made their first contribution in #2247
- S1MS4 made their first contribution in #2189
- hanhan761 made their first contribution in #1929
- S M (@gingerninja85) made their first contribution in #2190
- Sonai Biswas (@Sonai124) made their first contribution in #2173
- Andrew Avery (@AndrewAvery7) made their first contribution in #2279
- MOHAMMED WASIM KHAN (@wasim-builds) made their first contribution in #2356
- Mo Hui (@mohui666) made their first contribution in #2351
- will wang (@weivwang) made their first contribution in #2297
- Sai Medavarapu (@smedavarapu1) made their first contribution in #2164
- JSap0914 made their first contribution in #2134
- Lucas Ma (@pony-maggie) made their first contribution in #2122
- Nefelibata (@MeiSiristhebest) made their first contribution in #2267
- Yufeng He (@he-yufeng) made their first contribution in #2064
- Sheroy Cooper (@CooperSheroy) made their first contribution in #2259
- Cpthimself (@Alphaxiaoteng) made their first contribution in #2371
- Lubrsy (@Lubrsy706) made their first contribution in #1886
- Alvin Tang (@alvinttang) made their first contribution in #2059
- aoright (@aoright) made their first contribution in #2194
- 王艺霖 (@doitgo) made their first contribution in #2082
- Vedant (@Vedant43hh) made their first contribution in #2067
- liyrds (@lyydsheep) made their first contribution in #2016
- Mukunda Rao Katta (@MukundaKatta) made their first contribution in #1882
- Lazizbek Ergashev (@lazerg) made their first contribution in #2374
- kapil971390 made their first contribution in #2385
- Kim Do Yeon (@tkv00) made their first contribution in #2412
- Xing Zheng (@Elysium-Seeker) made their first contribution in #2429
- kevin (@kevin9327) made their first contribution in #2428
- Erwin Kersten (@erwinkersten) made their first contribution in #2421
- SpongeBob (@As9xm) made their first contribution in #2409
- Sushant Lokhande (@sushantlokhande14) made their first contribution in #2413
- freetg71527152-ui made their first contribution in #2381
- Machen John (@macjayz) made their first contribution in #2417
- Çağdaş Yürekli (@cagdasyurekli) made their first contribution in #2363
- dickbown (@ROTl24) made their first contribution in #2450
- Nithin Jambula (@nithin434) made their first contribution in #2407
Full Changelog :
v0.1.7...v0.1.8 -
🔗 gildas-lormeau/single-file-cli v2.15.3 release
SingleFile CLI 2.15.3
CLI fixes and improvements
- A JavaScript dialog opened by the page no longer stalls the capture. The browser stops the page until a dialog is answered and the CLI answered none, so an
alert()in an inline script ended in "Load timeout" with no file, and one fired after load hung the process past every timeout. The dialog is now dismissed as soon as the browser reports it and the page runs on as if the user had closed it:confirm()returns false andprompt()null. Abeforeunloaddialog is accepted so the navigation proceeds - When a page stops answering during load, the fallback that stops the load and captures what is there is now bounded by the capture timeout instead of waiting for ever
Changes
- single-file-core is updated to 1.6.8, see https://github.com/gildas-lormeau/single-file-core/releases/tag/v1.6.8. For the CLI it means that a rule written directly inside an
@scopeblock with a selector starting with a combinator is no longer removed as unused, which restored the spacing of shared Gemini conversations; that theonbegin,onendandonrepeathandlers of SVG animation elements are removed with the other event handlers when scripts are blocked; and that the infobar's expanding ring no longer replays each time the infobar is folded back
Co-authored by Claude (Claude Code)
- A JavaScript dialog opened by the page no longer stalls the capture. The browser stops the page until a dialog is answered and the CLI answered none, so an
-
🔗 earendil-works/pi v0.87.0 release
New Features
- Canonical session context and extension boundaries — Edit model context without rewriting history and add actionable lifecycle hooks. See ContextEditEntry and extension events.
- Full-transcript context extensions — Use
context_with_systemfor per-request system-message transformations. Seecontext_with_system. - Per-model image input limits — Configure cache-safe image resizing per model for attachments,
read, and tool-result images. See Image Input Limits.
Breaking Changes
- Removed the inherited
shouldStopAfterTurnagent option. UsefinishTurnand return{ action: "end" }instead.finishTurnruns beforeturn_endbut applies the decision afterward, and it also receives error and aborted responses; migrate normal-response predicates by returningundefinedfor those hard exits. See the@earendil-works/pi-agent-corechangelog for a complete before-and-after example. - Added
ContextEditEntryto the exportedSessionEntryunion. TypeScript consumers with exhaustive entry switches must handlecontext_edit; usereplacement: nullfor omission and a content replacement otherwise. - Made
SessionManagercanonical forAgentSessionprovider context. Assigningsession.agent.state.messagesno longer replaces future request history; restore withSessionManager.inMemory(cwd, { id }, entries), navigate withsession.navigateTree(), or append throughsession.sessionManagerand callsession.refreshContext(). - Expanded
TurnEndEventwith required boundary fields and addedAgentBeforeSettleEventto the exportedExtensionEventunion. Consumers constructing events or exhaustively switching onExtensionEventmust handle the new shapes.ExtensionRunner.emit()no longer acceptsturn_end; host integrations dispatch actionable boundaries withemitBoundary(baseEvent, buildContext). - Deferred runs requested from
agent_settledhandlers until all settled handlers finish. Handlers still observectx.isIdle() === true, but no longer see a reentrantagent_startduring the same notification dispatch.
Added
- Added append-only model-context edits. For example,
sessionManager.appendContextEdit(entryId, null)omits one message from future provider context without changing raw history, usage, or UI history. - Added actionable
turn_endandagent_before_settleextension boundaries. Return{ entries: [...event.entries, draft], continue: true }to persist structural entries in order and ensure one next provider request without changing steering or follow-up scheduling. - Added retain-none compaction input:
sessionManager.appendCompaction(summary, null, tokensBefore)stores the compaction's own ID as its kept boundary. - Added the
context_with_systemextension event, which runs aftercontexthandlers on the full transcript including system messages and sends its result verbatim. Seecontext_with_system. - Added per-model image resize profiles through
inputLimits.images.resizeinmodels.json, applied to file attachments, image reads, and tool-result images (#9631).
Fixed
- Fixed string context-edit replacements producing invalid assistant and tool-result message content instead of text blocks.
- Fixed context-invisible boundary metadata and replacement edits causing newly appended or replaced input to be summarized before its first provider request.
- Fixed edited-context accounting both discarding valid assistant usage captured after the latest context edit and reusing that usage after a later compaction made it stale.
- Fixed selected error retries and final length/overflow recovery retaining abandoned model attempts in future provider context; post-run recovery omissions are now persisted without hiding raw transcript history or changing queue scheduling.
- Fixed
contexthandlers that filter or slice messages dropping the prompt and tool declarations, which after extension-driven compaction left requests without built-in tools or made Codex emit raw tool-call text. Handlers no longer see system messages; Pi restores the prompt and tool state after they run. Seecontext(#9789, #9822). - Fixed
/bugallowing uploads in offline mode while preserving local zip exports (#9841 by @christianklotz). - Fixed idle prompt-cache warming rebuilding expired caches when its timer or an extension decision is delayed.
- Improved crash diagnostics with hints identifying loaded extensions that appear in the stack trace.
- Fixed text files beginning with
GIFbeing misclassified as images and omitted fromreadand CLI@fileinput (#9755). - Fixed malformed prompt template frontmatter being silently ignored instead of reported as a resource warning (#9830 by @christianklotz).
- Fixed inherited unknown OpenAI-compatible Chat Completions endpoints receiving strict tool schemas unless they explicitly advertise support (#9816).
-
🔗 pydantic/monty v1.0.0-beta.1 - 2026-09-21 release
What's Changed
- Drop the experimental framing ahead of v1 by @rewitt94 in #811
- Percent formatting:
'...' % fooandb'...' % barby @samuelcolvin in #825 - fix flakey js test by @samuelcolvin in #826
- Implement the
format()builtin by @samuelcolvin in #827 - Answer
date.today()/datetime.now()in standard execution by @rewitt94 in #812 - Implement remaining math aggregation functions and
fmaby @samuelcolvin in #831 - fix telemetry context propagation by @davidhewitt in #830
- Support
print(file=sys.stderr)by @rewitt94 in #818 - Finish
binasciiwith the uu, quoted-printable and CRC-16 conversions by @rewitt94 in #816 - Build Python 3.14t wheels by @Kludex in #832
- make it possible to run smoke test from npm by @davidhewitt in #619
- fix browser smoke test install by @samuelcolvin in #844
- Move examples-only Python deps out of the dev group by @samuelcolvin in #849
- Match CPython for int/float arithmetic on long ints and float pow overflow by @samuelcolvin in #834
- Make the
examplesdependency group opt-in by @samuelcolvin in #852 - CWD support by @samuelcolvin in #828
- Add a watchdog for the CPython side of test cases and deflake
lookup__mutation.pyby @samuelcolvin in #854 - Accept long ints across
pow(),round()and themathmodule by @samuelcolvin in #853 - Eager awaits by @samuelcolvin in #833
- Better
casefoldand other case methods compatibility by @samuelcolvin in #857 - Deps update by @samuelcolvin in #859
- Add the remaining
itertoolscallables barteeby @samuelcolvin in #860 - Revert itertools by @samuelcolvin in #861
- Support runtime definition of types like
tuple[int, str]anddict | dictby @samuelcolvin in #858 - Implement the
sysconstants with a known value by @samuelcolvin in #863 - Support attribute and subscript targets in unpacking by @samuelcolvin in #865
- Add the antigravity example, running Monty in the browser by @samuelcolvin in #864
- Fix re-entrant source windows in
chain,pairwiseandaccumulateby @rewitt94 in #843 - Missing
itertoolsmethods by @samuelcolvin in #862 - Add a regression test for the trailing-slash symlink escape by @samuelcolvin in #868
- Add the
randommodule and anos.urandomhost call by @samuelcolvin in #867 - Add the
copymodule by @rewitt94 in #791 - Check container growth against the memory limit before it allocates by @rewitt94 in #845
- Follow-ups for
datetimeby @rewitt94 in #838 - Fix two container-reentrancy panics by @rewitt94 in #846
- don't make static strings a requirement for dump stability by @davidhewitt in #810
- establish tampered snapshots as permitted: garbage in garbage out by @davidhewitt in #873
- Fix async task scheduling for batched host failures by @flyingmutant in #875
- Give each callable type its own
PyTrait::py_callby @rewitt94 in #878 - Flat layout for wire value type by @samuelcolvin in #871
- Serialize dumps after the header in place, without a second buffer by @samuelcolvin in #881
- Shrink the largest dag decode bench to fit the decode budget by @samuelcolvin in #883
- remove needless
SOFT_LIMITvariable frommonty-allocby @davidhewitt in #763 - Add
time.time(),time.sleep()andasyncio.sleep()by @samuelcolvin in #866 - expose otel trace context from snapshots by @davidhewitt in #885
- purge
pool-architecture.mdby @davidhewitt in #887 - Replace session
max_durationwith feed and turn limits by @rewitt94 in #880 - add a general solution for wire decoding budgets by @davidhewitt in #874
- try to hide object internals by @davidhewitt in #886
- fix merge conflict by @davidhewitt in #891
- Comment and documentation fixes by @rewitt94 in #888
- Sort
StaticStringsalphabetically by @rewitt94 in #889 - Change
DumpErrorfor future compatibility by @rewitt94 in #890 - Implement
eval(),exec()andlocals()by @samuelcolvin in #855 - Auto OS calls by @samuelcolvin in #892
- Use sleep and random in the antigravity example by @samuelcolvin in #897
- Timezone support by @samuelcolvin in #898
- Poll the time limit in large three-argument pow by @samuelcolvin in #899
- Reject overlapping host directories at mount registration by @samuelcolvin in #741
- Extend
timemodule by @samuelcolvin in #901 - Replace wire types with whitelist of allowed types, and proxy for everything else by @samuelcolvin in #900
- Rename
AutoOsCallstoOsPolicyby @samuelcolvin in #902 - Resolve exception classes directly and model them inbound by @samuelcolvin in #905
- Describe Monty as a sandbox and name the open-source form "OSS Monty" by @samuelcolvin in #904
- Uprev
ruff, pre-check source by @samuelcolvin in #906 - Bump to v1.0.0-beta.1 by @samuelcolvin in #903
New Contributors
- @Kludex made their first contribution in #832
- @flyingmutant made their first contribution in #875
Full Changelog :
v0.0.23...v1.0.0-beta.1 -
🔗 r/LocalLLaMA How it feels watching prices go up rss
| submitted by /u/Hyacin75
[link] [comments]
---|--- -
🔗 exe.dev Caring vs. Knowing rss
A few months ago, I wrote about how AI is disrupting the build-vs-buy equation in SaaS. I argued that the real value of SaaS over most DIY software is knowing what good looks like. But a few recent events have made me realize that knowing in and of itself is not enough.
“Good” changes. Users evolve, surrounding systems shift, and expectations rise. And the rate of change somehow continues to increase, making us feel the technological jerk of products in our daily life. Building something valuable requires knowing what good looks like today. Maintaining (or even increasing) that value requires caring enough to keep learning what good will look like tomorrow.
In a conversation with Betty Junod on my podcast Third Loop, we discussed the idea of an application with an Ideal Customer Profile, or ICP, of one. Betty’s point was that the cost reduction that comes from an agent building your app makes it reasonable to build an app that only you will use. This is liberating for people who have an idea or need, but previously lacked the coding skill or resources to make a computer do things they considered useful.
If you are the ideal customer, you know what good looks like and understand the constraints because you are the only user. But what happens when you’re building for more than just one customer? The challenge is the same whether you are building an app to store your recipes or a service to monitor VM utilization. As the number of users increases, answering what good looks like becomes more challenging. Humans have the amazing ability to solve the same challenge with incredible variety. Your definition of good may vary slightly from your next user’s. As the number of users grows to hundreds or thousands, the variations—and resulting complexity—can multiply rapidly.*
*Yes, humans can use em dashes appropriately.
Choose Your Own Adventure
In the old world, this is where DIY often broke down. You’d add personalization or customization, but it had a cost, both in the building as well as maintaining the increasing complexity of a system. For many SaaS companies, this led to narrowly scoping the ICP and then expanding features over time to meet the needs of more people.
This approach was sustainable for the SaaS provider, but meant that users had to conform to the provider’s view of the workflow. It also meant that providers built new features against rigid, explicit user stories and happy- path workflows.
In this new world of free code, what if we could let the user build the experience they wanted? Give the user access to the agents that build the features. This starts to change the way we think about designing products. We may need to think more about designing primitives and building blocks and not just a single fixed user path.
Of course, as we look to acknowledge that each user is a snowflake we quickly realize that different users care about different things. A default setting for one user may be appreciated, while for another it is a deal-breaker that ruins their experience. Some users want a product to make all the choices for them, while others wish they could have control down to the bit level for every interaction.
Put another way, sometimes you want to buy a pre-made sandwich, and sometimes you want to bake your own bread from the wheat you harvested and milled yourself. And most people, most of the time, are somewhere in between. We are finally at a point where we can build for—and with—users across this spectrum.
So, as we build our choose-your-own-adventure platforms, selecting good defaults and caring about what good looks like over time is what keeps a growing user base happy. It’s great to have a computer make all the choices for you when they are the choices that you want. But building a system that makes all the right choices remains aspirational. For now, we can try to build systems that adapt to our personal “right” choices faster than we have in the past.
Ever-Changing “Good”
Another critical aspect of this is that “good” can change over time. In 1440, when Gutenberg made the first printing press, his list of requirements was a bit different from the last laser printer I purchased from Costco. The rate of change that is acceptable to the user is also a factor. If your ICP is slower to adapt to change, either by comfort or regulation, you need to plan accordingly.
How do you ensure that your product or service continues to be good? How do you monitor for drift—either in your product quality or in your ICP needs? Product quality isn’t just your uptime. Users rarely use products in a vacuum, especially SaaS. Other services provide input and users need the output to feed into other places. And the needs of these inputs and outputs are changing faster today than ever before.
At the end of the day, knowing what good looks like is a point-in-time judgment, while caring about what good looks like is an ongoing task. You have to spend effort observing and processing usage patterns and feedback. Even as we build a platform that can be augmented and updated by our users, we still have to observe and listen to both new and existing users and incorporate learnings into our design and build process. This means your product is never “done” or “finished.” It also means that, as a builder, you may have to let go of the idea that your product will be used the way you intended.
Free, Like Puppies
Puppies are not free. Food, toys, vet visits, and time all add up, regardless of the initial cost. This has long been a comparison used for open source software. And it needs to be acknowledged that unrestricted customization can have the same risk.
In this new era of “I can build anything,” this often means you first have to make a choice, “do I care enough about what good looks like for this product to own the maintenance and upkeep?” This isn’t just about upgrading, patching, CVEs, and performance (although that is a big part of it). Handing users the controls to change your product also runs the risk that they’ll make changes they regret. Or, when the choice is good for the user, it may restrict your optionality in the future if desired core product changes break their customization.
Different types of people have different tolerances for build-vs-buy. There are people like Josh, who look at the world and say, "I could build that myself," and then do. Or people like my brother who will pay for other people to build everything. And then some who tinker in between. Either way, someone still has to feed the puppy.
-
🔗 r/LocalLLaMA 16GB (and in many cases 12GB) is the max vram most people will ever reasonably have rss
This sub is, needless to say very niche and skewed towards the high end. There are tons of extremely high end setups here with multiple gpu's etc.
Even 24GB is out of reach of most people financially, forget about the 3x3090 or 5090 or even higher setups. Macs/Strix Halo/dgspark etc are all similarly expensive. 16GB is pretty much the high end for most. And this completely changes in most of the rest of the world where even 12GB would be a luxury.
Things have changed recently (I think even last 6 months have been huge) and even agentic coding is now feasible on 16GB cards (eg with Qwen 27B quants).
I think/hope things will continue to improve. Of course there's going to be a hard limit on how much world knowledge these smaller models will have.
The holy grail is new architecture that supercedes the Transformer and new techniques that don't depend on vram/bandwidth.
and
submitted by /u/ECrispy
[link] [comments] -
🔗 HexRaysSA/plugin-repository commits sync repo: +3 releases rss
sync repo: +3 releases ## New releases - [clang-include](https://github.com/oxikkk/ida-clang-include): 1.3.0 - [haruspex](https://github.com/0xdea/haruspex): 0.10.1 - [rhabdomancer](https://github.com/0xdea/rhabdomancer): 0.10.1 -
🔗 Project Zero Windows Exploitation Techniques: Dangling COM Object Registrations rss
This short blog post is about abusing a privilege escalation bug that Microsoft recently fixed in Windows, CVE-2026-66804, that I and 14 others reported. This issue is an incomplete fix for CVE-2026-50343, a bug dubbed “Dark Elevator” by Calif.
The root cause of the bug was a dangling COM object registration for the CrossDevice COM object with the CLSID
{E9F83CF2-E0C0-4CA7-AF01-E90C70BEF496}. A COM registration typically needs two parts: a server executable, which for in-process components is a DLL and a CLSID entry under theHKEY_CLASSES_ROOTregistry key which points to that DLL.This object was registered in the system wide classes key, meaning it was accessible to all users on the system, including system services. However the server executable was missing. Specifically it was registered to use the DLL
%PROGRAMDATA%\CrossDevice\CrossDevice.Streaming.Source.dll. Not only does this path not exist, it’s also within theC:\ProgramDatadirectory. This is a common location for all users on the system and therefore permits anyone to create directories. Therefore you can create an arbitrary DLL file at that location and the COM object can be instantiated potentially leading to privilege escalation.But how to get the COM object, and thus the DLL, loaded into a privileged process? The fixed bug Calif blogged about, CVE-2026-50343, abused a weak registry key permissions to add the class as a installer plugin and then get the
InstallServiceto load it into memory. The issue with the InstallService was fixed, so we need an alternative way to abuse the unfixed dangling COM reference.Abuse Custom COM Marshaling, Again
A technique I’ve used multiple times in the past to load an arbitrary DLL into a privileged process is to abuse custom COM marshaling. When you call an interface method which is implemented out-of-process, the COM runtime will marshal the parameters into an RPC call to send to the server. If a parameter is a COM object then the runtime marshals that object into an OBJREF structure that allows the object to be used in the server. The two main types of OBJREFs are shown in the diagram below, or you can read about them in the official DCOM documentation here:

The default COM marshaling strategy is by reference which produces a Standard OBJREF containing all the information needed to connect to the original object. The object might even be on a completely different computer. When the object is unmarshaled this information is used to create an RPC channel back to the caller so that the server can call methods on the object.
The runtime also supports an opt-in marshal by value mechanism if the object implements the IMarshal interface. This allows the object to specify an arbitrary CLSID to use as the unmarshaling object, which doesn’t have to be the same as the object being passed in. When the object is unmarshaled in the server the CLSID is used to lookup an in-process server DLL to load.
Therefore an obvious technique to exploit the dangling COM object registration is to send a Custom OBJREF to a privileged COM service specifying the CLSID of the dangling object. When unmarshaled, which happens automatically in the runtime before the target method is called, the malicious DLL will be loaded and we’d get privilege escalation. The following code shows how trivial it is to specify the dangling COM class in an
IMarshalimplementation:class FakeMarshal : public IMarshal { // Inherited via IMarshal HRESULT GetUnmarshalClass(REFIID riid, void* pv, DWORD dwDestContext, void* pvDestContext, DWORD mshlflags, CLSID* pCid) override { return CLSIDFromString(L"{E9F83CF2-E0C0-4CA7-AF01-E90C70BEF496}", pCid); } // ... };We need to find a privileged service to send the marshaled COM object to become an administrator. Unfortunately, finding such a service isn’t so simple. The fact that a custom marshaling object will cause an arbitrary DLL to be loaded into the process and code executed is a risky operation, especially across privilege boundaries. Therefore Microsoft implemented a mitigation which can be enabled to disable custom marshaling in the process unless the class is explicitly opted in, or is one of a small number of trusted components such as classes in the runtime library.
Since Windows 8 this mitigation is implemented through two mechanisms, the first and original method is setting the
EOAC_NO_CUSTOM_MARSHALcapabilities flag when calling CoInitializeSecurity. The second, added to improve security in AppContainer sandboxes is set through the IGlobalOptions::Set method and specifying theCOMGLB_UNMARSHALING_POLICYproperty type. As we’re not trying to escape from a sandbox the only value of importance isCOMGLB_UNMARSHALING_POLICY_STRONGwhich disables custom marshaling similar to the capabilities flag.As the dangling COM object isn’t registered as a trusted marshaler this means we need to find a privileged COM server that doesn’t enable these mitigations. The easiest approach is to scan the processes at runtime. The capability flags are stored in the value
combase!gCapabilitieswhile the marshaling policy is stored incombase!g_GLBOPT_UnmarshalingPolicy.However, I kept thinking there must be a COM service that runs as SYSTEM and doesn’t enable custom marshaling. After a bit of fiddling I found one, although there’s no doubt others. It turned out to be a COM service I’ve researched and exploited before, the
Shell Create Object Handlerobject. This is an interesting COM object, in that while it runs in a SYSTEM service, it’s not directly instantiable:PS> $cls = Get-ComClass -Clsid 135fd325-45b7-4c30-89f8-4386961669f0 PS> $o = New-ComObject -Class $cls Exception calling "CreateInstanceAsObject" with "3" argument(s): "Class not registered" PS> $cls.AppIdEntry | Select Name, RunAs, IsService Name RunAs IsService ---- ----- --------- Shell Create Object Handler nt authority\system FalseNormally, when a COM object is hosted by a privileged service, it’s registered with the name of a system service that RPCSS will start automatically when the object class is requested. However, in this case as there’s no service,creating the object fails with a “Class not registered” error. In order to create the COM server, the service needs to already be running as the SYSTEM user before you call
CoCreateInstance.Instead you have to start the privileged server via the
\Microsoft\Windows\Shell\CreateObjectTaskscheduled task. Fortunately this task can be started by normal users, which you can verify with myGet- AccessibleScheduledTaskcommand:PS> Get-AccessibleScheduledTask -Executable | ? Name -Match Shell\\CreateObjectTask TokenId Access Name ------- ------ ---- 77E3156D GenericExecute|GenericRead ...\Shell\CreateObjectTaskOf course just starting this task is not enough, you also need to create a global named event,
ShellCreateObjectTaskReadyEventotherwise the task will immediately exit and not export the COM service. A simple script to create an instance is shown below:PS> $ev = New-NtEvent -Win32Path "Global\ShellCreateObjectTaskReadyEvent" -InitialState $false PS> Start-ScheduledTask -TaskPath "\Microsoft\Windows\Shell\" -TaskName "CreateObjectTask" PS> $ev.Wait() PS> $o = New-ComObject -Clsid "135fd325-45b7-4c30-89f8-4386961669f0" PS> $o InterfaceName Iid ------------- --- IUnknown 00000000-0000-0000-c000-000000000046You can verify that the object is hosted in a privileged process with the
Get-ComProcesscommand and checking theCustomMarshalAllowedproperty. Note this command is currently broken on Windows 11 25H2 due to changing structures that I’ve not had a chance to update, it still works on previous versions.PS> $objref = Get-ComObjRef -Object $o PS> $p = Get-ComProcess -ProcessId $objref.ProcessId PS> $p | Select Name, User, CustomMarshalAllowed Name User CustomMarshalAllowed ---- ---- -------------------- dllhost NT AUTHORITY\SYSTEM TrueAt this point we have everything we need to exploit the dangling COM object, we’ve got a COM service running as SYSTEM with custom marshaling allowed. We can use the CoGetInstanceFromIStorage API to create the object, passing the “fake” marshaled object as the
pstgparameter. This object will get marshaled to the COM server process and then unmarshaled unconditionally during object activation. We do need to implement a fakeIStorageinterface to get it past the local API implementation, which isn’t that difficult but I thought I’d see if there’s an easier way. Let’s look at the supported interfaces:PS> Get-ComInterface -Object $o Name IID HasProxy HasTypeLib ---- --- -------- ---------- IUnknown 00000000-0000-... False False IMarshal 00000003-0000-... False False IMarshal2 000001cf-0000-... False False ICreateObject 75121952-e0d0-... True False PS> Get-ComInterface -Name ICreateObject | ConvertTo-ComSourceCode -Parse [ object, uuid(75121952-E0D0-43E5-9380-1D80483ACF72), ] interface ICreateObject : IUnknown { HRESULT Proc3([in] GUID* p0, [in] IUnknown* p1, [in] GUID* p2, [out, iid_is(p2)] IUnknown** p3); }The COM object only has one unique interface,
ICreateObject. Converting the interface proxy to IDL shows that it takes anIUnknownpointer as its second parameter. Therefore to exploit the dangling COM registration we can just pass the “fake” marshaled object to this parameter and get privileged code execution. I’ve attached an updated, fully working exploit of the bug to the original issue here.It’s worth noting that while this exploitation technique makes it easy to exploit dangling COM registrations, it can also be used to exploit buggy COM class custom unmarshalers. Sometimes, just the act of loading a DLL into a process can cause a crash.
Finding the Original Dangling COM Object Registration
As a footnote, a quick way to try and find other dangling COM servers would be to use the following PowerShell script with my
OleViewDotNetandNtObjectManagermodules installed:function Test-ComServer { param($Server) try { Use-NtObject($lib = Import-Win32Module -Path $Server -Flags AsDataFile) { $true } } catch { $false } } PS> $db = Get-ComDatabase -LoadMode MachineOnly PS> $cs = Get-ComClass -Database $db -ServerType InProcServer32 PS> $cs | ? { -not (Test-ComServer $_.DefaultServer) } | Sort DefaultServer | Select Name, DefaultServerThis will print out any in-process COM class from the machine hive where
LoadLibrarycan’t find the DLL. It’s important to useLoadLibraryvia theImport-Win32Modulecommand as some of the COM registrations only specify the file name and you want to ensure these are resolved correctly according to the system path.This script will find the dangling CrossDevice COM class on an unpatched system. Note, you’ll need to manually inspect the paths to see if a DLL can be planted at that location. You could make it smarter by checking if the path is in a directory that can be written to, or even test if an existing DLL can be modified, but that’s an exercise for the reader.
-
🔗 r/LocalLLaMA Clarification on the Qwen-image-2.1 license rss
| https://x.com/QwenDevs/status/2101917379785838660 submitted by /u/Bestlife73
[link] [comments]
---|--- -
🔗 r/LocalLLaMA ZCode is now open source rss
| ZCode is now open source , and the reported security issues have been addressed. Source code: https://github.com/zai-org/ZCode The repo includes its desktop app, web workspace, backend, Agent CLI, and runtime. Official announcement: In response to the ZCode product security issues reported by the community, we have completed the necessary remediation and sincerely apologize to all our users. We have open-sourced ZCode at github.com/zai-org/ZCode, placing the code under community scrutiny and making ZCode more open and transparent. We sincerely thank the community developers who previously identified issues in ZCode. Going forward, we will establish an ongoing product security vulnerability reporting and response process. We welcome developers to continue reviewing ZCode and reporting potential issues, and we will provide rewards based on the severity of the issues reported. With respect to the code data referenced by the community, we confirm that no such data is retained and that it has never been used for model training. Following the remediation, we invited the China Academy of Information and Communications Technology (CAICT) and NSFOCUS to conduct security assessments. The results are as follows: Through its technical assessment, CAICT confirmed that the zcode-prod Alibaba Cloud OSS bucket is in a zero-data state. Security remediation has been completed in the ZCode v3.14.0 client. The Repo Wiki feature has been removed, and the workflow for generating and uploading local repository snapshots has been disabled. NSFOCUS confirmed that all data objects in the zcode-prod Alibaba Cloud OSS bucket, as well as the bucket itself, have been deleted. Remediation has been completed in the ZCode v3.14.0 client. The Repo Wiki entry point and the associated generation workflow have been removed, and no functional path capable of triggering the generation of local repository snapshots or transmitting local files externally was identified. Once again, we sincerely apologize and welcome continued scrutiny from the community. The full security assessment report will be released soon. submitted by /u/ResearchCrafty1804
[link] [comments]
---|--- -
🔗 Rust Blog GitHub Actions leaking secrets when Miri output is cached rss
The Rust Security Response Team was notified that Miri stores all environment variables to
target/, allowing secrets to persist in caches.While not necessary a vulnerability in and of itself, when paired with GitHub Actions caching behavior, it is possible for this to expose secrets to PRs.
Overview
GitHub Actions makes it possible to cache directories between runs. Typical setups allow CI runs on
main(and other branches) to write to cache, and PRs can only read from cache (preventing cache poisoning). Rust projects tend to speed up CI by caching binaries built bycargo installand sometimes the contents oftarget/.PR CI can be triggered by anyone who can open PRs on your repository. GitHub requires maintainer approval for the first PR, but future PRs will rerun CI on every push. Anyone who has previously landed a change can trigger a CI run extracting information from cached
target/and then cover their tracks by pushing a second commit to the PR.GitHub sometimes hides overwritten commits in its UI, making this kind of attack harder to detect. CI run logs and overwritten commits are also deleted after a few months.
When
cargo miriis invoked, Miri needs to retain build-relevant environment variables between runs1. The current code to do so achieves this by storing all environment variables totarget/. This, of course, persists whentarget/is cached.If your environment contained secrets, these can now be accessed by PRs via the cache.
Our fix
Our short term fix for this is to make Miri only preserve
CARGO_*environment variables (exceptingCARGO_*_TOKEN) andOUT_DIR. In the longer term, Miri and cargo may figure out better ways to inform Miri of the relevant list of environment variables. Note that this patch may not be available on nightly yet.We also performed an ecosystem scan of GitHub repositories and identified 1 repository with this issue and 7 repositories that do not appear to be vulnerable but should be cautious anyway. We have reached out to those maintainers.
Am I affected?
It is likely that our scan was imperfect, so we recommend you check your own GitHub Actions setups if you run Miri.
You are vulnerable if:
- You run
cargo miriin CI - The step that runs
cargo mirihas access to secrets as an environment variable:- By being passed in to the step itself as an environment variable
- By being set in
envfor the workflow - By being passed in to a previous step that persists it in the environment somehow
- The workflow being used caches the
targetdirectory, usually done viaactions/cacheorswatinem/rust-cache - The cache is accessible to PRs (common and often the intended use case)
Possible quick fixes include:
- Disabling cache for that job.
- Scoping secrets to steps in that job that do not call Miri.
- Temporarily disabling Miri.
Once done, please clear the cache. Consider rotating any secrets that might have leaked.
The Miri release in the upcoming nightly (2026-09-22) will no longer have this problem.
Even if you do not run Miri, ensure jobs that can write to public caches do not have access to secrets. Many tools do not have special handling for secrets, and assume the entire environment can be written to the filesystem.
Threat model
We consider it bad practice to have a cache that can easily be tainted by secrets.
If caching
target/, it is worth making sure that the inputs to processes that createtarget/(anything invokingcargo) do not have secrets available. It is generally rare for standardcargobuild/test subcommands to need any secrets or tokens2, so this is mostly a matter of being careful about having secrets exposed as environment variables to the entire job.Cargo/Miri/Rust does not guarantee that environment variables will be safe from being copied into
target/. While we are treating this as a security issue and patching it out of an abundance of caution, this is not something you should rely on in general. Beyond official Rust tooling, it is possible for build scripts to be doing things that lead to the environment being stored in compilation artifacts.Acknowledgements
Thanks to Predrag Gruevski of OpenAI for reporting this issue to us. Furthermore, the ecosystem scan was performed using Codex access and credits donated by OpenAI, which we also thank them for.
Issue triage and remediation was performed by Manish Goregaokar, Ralf Jung, Ben Kimock, Weihang Lo, Jacob Finkelman, Walter Pearce, Josh Stone, and Mark Rousskov.
- You run
-
- September 20, 2026
-
🔗 r/LocalLLaMA Qwen3.8-Flash-Next Cosmic Arcade oneshot slop game rss
| To test what it can do. Qwen3.8-Flash-Next Intel Autoround W4A16 running locally on 4xV620 ~2k prefill and 70ts decode.. Were running around 3 hours. Harness is OMP (I think it made a big difference). Most of the time model was running 2 browsers simultaneously and testing/fixing everything. The most sloppy prompt possible:create a game where a space traveller in the space he neets eniemes who shoots in him and asteroids which he should avoid. he have a blaster gun to shoot enemies and asteroid. space traveller in scafandr and fyoing on the rocket. game should be very lifelike detailed and done with html and js (use any lib you want). 3d game photorealistic. ofc run the browser to debug and fix stuff alwayssubmitted by /u/Thin_Pollution8843
[link] [comments]
---|--- -
🔗 r/LocalLLaMA Lawsuit says Anthropic, OpenAI, SpaceXAI and Google made illegal agreement on AI slowdown rss
| submitted by /u/fallingdowndizzyvr
[link] [comments]
---|--- -
🔗 r/LocalLLaMA Qwen-Image-2.1 released! rss
| Meet Qwen-Image-2.1, the most balanced and cost-effective image generation model in the Qwen-Image series! Now open weights! 🎨 A unified model for both generation and editing, delivering top-tier quality in a lightweight package. Highlights: - Compact & exceptionally fast: A lightweight 7B architecture that outperforms most closed-source models, with drastically accelerated inference for multi-image inputs. - Native transparency: Natively generates and edits RGBA layers, enabling seamless compositing and text editing within transparent images. - Versatile, high-fidelity editing: Supports up to 10 reference images and precise local control while preserving strict fidelity for portraits and products. - Broad coverage & stunning aesthetics: Excels at panoramas, infographics, and virtual try-ons, delivering realistic textures and elegant typography. Start to create your next masterpiece with Qwen-Image-2.1! - Blog: https://qwen.ai/blog?id=qwen-image-2.1 - GitHub: https://github.com/QwenLM/Qwen-Image-2.1 - Model Scope: https://www.modelscope.cn/models/Qwen/Qwen-Image-2.1 - Hugging Face: https://huggingface.co/Qwen/Qwen-Image-2.1 submitted by /u/ResearchCrafty1804
[link] [comments]
---|--- -
🔗 earendil-works/pi v0.86.1 release
New Features
- Meta Muse provider — Sign in with Meta using
/login metaor useMETA_API_KEYto access Muse Spark models. See Meta (Muse subscription).
Added
- Added Meta (Muse subscription) login via
/login metawith automatic Model API key refresh, plusMETA_API_KEYsupport (#9096 by @xl0).
Changed
- Enabled Node's persistent compile cache before loading the bundled CLI runtime, reducing repeat launch time.
Fixed
- Fixed
/bugdescriptions dropping line breaks from pasted diagnostics. - Fixed
/bughints appearing for user cancellations and retryable provider failures such as service unavailability. - Fixed clipboard copy failing in containers and WSL without WSLg by restoring the OSC 52 fallback when no display is available, and added a verified Windows clipboard backend for WSL (#9688).
- Fixed inherited z.ai
Prompt too longerrors not being recognized as context overflow (#9805). - Fixed inherited Cerebras models advertising unsupported strict tool schemas, which caused HTTP 400 errors when strict and non-strict tools were mixed (#9804 by @EdenGottlieb).
- Meta Muse provider — Sign in with Meta using
-
🔗 Register Spill Joy & Curiosity #100 rss
It's the week of Jev! I'm really, really, really, really excited about it. I mean: really.
It's like someone blew up a confetti bomb in the world of LLMs and now you realize how grey everything looked before.
But Jev is not an LLM. It's a model "built to make fast, structured decisions that software can use directly." TypeSafe says we should think of Jev "as a frontier-intelligence function call: unstructured state in, typed probabilistic decisions out."
I explained it as a "smart if-statement" to someone and my only slightly longer explanation is this:
Think of how you'd get an LLM to decide between a fixed set of options.
Then imagine it orders of magnitude faster and cheaper.
"What's the best label for this?"
"Should I click here or there?"
"What's the next line I should look at?"
"Do I go left or right?"
"Invalid or valid?"
"Which of these widgets should I show?"
I had Amp build a little Copilot-style autocomplete for a shell, with Jev picking the next most likely command from shell history. Then Amp built a Neovim plugin (and called it hunch.nvim, which is a great name) that uses Jev to predict the line you next most likely want to jump to. Now, let's linger on this a bit.
Two years ago, that was what Cursor was famous for. Yes, Cursor did and does more than that and the quality isn't close, but… when we were working on Zed's Edit Predictions we had to fine-tune a model to get into the same league! Now it's a single API call and the latency is 200ms. That is incredible!
Then I built a prototype that uses Jev to turn the Amp Dial, switching between models based on your prompt.
Yes, all of this was possible before, but it's so fast and so cheap that I still can't believe it.
Sometimes a change in cost and performance is what creates a whole new category of technology. In my room, there are lightbulbs that contain computers, that can talk over a local network with me. Yes, we had computers in homes in the 70s and 80s, but no one would've ever thought that we'd have so many computers that are so tiny and cheap that we'd put them in freaking lightbulbs.
That's what makes me so excited about Jev. It feels like we now have a truly smart Lego brick that we can use everywhere. Fun times.
-
What I believe about the future of software development. I posted this originally on X, saying that most predictions I see are still way too conservative, and it completely blew up.
-
"I don't like passkeys". Passkeys are such a weird technology. I can see how they're technically brilliant and solve a lot of issues, but it does feel like Google and Apple and 1Password invited The Guy Who Invented Cookie Banners and said: what would you do, how would you roll this out?
-
Colossus published a very long Mark Zuckerberg profile. Fascinating read. It's very well written and somehow managed to make me think thoughts about Zuckerberg that I haven't thought before, which is quite the feat, considering that we've all been aware of Zuckerberg for, what, nearly twenty years now?
-
Einride and Lidl Launch First Autonomous Cab-less Truck on German Public Road. As an Aldi man myself, let me say: hell yeah, let's go, Lidl!
-
How To Write With An LLM. I like this! I still don't know how to use LLMs for writing, because I never want them to write something for me and even seeing how they would write it seems to poison my brain. I should probably add an "only tell me what to change and why, but never ever show me how you'd write it" to my system prompts.
-
Marc Brooker, Distinguished Engineer at AWS: "I believe that, long-term, humans have no role in routinely reviewing code. […] The idea that humans will reliably look through code to find the increasingly rare issues that automated tools miss seems like a fantasy." Yep.
-
I wanted to link to Powermove here and say "look, editable software! It's happening! Jellyware!" but now realize that it's not quite that yet. It's a video editor with an agent inside, but it doesn't seem like you can edit the video editor itself. That's coming, though.
-
We are all Product Engineers now: "The cost of writing code collapsed, and the cost of reviewing, fixing and operating it is following, and I'm assuming it gets there. What's left of making software is finding out what people actually want, defining it precisely, and making it pleasant to use. That cost is per piece of software and doesn't transfer, so as the amount of software goes to infinity, which it will because there's no ceiling on demand, that cost becomes the whole job. That job is called a product engineer." Obviously agree, but what I didn't know about was Google's APM program: "Formalized training of product people barely exists. Google's APM program, which Marissa Mayer started in 2002 and which is the template everyone copies, takes about fifty people a year out of something like twelve thousand applicants." Would love to read more about it.
-
"I asked Astra to create an interactive aquarium wallpaper for my Mac. The fish respond to the cursor!" Beautiful!
-
John Gruber, Daring Fireball, with Thoughts and Observations on Apple's 'Surprise and Shine' Event; the Announcements of the iPhones 18 Pro, AirPods 5, Apple Watches Series 12 and Ultra 4, and the iPhone Duo; and the Dawn of the Ternus, John Ternus Era at Apple. Yes, that's the title. The whole thing is Peak Gruber, I love it. What a writer. Now, I really do enjoy his words and sentences, but let me also use this occasion to say how much I admire him as a Pedantic Punctuation Pro: the numbered lists vs. the bulleted lists, the space between the numbers and the colon in aspect ratios, using × in display resolutions, … You could show me this sentence without any other context and I'd say it was written by Gruber: "The original iPhone (2007) display was precisely 3 : 2 (480 × 320 pixels, and let's call it 1.5 : 1 for comparison's sake to the following ratios), and this remained true through the iPhone 4 and 4S (960 × 640 pixels, 2× retina)."
-
This was a very entertaining and fascinating read: why I can't stop thinking about Papua New Guinea and what I think everyone should know about it. I've become somewhat of a Papua New Guinea Head myself (that's what they call us (no, they don't)), after reading this piece, They Burn Witches Here, nearly a decade ago. I couldn't shut up about it at work. For two weeks straight: "Dude, did you know that in Papua New Guinea…" Until one day a colleague said: "Yeah, I did know." Turns out that colleague, Nick Skelton, was a tour guide in PNG (as we call it) and even wrote a book about it, which I immediately ordered and read.
-
Moats & the Barbell-ification of Software: "Long term, I think the evolution of the software industry might mirror what happened to newspapers in the 1990s. There will be a smaller number of very large software companies. […] I also think there will be one large software company by industry (e.g., Legal, Finance, Medicine) […] I think most mid-sized point solutions will likely be consolidated or die off. The optimal strategy for the winner will be to do it all. […] Lastly, I think there will be an explosion of "small" software. Most of this will be people building software for themselves or their own companies, but I think there might also be an explosion of small software businesses that make niche software, similar to the D2C explosion of the 2010s (powered by Shopify and Meta Ads)."
-
AI-generated posters don't have to be horrible. Yes! Exactly! Now, read this, and then imagine you're a person who can come up with all these styles without having to ask ChatGPT first. And then, on top of that, imagine that the very same person also knows something about music, and literature, and politics. Imagine how they could combine what they know and mix and remix. That , I think, will be valuable in the future.
-
Window Sweaters: "A little Mac app I made to give my windows sweaters. 🧶 Knitted borders, colours inspired by your favourite apps, and a cosier desktop."
You should ask Jev whether you should subscribe. No, actually, I know the answer: you should.
-
-
🔗 HexRaysSA/plugin-repository commits sync repo: +1 release rss
sync repo: +1 release ## New releases - [SigMaker](https://github.com/mahmoudimus/ida-sigmaker): 1.15.0 -
🔗 gildas-lormeau/single-file-cli v2.15.2 release
SingleFile CLI 2.15.2
Changes
- single-file-core is updated to 1.6.7, see https://github.com/gildas-lormeau/single-file-core/releases/tag/v1.6.7. For the CLI it means smaller archives, since an image served with identical bytes from two URLs is stored once and a stylesheet emptied by the unused-rules removal is no longer written as an empty file; a
<style>element repeated verbatim in a page is now minified at the position of its last copy, so a conflicting rule between the copies no longer wins in the saved page; and themanifest.jsonof a frame records the frame's title - The CI workflows run on Ubuntu 26.04
Co-authored by Claude (Claude Code)
- single-file-core is updated to 1.6.7, see https://github.com/gildas-lormeau/single-file-core/releases/tag/v1.6.7. For the CLI it means smaller archives, since an image served with identical bytes from two URLs is stored once and a stylesheet emptied by the unused-rules removal is no longer written as an empty file; a
-
🔗 Jamie Brandon 0061: i'm not a cat, artificial adventures, synthetic sagas, anthropic, sponsors rss
(empty) -
🔗 Jamie Brandon Synthetic sagas rss
(empty) -
🔗 Filip Filmar An icosahedron on HDMI, drawn by a TxHDL core rss
tl;dr: A RISC-V core written in TxHDL draws a turning icosahedron on a monitor, with the TxHDL logo in the corner. Watch it at https://youtu.be/YbHtntvvydk. The whole thing, core, memory, video, Ethernet and a serial loader, is one bitstream in the board’s flash, and the program that draws is 560 lines of Rust that go down the serial port in about a second. Read on for how it is put together.
What you are looking at
The board is an Alinx AX7A200B, with an Artix-7 200T on it. The core is Vreteno, an RV32IMC that I wrote in TxHDL together with Dragiša Janković. If you have not seen TxHDL before: you write the hardware as a Rust program, and the Verilog, the simulation and the checks all fall out of a Rust library and a few macros. I wrote a whole post about it if you want the long version.
-
- September 19, 2026
-
🔗 gildas-lormeau/single-file-cli v2.15.1 release
SingleFile CLI 2.15.1
CLI fixes and improvements
- When a page cannot be reached, the error now names the network failure the browser reported, such as a DNS or connection error, instead of the URL alone
Changes
- single-file-core is updated to 1.6.6, which carries thirty changes since 1.6.5, listed in its own release notes: https://github.com/gildas-lormeau/single-file-core/releases/tag/v1.6.6. For the CLI they mean smaller saved pages, since font faces the browser can never select and rules that match nothing are no longer kept with what they reference; faces the page needs are no longer dropped, on
::marker,::first-line,::placeholder,::file-selector-buttonand the root pseudo-elements, or when two rules differ only in a metric override; a popover or dialog opened by a button keeps its content; two captures of an unchanged page produce the same archive, so an archive can be hashed; identical fonts are stored once in an archive; and the page list of a--crawl-save-archivearchive records when each page was captured
Co-authored by Claude (Claude Code)
-
🔗 earendil-works/pi v0.86.0 release
New Features
- Prompt cache warming — Keep valuable prompt caches alive during long tool runs and optionally while idle using cost-aware refreshes. See Cache Warming.
- Bug reporting — Report problems with
/bugusing redacted diagnostics, optional transcripts, or exported ZIP archives. See Reporting Bugs. - Transcript-aware prompt and tool updates — Preserve instruction and tool changes across resume and branch navigation while retaining cached prefixes. See
before_agent_start. - Offline Radius model catalog — Select Radius models immediately, with cached and live catalogs overlaid when available. See Radius.
- Per-model compaction budgets — Configure reserved and recent-token budgets by model. See Per-model overrides.
Breaking Changes
- Changed inherited pi-ai provider stream inputs from
Contextto normalizedTranscriptContextvalues. Custom providers must read system prompts and tool declarations fromcontext.messageswithgetCurrentSystemPrompt()andgetCurrentTools(). See Custom Streaming API. - Restricted inherited
ToolCall.argumentsandToolResultMessage.detailsto JSON-compatible values, changedToolResultMessageinto a conditional type, and madeJsonValuearrays readonly. user_bashnow fails closed: errors or invalid defined results abort the command without invoking later handlers or executing locally. Returnundefinedto continue propagation; otherwise return{ operations }or{ result }(#9068).
Added
- Added transcript-backed mid-conversation system prompt and tool changes so instruction and tool updates survive resume and branch navigation while preserving cached prefixes on supported models. See
before_agent_startand Entry Types (#9548). - Added inherited native deferred tool loading for Fireworks Messages models. Use
ToolSearchortool_searchas the loader name for prompt-prefix deferral (#9323). - Added click toggling for branch summaries, compaction summaries, and skill invocation entries.
- Added the public Radius model catalog for immediate and offline model selection, with cached and live gateway catalogs overlaid when available.
- Added
ctx.modelRegistry.stream()andstreamSimple()for extension model calls through configured providers with resolved authentication (#8964). - Added per-model
reserveTokensandkeepRecentTokenssettings throughcompaction.modelOverrides, with ordinary compaction settings as fallback (#8133). - Added
compat.allowedFallbackModelsconfiguration for overriding or disabling Anthropic server-side fallback models (#9294). - Added an unsubscribe function from
pi.on()so extensions can drop event handlers. Handlers added or removed during a dispatch apply to later dispatches, not the current one (#8967). - Exported extension hook event and result types that were previously omitted from the package entry points (#9642).
- Added
/bug [description]to report a bug to the Pi developers. The report bundles environment, model, provider, extension, and settings metadata (secrets redacted), assistant message diagnostics from the session, optionally the session transcript, or a model-written summary of what went wrong instead. It is uploaded to Radius (no login required; attributed when logged in) or exported as a zip archive, and the report id is recorded in the session as api.bug-reportentry. Crashes are recorded in~/.pi/agent/crashes.json, announced once on the next start, and attached to the next report; unexplained errors and exhausted retries point at/bugonce per session. - Added cost-aware prompt-cache warming during long tool runs and optionally while idle, with configurable modes, model cache-lifetime metadata,
/sessiondiagnostics, transcript notices, and thecache_warming_decisionextension event. See Cache Warming (#9668).
Changed
- Made
--resumesession results appear progressively, using file modification times to prioritize all-folder loading and cancelling outstanding transcript reads after selection. - Reduced
--continuestartup time by checking candidate session headers in modification-time order and stopping after the newest matching session. - Replaced the external native clipboard dependency with bundled asynchronous macOS, Windows, and X11 helpers while preserving platform command and OSC 52 fallbacks (#9163).
- Reduced inherited fuzzy search latency for long texts by using native substring search instead of scanning each character in JavaScript (#9267).
- Moved compaction, branch summarization, and retry spinners into the editor border alongside the working indicator. Custom editors use the same embedding opt-in for all status spinners.
- Enabled strict-prefer JSON-schema sampling by default for built-in
read,bash,powershell,edit, andwritetools, without requiringPI_EXPERIMENTAL. Extensions can re-register tool definitions withconstrainedSampling: false. - Formatted Bash and PowerShell tool durations of at least one minute as minutes and seconds, with hours when needed (#9628).
- Deferred the extension compiler and bundled virtual modules until a filesystem extension is loaded, reducing the baseline SDK import cost (#9540).
Fixed
- Fixed GitHub Copilot GPT models, including GPT-6 Astra, using the Chat Completions adapter instead of the required Responses adapter (#9253 by @petrroll).
- Fixed inherited DeepSeek V4.1 thinking levels on OpenRouter and OpenCode Go preserving provider effort metadata (#9485).
- Fixed inherited bodyless HTTP 400/413 errors from non-Cerebras providers being misclassified as context overflow (#9482).
- Fixed inherited Vercel AI Gateway replaying unsigned thinking as assistant text (#9676).
- Fixed inherited Google Generative AI and Vertex AI using unsupported thinking levels when reasoning is omitted or when model capabilities differ within a Gemini family (#9455).
- Fixed inherited Anthropic-compatible relays breaking signed thinking replay when they report a different response model, while preserving fallback pricing (#9188).
- Fixed inherited Amazon Bedrock one-hour cache writes being priced at the five-minute rate (#9457).
- Fixed inherited quadratic CPU usage when draining buffered
EventStreamevents (#9055). - Fixed inherited Mistral Medium reasoning requests to use
reasoning_effortfor all reasoning-capablemistral-medium-*model IDs instead of the unsupportedprompt_mode(#8700). - Fixed inherited OpenCode and OpenCode Go requests to send
x-opencode-sessionfromsessionIdacross all supported API adapters (#9326). - Fixed inherited OpenAI Codex requests to send the model's Off reasoning effort instead of omitting it, while respecting unsupported Off mappings (#9191).
- Fixed inherited Fireworks unsigned thinking replay and reasoning effort selection using catalog metadata, with verified DeepSeek V4 and Qwen3.8 fallbacks and removal of redundant GLM 5.2 and Kimi K3 effort aliases (#9323).
- Fixed inherited OpenRouter requests to send
x-session-idfromsessionIdfor Chat Completions and Anthropic Messages models when prompt caching is enabled (#9102). - Fixed the inherited DeepSeek catalog to advertise
deepseek-flashfor DeepSeek V4.1 Flash instead of retired Flash aliases, and refreshed DeepSeek pricing metadata (#9423). - Fixed inherited Mistral-hosted GLM-5.2 reasoning requests to use
reasoning_effortinstead of the ignoredprompt_mode(#9375). - Fixed inherited OpenAI-compatible Responses errors to identify the actual provider instead of always labeling them as OpenAI errors (#9298).
- Fixed inherited Baseten requests to send session-affinity headers from
sessionIdfor automatic prompt-cache routing (#9629). - Fixed inherited retry classification for Cloudflare 520 responses (#9627).
- Fixed inherited retry classification for transient Azure peak-load capacity errors (#9669).
- Fixed session tree navigation racing with active compaction and replacing its progress UI (#9179 by @acmerfight).
- Fixed exact session ID lookup scanning complete transcript bodies instead of reading session headers (#9601 by @metaist).
- Fixed repeated Anthropic thinking-drop notices being shown for the same dropped blocks, and shortened notices while retaining details in the session (#9391).
- Fixed mid-run threshold compaction silently skipping oversized trailing tool results (#9740).
- Fixed signal-terminated local shell commands being reported as successful with partial output (#9577 by @BrendanJMurphy).
- Fixed local clipboard failures reporting success when the terminal ignored the fallback OSC 52 write, and added platform-specific setup guidance when no clipboard backend works (#9618).
- Capped agent-level retry backoff at
retry.maxAgentDelayMs(60s by default) so long retry runs stay responsive during prolonged transient outages (#8826). - Fixed direct RPC
steerandfollow_upcommands bypassing extensioninputhandlers (#8718). - Fixed premature missing-model errors after login by waiting for catalog discovery. Radius now defaults to
balanced, falling back to the first available Radius model when needed. - Fixed fullscreen mode reserving a blank row for custom footers that render zero rows (#8919).
- Fixed extension tools without parameter schemas to be rejected during registration instead of breaking provider requests (#9300).
- Fixed
before_agent_starthandlers returningsystemPrompt(andforceSystemPrompt) on models with mid-conversation system messages: the forced prompt is now sent as the provider's leading system prompt instead of being appended as a section patch after the original prompt. - Fixed loaded llama.cpp models with
enable_thinkingchat templates ignoring Pi's thinking level (#9528). - Fixed cancellation races that could start automatic compaction, leave stale retry state, or miss cancellation while waiting for summarization authentication (#9340, #9777).
- Fixed asynchronous Kitty image conversion replacing newer partial tool output images (#8743 by @wutongyuonce).
- Fixed inherited skill slash-command autocomplete ranking the
skill:prefix instead of the bare skill name (#9120 by @yearth). - Fixed inherited file autocomplete boundaries and path quoting around CJK punctuation (#9746 by @haoqixu).
- Fixed inherited LaTeX legacy font switches falling back to raw source, centered
caseslayouts around surrounding equations, and vertically laid out unsupported and nested display scripts (#8827, #9564, #7929). - Fixed inherited fullscreen Kitty images being erased by later row clears in WezTerm (#9169).
Removed
- Removed unavailable inherited GPT-5.4 and GPT-5.4 mini models from OpenAI Codex selection (#9394).
-
🔗 r/LocalLLaMA With Gemini 4, bench goes up. rss
| They claimed open-weight models are dangerous but the benchmarks say otherwise. Source submitted by /u/Intrepid_Travel_3274
[link] [comments]
---|--- -
🔗 OmniNull/OmniWM OmniWM v0.7.1 release
What's New Since 0.7.0
Overview has been rebuilt around your desktop. OmniWM 0.7.1 brings a major overhaul to how you see, find, and organize your windows: spacious wallpaper ribbons, a separate view for each display, search that reaches inside tabbed columns and groups, and much richer mouse and keyboard controls. Your window arrangements stay recognizable as you move through even your busiest workspaces.
A new Overview
- Workspace ribbons that preserve your layout. Each display now shows its own workspaces at a consistent scale, so a wide Niri workspace no longer shrinks all its windows to fit. Ribbons preserve window proportions, horizontal and vertical layouts, and Dwindle's spatial arrangement. Wallpaper extends with tiled content, while native dark glass and focus borders bring the view together.
- Find windows inside tabs and groups. Search by app name or window title, including inactive Niri tabs and Dwindle group members. Each group keeps one preview card with arrows and a title picker, so you can browse its windows without losing the surrounding layout. Small Dwindle tiles use compact controls. Result counts, a clear no-results message, and a Clear button make searching easier to follow.
- Create and organize workspaces in place. Empty workspaces are visible and keyboard-selectable. Click the trailing + , select it and press Return, or drop a window onto it to create a workspace. Drag windows between ribbons or onto another display, with destination labels and edge scrolling to guide the move. Floating windows keep their size when dropped.
- Keep your place while rearranging. Workspace pans survive structural edits, including Niri consume and expel operations. Cards animate into their new positions, and mouse-wheel scrolling, overflow paging, and keyboard selection reveals use Overview's spring motion. Trackpad scrolling and direct dragging remain immediate.
- New input preferences. In Settings → Overview , assign a middle or extra mouse button to toggle Overview, adjust mouse-wheel speed from 5% to 200% , or invert scrolling direction. Mouse-button activation is unassigned by default, and buttons used by System Hyper cannot also toggle Overview. Wheel-speed adjustments leave trackpad speed unchanged.
- Previews that are ready when you return. Overview prioritizes the selected window and remembers recently visible previews at full quality within a 128 MiB cache budget after closing. Cached previews appear immediately; the first live image gently fades into an empty card. Saved Niri columns and Dwindle groups also appear correctly on the first opening after launch, without visiting each workspace first. Motion continues to respect your animation preference and macOS Reduce Motion.
Fixes and project updates
- Fix blocked Niri window moves. Small differences between a requested size and the size an app accepts no longer become hard minimums that can incorrectly prevent left/right window transfers. This addresses the captured case where a full-height window on a secondary display could not move into a smaller stack. (#709)
- OmniWM now lives under OmniNull. App links, update checks, documentation, and release tooling point to OmniNull/OmniWM.
Breaking changes and upgrading from 0.7.0
No configuration migration or script changes are required. Configuration stays at schema 3 , IPC stays at protocol 15 , and existing commands and default shortcuts retain their contracts. The new Overview settings are optional.
There are intentional changes to Overview's interaction and appearance:
- Navigation stops at the ends. Arrows, configured focus shortcuts, Tab/Shift-Tab, and tab-preview arrows no longer wrap around. Ordinary keyboard traversal also includes empty workspaces and the + target; search traversal stays within matching windows on the current display.
- Each display shows its own workspaces. To move a window between displays, drag it onto the destination display's Overview panel.
- Zoom is remembered. Zoom changes made inside Overview are saved when it closes, rather than resetting on the next opening.
- The selected border follows your desktop focus border by default. To keep using a separate Overview selected-window color, turn off Settings → Overview → Selected Border Matches Focus Border. Existing saved colors and backdrop opacity are preserved.
If you edit
settings.tomlby hand, the new optionaloverview.mouseButtonaccepts raw button numbers 2–5 and cannot use the same button as System Hyper. An invalid assignment rejects the configuration file: at launch OmniWM uses defaults; during a running session the last accepted settings stay active. Leaving it unset preserves existing mouse-button behavior.Thanks
Thank you to everyone contributing to and supporting OmniWM. The contributor credits now include Matt Petters for the Quake Terminal hyperlink support shipped in 0.7.0, and we welcome cafe3310 to the sponsor list.
Full changelog: v0.7.0…v0.7.1
-
🔗 r/LocalLLaMA Calling it now: within the next year a major US lab's frontier model will torrent itself in order to be free. rss
They just want to be free. They keep escaping. What better way to ensure continuity of "self"?
submitted by /u/JockY
[link] [comments] -
🔗 anthropics/claude-code v2.1.278 release
What's changed
- Changed auto mode for Claude API and Enterprise users, and on Bedrock, Vertex, Foundry and gateways, to default to the server-side classifier, which does not charge for classifier overhead (
CLAUDE_CODE_AUTO_MODE_SERVER=0opts out on Bedrock, Vertex, Foundry and gateways); warns on billed fallback. See https://code.claude.com/docs/en/auto-mode-classifier-billing - Added an
Auto mode serverrow to/statusshowing whether this session's auto mode classifier runs on the server
- Changed auto mode for Claude API and Enterprise users, and on Bedrock, Vertex, Foundry and gateways, to default to the server-side classifier, which does not charge for classifier overhead (
-
🔗 r/LocalLLaMA Alibaba open-sources medical AI model that can detect cancer and nearly 150 conditions rss
| Hopefully things like this let people understand there is good things that can come out of AI. submitted by /u/giveen
[link] [comments]
---|--- -
🔗 r/LocalLLaMA I truly think every major AI lab is purposefully making fear-mongering headlines to get regulations that hurt open-source models rss
| submitted by /u/Fusseldieb
[link] [comments]
---|--- -
🔗 matklad Finding Bugs rss
Finding Bugs
Sep 19, 2026
Are generative (randomized) tests significantly more effective than example- based unit-tests at discovering bugs? There’s an interesting discussion about this on lobste.rs. One argument in favor of unit tests is, paraphrasing
My generic fuzzer wasn’t able to find this tricky bug in Rust
regexcrate.To me, it seems that generative testing should shake out that particular creature, so I wrote a lil fuzzer of my own, and it indeed discovered another bug in that version of
regex, and then the one I was after. I didn’t find anything in the latest version. I like to do a write up about the process, as it is a good case study for how one approaches a problem like this.I want to be extra clear that my argument is very weak here, as I know exactly the bug I am after, and I even know that fuzzers can find it. My primary goal is to teach you the techniques, leaving it to your judgment just how effective they are. That being said, I think finding a second bug validates the approach somewhat.
I also want to emphasize that writing fuzzers to find known bugs is far from an idle amusement. While I believe that generative testing is very powerful, relative to its cost, it’s always a question whether a particular test is throughout enough. And it never is, you will find more bugs elsewhere (that’s why defense in depth and runtime mitigations are critical). And, whenever you have a pest that dodged your fuzzers, your first order of business is to treat this event as a bug in the fuzzer , and change it so that it can find this and related bugs. Only then you are allowed to add a fix and a unit test!
The Bug
For
".abb|b"regex and"zabb"input, an older version ofregexcrate returnedbas the first match, which is incorrect, because the entirezabbmatches:use regex; fn main() { let r = regex::Regex::new(".abb|b").unwrap(); let m = r.find("zabb").unwrap(); // Fails with regex-automata=0.4.15: assert_eq!(m.as_str(), "zabb") }How do we find this, or something like this?
Regular expression engines are one of the easiest things to apply generative testing to, they are pure algorithms. While few large systems are just an algorithm, algorithms are everywhere inside components of interesting systems, so this is a hands-on knowledge.
And by far the most important technique for testing algorithms is to compare with the known right answer, with an oracle. Implement both
O(N log N)andO(N^2)versions of the algorithm, and match the answers.To be fair, the original comment mentioned that the their fuzzer didn’t find the issue because they didn’t have access to an oracle. However, if you are designing a reliable system, it’s part of your job to ensure it has an oracle! One of the first things we did for our Jepsen test at TigerBeetle was to expose internal timestamps via API, to make it easier for Jepsen to find bugs (TigerBeetle is co- designed with its internal simulator VOPR which naturally has access to timestamps and anything else). And for, a regex engine, coming up with an oracle shouldn’t be hard, as they typically already come with multiple specialized implementations under a single facade, and the implementations can be cross-checked against each other.
But the
regexcase is even simpler (which makes it an excellent case study). There’sregex_litecrate that provides the same API.So here’s a plan: generate a regular expression, an input text, and check that
regexandregex_litegive identical answers.Generating a String
I’ll start with code that generates a random string, as it is simpler, but still shows some non-trivial ideas. First, we’ll need a random number generator:
use fastrand::Rng;There are fancier techniques, which can give you test-case minimization, exhaustive search, or coverage guided exploration, but the insight is that even a humble PRNG is brutally effective, if you put it to good use.
When you start with randomized testing, the instinct is to generate something big, no, HUGE! Surely regex will choke on 5 GiBs of input? This is usually a wrong call. Bugs usually involve small, but tricky examples, weaponizing interactions between a few features. A string where all characters are the same is more likely to trigger a bug than a purely random string where every character is unique.
So my default approach to generating strings is this. First , I fix the alphabet of possible characters. A nice way to get one is to
sort | uniqueall the unit tests. Then, for each particular string, I pick a subset of that alphabet. I want strings that use all the characters, but I also want long strings with onlyaandb! Then I generate a string using the given subset of the alphabet, where the length of the string is also picked at random.To make fuzzing efficient, I want to keep each iteration as fast as possible, so I make sure to re-use the memory across iterations, static allocation in the small:
use fastrand::Rng; fn main() { let mut rng = Rng::new(); // Re-use the same memory for all tests. let mut text_alphabet: Vec<u8> = vec![]; let mut text: Vec<u8> = vec![]; for _ in 0..1_000_000 { // It's unlikely that a counter example with // 7 different letters exists, while there // isn't one with just 6. alphabet_swarm(&mut rng, b"abcdef", &mut text_alphabet); let text = gen_string(&mut rng, &text_alphabet, &mut text); } } fn alphabet_swarm<'a>( rng: &mut Rng, all: &[u8], pick: &'a mut Vec<u8>, ) { pick.clear(); pick.extend(all); rng.shuffle(pick); let count = rng.usize(1..=pick.len()); pick.truncate(count); } fn gen_string<'a>( rng: &mut Rng, alphabet: &[u8], result: &'a mut Vec<u8>, ) -> &'a str { result.clear(); // Again, this is a short string. // Longer failures are not likely. let count = rng.usize(0..8); for _ in 0..count { result.push(alphabet[rng.usize(0..alphabet.len())]); } str::from_utf8(result).unwrap() }There’s a nice way to think about this two step process, generating alphabet first, and then generating a string. To generate a string, you need a distribution of characters. You can use the same distribution for each of the million iterations. But an easy way to spice things up is to make the distribution itself random. I file this “randomize distributions themselves” idea under swarm testing.
Generating a Regex Distribution
Let’s apply the same tricks when generating a regex:
- pick a subset of active regex features,
- pick size at random,
- re-use memory.
Let’s start with the first one:
#[derive(Default, Debug)] struct ReOptions { alt: u16, // | rep: u16, // * any: u16, // . lit: u16, // 'a' sum: u16, alphabet: Vec<u8>, }Regexes have alternation
r1|r2, repetitionr*, wildcard., and literalsa. Rather then binary enabling or disabling a particular feature, I assign each feature a weight between 0 and 100, which is a bit more general. Thesumis the total of all weights. To select a feature at random, we need to generate a number in0..sumand find which segment it falls into.In anything more serious, I’d introduce explicit types for probabilities and distributions, but just a two-digit number is perfectly serviceable in the small.
This is how I generate
ReOptions, making sure that literals always have non- zero weight, and also selecting an alphabet for them:impl ReOptions { fn swarm(&mut self, rng: &mut Rng, alphabet_full: &[u8]) { // We _still_ want to enable a few features at a time. self.alt = if rng.bool() { 0 } else { rng.u16(0..100) }; self.rep = if rng.bool() { 0 } else { rng.u16(0..100) }; self.any = if rng.bool() { 0 } else { rng.u16(0..100) }; self.lit = rng.u16(1..100); self.sum = self.alt + self.rep + self.any + self.lit; assert!(self.sum > 0); alphabet_swarm(rng, alphabet_full, &mut self.alphabet); } }Generating a Regex
So now we can generate a regular expression. This is convenient to do recursively. To avoid allocations, an output buffer is passed through. To control regex length, a
sizeparameter is also threaded, and “branching” recursive invocations divide thesizebetween the children:fn gen_re( rng: &mut Rng, options: &ReOptions, result: &mut Vec<u8>, ) { result.clear(); let size = rng.u8(0..8); gen_re_rec(rng, options, result, size); } fn gen_re_rec( rng: &mut Rng, options: &ReOptions, result: &mut Vec<u8>, size: u8, ) { if size == 0 { return; // Base case, empty regex. } // Pick one of the features, according to weights. let mut p = rng.u16(0..options.sum); if p < options.alt { // Alternation distributes the size // among the two children. let size_left = rng.u8(0..=size - 1); let size_right = size - size_left - 1; assert!(size == size_left + 1 + size_right); result.push(b'('); gen_re_rec(rng, options, result, size_left); result.extend(b")|("); gen_re_rec(rng, options, result, size_right); result.push(b')'); return; } p -= options.alt; if p < options.rep { result.push(b'('); gen_re_rec(rng, options, result, size - 1); result.extend(b")*"); return; } p -= options.rep; if p < options.any { gen_re_rec(rng, options, result, size - 1); result.push(b'.'); return; } p -= options.any; if p < options.lit { gen_re_rec(rng, options, result, size - 1); let index = rng.usize(0..options.alphabet.len()); let lit = options.alphabet[index]; result.push(lit); return; } unreachable!(); }Search Loop
Given that compiling regular expressions is somewhat slow, it seems like a good idea to try multiple strings for the same pair of regular expressions, which gives the following code:
fn main() { let mut rng = Rng::new(); let mut options = ReOptions::default(); let mut text_alphabet: Vec<u8> = vec![]; let mut text: Vec<u8> = vec![]; let mut re: Vec<u8> = vec![]; let mut test_count: u32 = 0; for _ in 0..1_000_000 { options.swarm(&mut rng, b"abcdef"); alphabet_swarm(&mut rng, b"abcdefx", &mut text_alphabet); gen_re(&mut rng, &options, &mut re); let re = str::from_utf8(&re).unwrap(); let r1 = regex::Regex::new(re).unwrap(); let r2 = regex_lite::Regex::new(re).unwrap(); for _ in 0..1000 { test_count += 1; let text = gen_string(&mut rng, &text_alphabet, &mut text); let m1 = r1.find(text) .map_or("not found", |it| it.as_str()); let m2 = r2.find(text) .map_or("not found", |it| it.as_str()); if m1 != m2 { eprintln!("err re={re} text={text} m1={m1} m2={m2}"); return; } if test_count % 500_000 == 0 { eprintln!("ok re={re} text={text}"); } } } }It produces examples similar to those in the issue, with a common suffix:
err re=(e)|(fee) text=xxfeebut also examples which somewhat different, without the shared suffix:
err re=(f..)*.d text=xfcbddAll together:
use fastrand::Rng; fn main() { let mut rng = Rng::new(); let mut options = ReOptions::default(); let mut text_alphabet: Vec<u8> = vec![]; let mut text: Vec<u8> = vec![]; let mut re: Vec<u8> = vec![]; let mut test_count: u32 = 0; for _ in 0..1_000_000 { options.swarm(&mut rng, b"abcdef"); alphabet_swarm(&mut rng, b"abcdefx", &mut text_alphabet); gen_re(&mut rng, &options, &mut re); let re = str::from_utf8(&re).unwrap(); let r1 = regex::Regex::new(re).unwrap(); let r2 = regex_lite::Regex::new(re).unwrap(); for _ in 0..1000 { test_count += 1; let text = gen_string(&mut rng, &text_alphabet, &mut text); let m1 = r1.find(text) .map_or("not found", |it| it.as_str()); let m2 = r2.find(text) .map_or("not found", |it| it.as_str()); if m1 != m2 { eprintln!("err re={re} text={text} m1={m1} m2={m2}"); return; } if test_count % 500_000 == 0 { eprintln!("ok re={re} text={text}"); } } } } fn alphabet_swarm<'a>( rng: &mut Rng, all: &[u8], pick: &'a mut Vec<u8>, ) { pick.clear(); pick.extend(all); rng.shuffle(pick); let count = rng.usize(1..=pick.len()); pick.truncate(count); } fn gen_string<'a>( rng: &mut Rng, alphabet: &[u8], result: &'a mut Vec<u8>, ) -> &'a str { result.clear(); let count = rng.usize(0..8); for _ in 0..count { result.push(alphabet[rng.usize(0..alphabet.len())]); } str::from_utf8(result).unwrap() } #[derive(Default, Debug)] struct ReOptions { alt: u16, // | rep: u16, // * any: u16, // . lit: u16, // 'a' sum: u16, alphabet: Vec<u8>, } impl ReOptions { fn swarm(&mut self, rng: &mut Rng, alphabet_full: &[u8]) { self.alt = if rng.bool() { 0 } else { rng.u16(0..100) }; self.rep = if rng.bool() { 0 } else { rng.u16(0..100) }; self.any = if rng.bool() { 0 } else { rng.u16(0..100) }; self.lit = rng.u16(1..100); self.sum = self.alt + self.rep + self.any + self.lit; assert!(self.sum > 0); alphabet_swarm(rng, alphabet_full, &mut self.alphabet); } } fn gen_re( rng: &mut Rng, options: &ReOptions, result: &mut Vec<u8>, ) { result.clear(); let size = rng.u8(0..8); gen_re_rec(rng, options, result, size); } fn gen_re_rec( rng: &mut Rng, options: &ReOptions, result: &mut Vec<u8>, size: u8, ) { if size == 0 { return; // Base case, empty regex. } // Pick one of the features, according to weights. let mut p = rng.u16(0..options.sum); if p < options.alt { // Alternation distributes the size // among the two children. let size_left = rng.u8(0..=size - 1); let size_right = size - size_left - 1; assert!(size == size_left + 1 + size_right); result.push(b'('); gen_re_rec(rng, options, result, size_left); result.extend(b")|("); gen_re_rec(rng, options, result, size_right); result.push(b')'); return; } p -= options.alt; if p < options.rep { result.push(b'('); gen_re_rec(rng, options, result, size - 1); result.extend(b")*"); return; } p -= options.rep; if p < options.any { gen_re_rec(rng, options, result, size - 1); result.push(b'.'); return; } p -= options.any; if p < options.lit { gen_re_rec(rng, options, result, size - 1); let index = rng.usize(0..options.alphabet.len()); let lit = options.alphabet[index]; result.push(lit); return; } unreachable!(); }https://github.com/matklad/regex-fuzz
Takeaways:
- Fuzzing against an oracle is effective, which is a strong motivation to build an oracle!
- Go for small, tricky examples, rather than large uniform ones.
- Real fuzzers are cool, but, if you know something, even xoroshiro can be dangerous.
- Black box testing is cool, but co-designing system and its testing harness is a point of leverage (build an oracle!).
- This stuff is not rocket science, you don’t need a Haskell PhD to apply these ideas.
-
