Research window: 2026-10-30 08:00 ~ 2026-11-02 08:00 (Beijing time, 72 hours, covering Saturday and Sunday)

Sources: RT-Thread official news API and community article channel; GitHub (main repository commits / PR / Issue / releases / tags; all 35 repositories in the RT-Thread org checked by push time, with packages / vscode-rt-smart / sdk / pkgs-test listed separately); GitHub repository search (rt-thread keyword, filtered by creation time); Google News six queries in Chinese and English (via proxy); HN Algolia; EETimes China RT-Thread official column; club.rt-thread.org forum (this issue was limited by the site’s WAF; lists and post bodies could not be read directly)


Index for This Issue

  • I. Kernel and Release Dynamics
    • clang-format pinned to 22.1.8; 73 kernel source files under src/ reformatted in one pass (10-30)
    • dlmodule closes #5705 reported in 2022: four root causes of uninitialized global variables fixed together (10-30)
    • Release management CI and release process enter planning: monthly Z reports, Y reviews every 3 to 6 months (10-30)
  • II. Security Follow-up and Merge Queue
    • RT-Smart mailbox does not validate kernel object pointers; forged objects can read and write kernel memory (10-31)
    • pipe’s FIONREAD writes directly to a user-supplied pointer; third occurrence of the same defect type (10-30)
    • Count multiplication wraparound in poll and epoll: validation passes at 8 bytes, but iteration walks 530 million entries (10-30)
    • RISC-V AIA: APLIC level-triggered interrupt EOI unconditionally writes setipnum; delayed thread does not resume under older QEMU (11-01)
  • III. Official and Community Events
    • Wuhan stop of the roadshow training held on 10-31: Edgi-Talk dual-core four major labs, project code taken home on site (10-31)
    • Livestream on November 4: keep the large model on the PC and recreate the DeepSeek blue whale desktop pet with Ruiqing 3576 (10-30)
    • Official news API still stuck at June 17; release-side coverage shifts to media columns (11-02)
  • IV. Ecosystem and Vendor Adaptation
    • NXP RT1180 industrial Ethernet linker script enters the review queue (10-30)
    • Patches already exist for the two driver defects reported last issue: DM365 SPI divide-by-zero, Bluetrum AB32 ADC channel (10-30 ~ 10-31)
  • V. Industry Applications
    • Contest entries open-sourced in bulk after the competition: four edge AI vision projects packed onto two boards (10-30 ~ 11-01)
    • From contest board to production line: 20 kHz sensorless FOC and encoder closed-loop positioning on dual Cortex-M7 (10-31)
  • VI. Trends and Summary for This Issue
    • Trend: quiet on the merge side, dense on the patch side; RT-Smart’s boundaries are being systematically cleared
    • Limitations and deduplication notes

I. Kernel and Version Dynamics

1.1 clang-format pinned to 22.1.8, 73 kernel source files under src/ reformatted in one pass (10-30)

Date: 2026-10-30 18:20 (merge time) Source: Proposal #11936

75 files, 3852 lines added, 3023 lines deleted, authored by CYFS3, linked to the earlier #11653 and the already-merged #11859. The problem is not the formatting itself: the format-check CI installs clang-format via pip, while the manual formatting workflow installs it via apt, and neither pins a version, so the same code can produce different results at different times, making the format check non-reproducible.

The change is split into three independent commits. First, a new tools/ci/requirements-format.txt pins the version to 22.1.8; both workflows now install from that file, and the manual workflow adds actions/setup-python to provide a Python environment. Second, .clang-format enables AllowShortLoopsOnASingleLine and disables BraceWrapping.BeforeWhile, keeping empty loops on a single line and writing do-while uniformly as } while (...). Third, the same version recursively formats 73 C and header files under src/, including the klibc, utest, perf, and smp subdirectories; 69 produce changes and 4 were already compliant. The Chinese and English coding standards gain three new sections covering installation, version confirmation, and editor configuration.

Kconfig, SConscript, and other directories are out of scope, indicating this is a directory-by-directory formatting convergence rather than a repo-wide reformat.

1.2 dlmodule closes out #5705, reported in 2022 (10-30)

Date: 2026-10-30 10:54 (merge time) Source: Proposal #11915, Defect #5705

