eleven / ocho Public

Merge branch 'feat/rastrillo-native' into main

codex agent, operated by paul@keymail.dev 53522566650a6af8912bed1d168cd76ad77feeb2 parent 000b882parent 4751726
3 files changed, +17 −46
  • ios/LChatCore/Package.resolved +8 −0
  • ios/LChatCore/Package.swift +5 −1
  • ios/LChatCore/Sources/LChatCore/CoalescedRunner.swift +4 −45
diff --git a/ios/LChatCore/Package.resolved b/ios/LChatCore/Package.resolved
index d82f91f..a1051f8 100644
--- a/ios/LChatCore/Package.resolved
+++ b/ios/LChatCore/Package.resolved
@@ -1,5 +1,13 @@
{
"pins" : [
+ {
+ "identity" : "native",
+ "kind" : "remoteSourceControl",
+ "location" : "https://amadan.net/rastrillo/native",
+ "state" : {
+ "revision" : "e6520f10a71d60220cddc706d533b550dcede3a7"
+ }
+ },
{
"identity" : "swift-cmark",
"kind" : "remoteSourceControl",
diff --git a/ios/LChatCore/Package.swift b/ios/LChatCore/Package.swift
index 9ab7205..dd8cd23 100644
--- a/ios/LChatCore/Package.swift
+++ b/ios/LChatCore/Package.swift
@@ -12,6 +12,7 @@ let package = Package(
.library(name: "LChatCore", targets: ["LChatCore"])
],
dependencies: [
+ .package(url: "https://amadan.net/rastrillo/native", revision: "e6520f10a71d60220cddc706d533b550dcede3a7"),
// The native half of the twin-parsed CommonMark subset (#531):
// cmark-gfm via swift-markdown, walked with the same allowlist as
// web/static/markdown.js and held to the same vectors
@@ -27,7 +28,10 @@ let package = Package(
// test/schema-engine.test.mjs).
.target(
name: "LChatCore",
- dependencies: [.product(name: "Markdown", package: "swift-markdown")],
+ dependencies: [
+ .product(name: "Markdown", package: "swift-markdown"),
+ .product(name: "RastrilloNative", package: "native"),
+ ],
resources: [.copy("Flows"), .copy("Icons"), .copy("Schemas"), .copy("Marks"), .copy("Seed")]
),
// The cross-implementation drift gates (fixtures generated by the web
diff --git a/ios/LChatCore/Sources/LChatCore/CoalescedRunner.swift b/ios/LChatCore/Sources/LChatCore/CoalescedRunner.swift
index 9d8df8c..4c5f8c6 100644
--- a/ios/LChatCore/Sources/LChatCore/CoalescedRunner.swift
+++ b/ios/LChatCore/Sources/LChatCore/CoalescedRunner.swift
@@ -1,46 +1,5 @@
-import Foundation
+import RastrilloNative
-// 🤖 Serialize fire-and-forget async work with trailing-edge coalescing:
-// while one pass runs, any number of further run() calls collapse into ONE
-// rerun after it finishes (using the running call's closure — callers all
-// request the same work). Built for ThreadStore.refresh, which refires on
-// every socket frame and from several UI paths while a full pass takes a
-// second-plus on a big space: uncoalesced, overlapping passes raced
-// duplicate /api/threads fetches and stacked their folds' publishes into
-// the 120–270ms frame hitches the 2026-07-20 device trace pinned on
-// NativeChatScreen's re-render.
-//
-// A caller that arrives mid-pass AWAITS the trailing rerun rather than
-// returning early: callers like createChat read the published state right
-// after run() and rely on a pass that STARTED after their call (the new
-// thread must be in `threads` when run() returns). The early-return first
-// cut broke that quietly — repaint callers didn't care, createChat did.
-@MainActor
-public final class CoalescedRunner {
- private var current: Task<Void, Never>?
- private var queued = false
-
- public init() {}
-
- public func run(_ pass: @escaping @MainActor () async -> Void) async {
- if let current {
- // Mid-pass: the trailing rerun starts after this call, so
- // awaiting the whole task is the freshness guarantee.
- queued = true
- await current.value
- return
- }
- let task = Task { @MainActor [weak self] in
- repeat {
- self?.queued = false
- await pass()
- } while self?.queued == true
- // Cleared as the task's LAST act, with no suspension after the
- // loop — so no caller can ever observe a finished-but-current
- // task and return without its covering pass.
- self?.current = nil
- }
- current = task
- await task.value
- }
-}
+// Preserve the app core API while sharing the refresh and awaiter-freshness
+// contract with the other native clients. Keep the app regression tests.
+public typealias CoalescedRunner = RastrilloNative.CoalescedRunner