Seed registry-owned SystemIO service - #12342
Draft
franknoirot wants to merge 10 commits into
Draft
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
franknoirot
force-pushed
the
codex/systemio-operation-core
branch
from
July 6, 2026 17:29
edc38bb to
63e1f9e
Compare
franknoirot
force-pushed
the
codex/systemio-operation-core
branch
from
July 6, 2026 18:12
63e1f9e to
ee1b0d6
Compare
franknoirot
force-pushed
the
codex/systemio-operation-core
branch
from
July 23, 2026 15:59
ee1b0d6 to
d8b4afd
Compare
franknoirot
force-pushed
the
codex/systemio-operation-core
branch
from
July 23, 2026 17:37
d8b4afd to
1ea4ddd
Compare
This was referenced Jul 23, 2026
franknoirot
force-pushed
the
codex/systemio-operation-core
branch
from
July 24, 2026 17:56
1ea4ddd to
b594e97
Compare
The pure-systemIO operation-core refactor left the legacy XState actor no longer driven into readingFolders, breaking the service<->actor bridge in both directions and dropping project-list updates. - systemIOMachine: handle setFolders while idle, where the service now permanently sits and pushes refresh results as a legacy bridge. - service: skip actor snapshots with undefined folders so an unrelated idle snapshot can't clobber the freshly-loaded project list; keep the stopped actor reference on dispose so late send/subscribe calls are absorbed instead of crashing app.systemIOActor consumers. - operationQueue: only coalesce into a still-queued operation, so a refresh triggered after a filesystem mutation re-reads instead of reusing an in-flight scan that predates the change. - homeProjects: clear lastRefreshKey when a refresh fails so a transient error no longer permanently blocks re-requests for that directory. Adds regression tests for each fix. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The `latestRefreshId` guard reads as a per-directory bug at first glance, but it is deliberate: `projects`/`projectHandles` model a single current project directory, and the most recently started refresh must win so a stale in-flight refresh (e.g. for a directory the user navigated away from) cannot clobber newer state. Same-directory refreshes are already serialized by the operation queue, so the guard only arbitrates across directories. Comment this so it is not mistaken for a concurrency defect. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…jections Callers that only watch the status signals never read `operation.result`, so a failed or cancelled operation's rejection could escape as an unhandled promise rejection. Attach an internal no-op catch to the queue-owned result promise; observers that await `.result` still receive the rejection through their own handler. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Previously, folding a request into a still-queued operation returned the existing operation and silently dropped the new caller's handler and request payload, so the work enqueued first always won. Track the request/handler mutably and adopt the newest intent when coalescing, so a still-queued operation runs the freshest handler/request when it starts. Behavior is unchanged for identical duplicate refreshes (the current only caller), and running operations are still never coalesced into. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Operation snapshots were retained forever, so a long-lived session that refreshes on every mutation/watcher event grew the `operations` array without bound. Add a writable `recordLimit` signal (default 200) that evicts oldest settled records once the count exceeds it, while never dropping in-flight operations. Expose it on the service as `operationRecordLimit` so a debug/inspection UI or a developer in a pinch can raise it — set it to `Infinity` to keep every record. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ion-core # Conflicts: # src/registry/extensions/homeProjects/index.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This rebases the original SystemIO operation-core seed onto current
mainafter #12551 and turns it into the first registry-owned SystemIO service step:src/lib/systemIO, withsrc/registry/contracts/systemIO.tsleft as a compatibility re-exportsystemIOService.request(...)API, currently starting withprojects.refreshsystem-ioextension that providessystemIOServiceand reads project directories through the merged project-library scanner plus the registry-provided WASM bundlesystemIOMachineImplactor lifecycle, withApp.systemIOActorkept as a compatibility getter instead of an App-owned actor instanceprojectssignals and legacy actorfolderscontext synchronized while callsites migratesystemIOService.actorto the new service request/signal APIApp.buildSingletons()bridge that provided the oldsystemIOActorassystemIOServiceBoundary
This is still intentionally a first slice. Legacy actor callsites remain for route loaders, command flows, Zookeeper/file replay, file mutations, watchers, and the remaining XState machine operations. The important ownership change is that
Appno longer constructs or stops that actor; the registry-owned SystemIO service does. The next steps should move one actor-invoked operation at a time behind this service instead of folding every route/session/UI behavior into one oversized PR.Validation
npm run test:unit -- src/lib/systemIO/operationQueue.test.ts src/lib/systemIO/service.test.ts src/lib/homeProjects.test.tsnpm run test:integration -- src/registry/contracts/homeProjects.spec.ts src/registry/contracts/projectLibraries.spec.ts src/lib/app.spec.tsnpm run tsc -- --pretty falsenpm run lint