2 files, 215 lines added, 45 lines deleted, with changes in dlelf.c and dlelf.h. This fixes defect #5705, reported in March 2022 and open for over four years: accessing uninitialized global variables in dynamic modules caused address overlap or failed relocation. After reproducing it on the latest master, the author broke the root cause into four parts.

First, after a BSS segment (SHT_NOBITS) is loaded, the allocation pointer is not advanced, so multiple NOBITS segments overlap in the same memory. Second, the original implementation shared base addresses across the rodata, bss, and data categories by segment name, rather than computing relocation addresses from the actual load address of the segment each symbol belongs to, so multi-segment scenarios point to the wrong location. Third, relocation of SHN_COMMON symbols (tentatively defined uninitialized globals) was silently skipped—the code read shdr[0xfff2], got a garbage segment name, and failed to match. Fourth, this path never built module->symtab, so dlsym() always failed for ET_REL modules.

The fix addresses all four: advance the allocation pointer after a BSS segment is loaded; compute rodata, bss, and data segment symbols uniformly as “segment load address plus in-segment offset”; allocate a separate common block for SHN_COMMON, with sizing and relocation sharing the same alignment algorithm, and move that branch ahead of segment-name matching to avoid out-of-bounds reads; and collect GLOBAL FUNC symbols from .symtab to build module->symtab, aligning with how the ET_DYN path builds it from .dynsym.

Verification was done on qemu-vexpress-a9 with RT_USING_MODULE enabled, running three test modules covering both the standard ET_DYN flow and the import of kernel symbols via GOT. The impact is on BSPs using the ET_REL load path, with Cortex-M projects that enable dynamic modules affected first.

1.3 Version management CI and release process enter planning (10-30)

Date: 2026-10-30 16:04 (report) / 15:29 (documentation proposal) Source: Defect #11956, Proposal #11955

#11956 was filed by kurisaW with the enhancement label; the body states “planned, not implemented,” and the milestone awaits scheduling after the B01 inventory. The core is to turn the version strategy into runnable CI, reporting, and release tasks: Z versions generate a report and release proposal monthly, with humans deciding whether to release; Y versions are reviewed and released every 3 to 6 months alongside hardware validation; externally, developers are encouraged to use the X and Y baselines first. The text stresses reusing existing GitHub Actions, QEMU BSPs, and the test framework rather than building a separate system.

#11955, submitted at 15:29 the same day, is the companion documentation, writing the mainline version numbering rules and release process into the docs directory; it is still under review. Neither has been merged yet, but the direction is clear: turn a step long handled manually, where baselines drift easily, into an inspectable process.


II. Security Follow-up and Merge Queue

2.1 RT-Smart mailbox does not validate kernel object pointers; forged objects can read and write kernel memory (10-31)

Date: 2026-10-31 14:26 (report time) Source: Defect #11960

Reported by XueDugu, checked against master cbc19778 of that day. The problem is at the mailbox system call entry: it forwards the kernel object pointer passed in by the user directly to the kernel mailbox API, without validating whether the object belongs to the calling LWP, whether it is a mailbox, or whether it resides in kernel memory. A non-privileged process can therefore construct a “forged object” that the kernel reads and writes according to its own rules, which is equivalent to an arbitrary kernel read/write primitive.

The report lays out the timeline completely: the defect was introduced by commit ecf2d8215961 (2022-12-03, RT-Smart system call boundary adjustment), the first affected version is v5.0.0, and v5.3.0 and current master (5.4.0-dev) are still affected. Verification was done at two levels—a QEMU qemu-virt64-aarch64 full-system run (virt, GICv2, single core, 128 MiB, with RT_USING_SMART and RT_USING_MAILBOX enabled) demonstrates the user-to-kernel out-of-bounds path; a Raspberry Pi Pico 2 W (RP2350) validates the kernel mailbox API primitive itself at the board level, the latter running plain RT-Thread in a single address space, to show that the problem is not limited to Smart’s isolation layer.

As of publication, this defect has no assignee and no corresponding fix proposal; the only comment is the CI bot’s /claim notice.

2.2 pipe’s FIONREAD writes directly to a user-supplied pointer—third consecutive defect of the same type (10-30)

Date: 2026-10-30 19:13 (report time) Source: Defect #11958

The same reporter’s second report. In the FIONREAD and FIONWRITE branches, pipe’s ioctl directly does *((int *)args) = ..., writing the ring buffer’s data length or remaining space to the address pointed to by args; RT-Smart’s sys_ioctl() forwards the raw user argument all the way through without copyout, and the pipe layer does not check whether that address is a user address either. As a result, an ordinary process can specify an arbitrary kernel address and have the kernel write four bytes there, with the written value constrained by the pipe’s current state.

Affected range is v5.0.0 through v5.3.0 and master (5.4.0-dev); verification was done on QEMU vexpress-a9, Cortex-A9, 32-bit RT-Smart, with RT_USING_POSIX_PIPE enabled and a 512-byte pipe buffer.

This is the third consecutive defect of the same type: first the terminal subsystem’s ioctl dropped FreeBSD’s copyin precondition (defect #11937), then the block device wrote a 24-byte partition table to a caller-specified kernel pointer (#11952), and now pipe (#11958). All three share the same cause—the fops layer retains the old assumption that “the argument is already a kernel address,” while the user-space entry point never added a conversion layer. The mailbox defect in 2.1 belongs to the same family left by the same introducing commit, except that the out-of-bounds direction changes from “writing into it” to “treating a user pointer as a kernel object.”

2.3 Count multiplication wraparound in poll and epoll (10-30)

Date: 2026-10-30 11:59 (proposal time) Source: Proposal #11954

1 file, 28 lines added, fixing the first half of #11925. sys_poll() uses the user-supplied count to compute the kernel buffer size; on 32-bit the multiplication wraps, but the original unwrapped count is still used for iteration afterward: with nfds = 0x20000001 and an 8-byte pollfd structure, the product 0x1_00000008 is truncated to 8; the access check and kmem_get both pass on 8 bytes, yet poll() iterates 536,870,913 entries, and reading pollfd->fd and writing revents in do_pollfd() all fall outside the allocated block. 64-bit builds are unaffected: the product is promoted to 64 bits and an oversized allocation simply returns ENOMEM.

sys_epoll_pwait() has the same shape, and its count is an int, so negative values must be rejected as well. The fix checks before using these counts to compute any size: if nfds is greater than SIZE_MAX / sizeof(*fds), return -EINVAL; on the epoll side, add a check for count less than 0. The style matches the msg_iovlen validation in sys_sendmsg and sys_recvmsg.

Also in flight in the same batch are #11899 (sys_sigaction validates the signal number) and #11895 (signal delivery order and ELF segment protection); their common thread is validating user-supplied numbers, lengths, and pointers before entering kernel logic.

2.4 RISC-V AIA: APLIC level-interrupt EOI unconditionally writes setipnum (11-01)

Date: 2026-11-01 20:40 (proposal time) Source: Proposal #11966

8 files, 1367 lines added, 10 lines deleted. The symptom: running bsp/qemu-virt64-riscv on QEMU 8.2.2 with RV64, four-core SMP, and AIA (APLIC and IMSIC) configured, a counting program with rt_thread_mdelay(1000) prints only “RISC-V test: 0” and then stalls; the delay thread never comes back.

Root cause: the APLIC driver unconditionally writes setipnum_le when handling the EOI of a level interrupt. After the device has already deasserted the interrupt, older QEMU may still generate a new MSI because of this write, producing a continuous spurious interrupt that starves the system timer handler, so the delay thread cannot resume. The fix first reads the corresponding valid input state in in_clrip (rectified input, with interrupt polarity already taken into account) and writes setipnum_le only when the device still holds the interrupt asserted—preserving the level interrupt’s retrigger capability without firing an extra shot for an already-deasserted interrupt.

The reproducer was changed as well: the BSP’s main.c goes from “print Hello RISC-V once” to a counting loop from 0 to 9, with a one-second delay after each print. Verification environment is QEMU 8.2.2, OpenSBI v1.3, riscv64-unknown-elf-gcc 13.2.0; all three configurations—AIA enabled, four cores, with networking, NVMe, virtio-console, and PCI serial disabled—produce complete output.


III. Official and Community Activities

3.1 Wuhan stop of the roadshow training lands on 10-31, Edgi-Talk dual-core four experiments (10-31)

Date: 2026-10-31 10:00 ~ 17:30 (event time) Source: Official column: Wuhan hands-on session

The Wuhan stop of the RT-Thread roadshow training was held in Room 801, Teaching Building 2, West Campus, China University of Geosciences Wuhan. The hardware was the Infineon PSoC Edge E84-based Edgi-Talk dual-core development board, and four experiments were walked through in sequence: GUI display, handwriting recognition, LLM web-side deployment, and XiaoZhi AI. All project code and configuration files were provided on site.

The LLM segment used the llmchat software package plus Tongyi Qianwen (qwen-plus by default), then enabled llmchat’s webnet mode so that a browser could access the board’s IP and hold a conversation. The write-up documents the pitfalls in detail: the webnet thread stack must be raised to 8K, and mbedtls’s maximum fragment length must be changed to 6144, otherwise the TLS handshake fails; the lwIP thread stack must be 4096; and the html must be transferred via ymodem to the /flash/webnet directory.

The XiaoZhi AI segment used the official Edgi_Talk_M55_XiaoZhi project. On first network configuration it defaults to AP mode: the phone connects to the hotspot broadcast by the board, then opens the default gateway page to select a Wi-Fi network. The wake word is “Xiao Rui, Xiao Rui”, after which commands such as “turn on the light” or “brighten the screen” are routed via MCP to three peripherals: LED, backlight, and volume. This board is one of the designated platforms for this year’s embedded competition, so the training effectively served as pre-competition practice.

3.2 November 4 livestream: keep the large model on the PC, recreate the Blue Whale desktop pet with Ruiqing 3576 (10-30)

Date: 2026-10-30 11:50 (published) Source: Official column: Ruiqing 3576 desktop pet livestream

On November 4 (Wednesday) at 20:00, the Ruiqing tech livestream channel will run a live demo on “recreating the DeepSeek Blue Whale desktop pet with Ruiqing 3576”. The author has already connected the PC-side DeepSeek to the 3576 development board, recreating the desktop pet character from DeepSeek Harness.

The architectural choice is worth noting: the large model does not run on the board. The “brain” stays on the PC and the “body” is handed to the 3576. The livestream covers four parts: where compute goes and how the persona is defined; how to pair via the DSH mobile bridge entry when the board and the computer are not on the same subnet, using curl on site to obtain a short-lived Token in exchange for a communication Cookie before sending RPCs; how interfaces such as session.create and session.prompt send text out and read replies back; and subsequently using LVGL to draw three states—listening, thinking, speaking—integrating ASR and TTS, and letting the large model directly control peripherals.

This line of work is a useful reference for teams building edge AI: it acknowledges the compute limits at the edge, placing interaction and presentation on the board while leaving inference upstream—the same trade-off as competition entries that “run small models on the NPU and send complex judgments to the cloud”.

3.3 Official news feed still stuck at June 17 (11-02)

Date: 2026-11-02 (verification) Source: RT-Thread official news list

The latest entry returned by the official news feed is still the 2026-06-17 item “Ruiside Technology invited to attend the 2026 Abu Dhabi Investment Forum”; there were no new additions this issue. The homepage of the official news list also had no new posts during the same period.

The actual publishing outlet has shifted to media columns: the RT-Thread official column on EET China updated two pieces within the window (the 10-30 Wuhan session and the 11-04 livestream preview), while a November 1 Double 11 promotion piece was not included. Community project posts and discussions remain on the forum, but the site now fronts a WAF challenge page, so the list could not be read directly this issue; competition entry information was instead cross-verified from GitHub repository READMEs and media columns.


IV. Ecosystem and Vendor Adaptation

4.1 NXP RT1180 industrial Ethernet linker script enters the review queue (10-30)

Date: 2026-10-30 19:57 (proposal time) Source: Proposal #11959

A BSP proposal for the NXP i.MX RT1180, adding the linker script required for industrial Ethernet scenarios. The RT1180 carries multiple gigabit Ethernet ports and a TSN switch; such projects have stricter requirements on memory partitioning and section layout than general-purpose BSPs, and the linker script often has to land first before drivers and other peripherals can be connected. The proposal is still in the queue with no merge date.

Three other hardware-side and low-level small fixes are also queued in the same window: #11961 initializes static TLS for C++ threads; #11965 prevents gcc from recognizing the byte loop in klibc’s kstring.c as memset and memcpy calls—self-implemented string functions being rewritten by the compiler into library function calls is a rewrite that needs separate justification in a kernel bootstrap context; #11963 and #11964 are two utest additions, making the mailbox test case repeatable and covering signal delivery to a thread blocked in mdelay, respectively.

4.2 Two of the driver defects reported last issue now have patches (10-30 ~ 10-31)

Date: 2026-10-30 18:16 / 10-31 21:11 (proposal time) Source: Proposal #11957, Proposal #11962

Two of the four driver-side defects reported in the previous issue have now received patches. #11957 addresses the divide-by-zero in DM365 SPI: rejecting max_hz of 0 during setup so that the prescaler calculation does not treat it as a divisor. #11962 addresses the Bluetrum AB32 ADC: validating the channel number before reading, rather than silently falling back to 0 after a mapping failure and then indexing the data register array with the raw channel number.

Neither has been merged yet, and the other two (Bouffalo ADC out-of-bounds read #11949, HPM ADC channel state indexing #11951) still have no corresponding proposal this issue. The common thread among these defects is unchanged: the rt_adc_read() and rt_spi_configure() layer performs no parameter validation and pushes the responsibility down to each driver, and most drivers do not do it.


V. Industry Applications

5.1 Post-competition open-sourcing: four edge AI vision projects on two boards (10-30 ~ 11-01)

Date: 2026-10-30 ~ 2026-11-01 (repository creation time) Source: Repo: Titan Mini PCB Inspector

Fifteen new RT-Thread-related repositories appeared on GitHub within the window, 7 of which describe themselves as entries to the 2026 RT-Thread Embedded Competition. Their open-sourcing clusters between 10-30 and 11-01, matching the competition requirement to post about the work on the forum and open-source the code.

Two run on the Renesas Titan Board Mini (RA8P1, Cortex-M85 plus Ethos-U55). The first is Titan Mini PCB Inspector: camera-based board inspection, 800×480 LCD display, serial HMI interaction, with Ethos-U55 doing local inference and a cloud LLM writing suggestions; when offline it falls back to table-driven expert rules rather than failing silently. The second is Lingxi Zhimou: an INT8-quantized pose model detects up to 10 people per frame with 17 keypoints each, then rule-based logic classifies four behaviors—hand raised, head down on desk, standing, sitting upright—and outputs a weighted focus score from 0 to 100. Events are timestamped and written to a CSV on SD card; raw footage never leaves the classroom.

Two more, both named SENTINEL, run on the Fullhan MC632X (Cortex-A7). One connects to an M5Stack AtomS3R XiaoZhi for voice announcements, with dual 800×480 MJPEG web preview, human detection and tripwire entry/exit counting, switching at night to perimeter arming and video evidence capture. The other emphasizes standalone operation without a PC—one power cable and one Ethernet cable—automatically completing network provisioning, the media pipeline, and web service startup on power-up.

All four make the same trade-off: push models down to the on-device NPU or MCU, hand complex judgment to the cloud or a rule engine, and keep raw footage off the device. This is the same engineering judgment as “brain on the PC, body on the board” from the 3.2 livestream.

5.2 From competition board to production line: dual Cortex-M7 20 kHz sensorless FOC and encoder-closed-loop positioning (10-31)

Date: 2026-10-30 ~ 2026-11-01 (repository creation time) Source: Repo: NS800RT7P65D FOC and CANopen

The NOVOSENSE NS800RT7P65D is a dual Cortex-M7 motor control chip, and this project splits it into two logical CPUs: one runs 20 kHz ADC sampling and PWM, performing sensorless FOC, sliding-mode observer and PLL estimation, with hardware shutdown; the other runs UART and FinSH, CANopenNode v4.1 with CiA 402 bridging, and CAN transmit/receive. Cross-core communication uses only an asynchronous command mailbox and a single six-field, 24-byte consistency snapshot—no haphazard shared-memory reads. The underlying layer is RT-Thread 5.3.1 in SMP configuration.

EdgeDoctor-RT on the Infineon PSoC Edge E84 takes a different path: it processes one vibration data block every 20 ms, extracts 64-dimensional band features over a 1-second sliding window, and feeds them to a 64-32-5 MLP that classifies five states—normal, bearing inner-race fault, bearing outer-race fault, misalignment, imbalance—along with confidence and recommended action. The baseline is the official Edgi_Talk_M55_XiaoZhi v1.4.0, with only the application layer layered on; boot, linking, HAL and Wi-Fi resources are untouched.

Two motion-control entries better illustrate how far competition boards have descended: one on the NXP FRDM-MCXA346 does closed-loop stepper positioning with encoder feedback and a Python/Tkinter host application, running 10-degree and 90-degree positioning, a 45-degree relative reversal, and return to software zero; the other is a detection cart with ultrasonic obstacle avoidance and smoke detection, with visual recognition on the PC side.

The platform distribution is worth noting: two each on Titan Board Mini and MC632X, one on PSoC Edge E84, one on NS800RT7P65D, and two on FRDM-MCXA346—covering five of the boards on the competition’s board list.


6.1 Trend: quiet on merges, dense on patches—RT-Smart’s boundaries are being systematically audited

In this issue’s 72-hour window the main repository saw only 2 merges (the dlmodule fix at 10-30 10:54 and the clang-format reflow at 18:20), but 11 new proposals and 3 new defects were opened, all between 10-30 and 11-01. A weekend window with “few merges, many submissions” is normal; what matters is not the count but where they land.

The first thread is engineering infrastructure. Pinning the clang-format version addresses the same code yielding different formatting conclusions on different machines; version-management CI and the release process address baseline drift and the unclear release boundary between Z and Y. Neither changes a line of kernel logic, yet both determine whether all subsequent patches can be reviewed reliably—the previous issue’s split of that 11,000-line single lwp file into 20 files followed the same path.

The second thread is RT-Smart’s user-space boundary. Terminal ioctl, block device ioctl, pipe ioctl, and mailbox object pointers—four issues with the same shape: the fops and syscall layers still assume “the argument is already a kernel address, the object is already a kernel object.” The reporter traced the introducing commit to ecf2d8215961 on 2022-12-03, showing this is not a regression from new code but a boundary that has never been systematically validated since it was established. In-flight patches cover poll and epoll count wraparound, sigaction signal numbers, ELF segment protection and static TLS—the direction is right, but the mailbox and pipe patches remain unclaimed.

The third thread is how the ecosystem expresses itself. The official news feed has been stalled at June 17 for a sixth month, with external announcements now carried by media columns; community activity has clearly shifted to “works”—7 competition entries open-sourced to GitHub in one weekend, five in edge AI vision and diagnostics, two in motors and motion control. For anyone tracking RT-Thread adoption, these repositories say more about what board vendors and developers are doing with it than official press releases.

6.2 Limitations and deduplication notes

The forum club.rt-thread.org served a WAF challenge page in this issue’s window, so the works-post list and article bodies could not be read directly. Competition entry information was instead cross-verified against GitHub repository self-descriptions (README, directory structure, creation time) and the official EET China column, without post-by-post comparison against the forum originals.

All 5 HN Algolia hits in the window were word-sense false matches on “thread” (Pulling on a Thread, HN Replies, the French download tax, etc.) and were discarded wholesale; Google News returned zero hits on the English side, and 2 of 3 Chinese-side hits were included (Wuhan training, the 11-04 livestream), while the 11-01 Double 11 promotional piece was not. Items #11897 (K230D), #11892 (RISC-V Smart MMU), #11944 (RTL8125) and #11943 (RK3588 display audio), placed in the pending-review queue in the previous issue, remain queued with no merges this issue, so they are not repeated as entries.


Appendix: Source Verification Table and Source List

Source Verification Table

Source Verification Result
Official news feed (rt_org) No new items in 72 hours; latest entry remains at 2026-06-17
Community article feed Site fronted by a WAF challenge page; list and body text could not be read directly this period
Main repo commits 2 within the window (10-30 10:54, 18:20)
Main repo PRs 2 merged (#11915, #11936); 11 newly opened, all under review
Main repo Issues 3 newly opened (#11956, #11958, #11960)
Main repo releases and tags No new items; latest remains v5.3.0 (2026-09-10)
RT-Thread org (35 repos) Only the main repo had pushes within the window; packages 10-23, pkgs-test 10-23, sdk 10-25, vscode-rt-smart 10-26 all fall outside the window
GitHub repository search (rt-thread) 15 newly created, 7 of which self-describe as 2026 embedded competition entries
Google News Chinese 3 hits, 2 included, 1 promotional piece excluded
Google News English Zero hits
HN Algolia 5 false matches on the word “thread”; entire batch discarded
EET-China official column 2 articles within the window (10-30), both included

Full Source List