Skip to content

feat(sdk): StorageProvider abstraction — complete migration + example providers#640

Merged
bradygaster merged 1 commit intobradygaster:devfrom
diberry:diberry/storage-abstraction-squashed
Mar 30, 2026
Merged

feat(sdk): StorageProvider abstraction — complete migration + example providers#640
bradygaster merged 1 commit intobradygaster:devfrom
diberry:diberry/storage-abstraction-squashed

Conversation

@diberry
Copy link
Copy Markdown
Collaborator

@diberry diberry commented Mar 26, 2026

What

StorageProvider abstraction layer for the Squad SDK -- pluggable persistence with 3 built-in providers.

Why

  • Squad currently uses direct filesystem access for all persistence
  • No way to swap storage backends for testing (InMemory), cloud deployment (Azure Blob), or embedded use (SQLite)
  • Contributors implementing custom providers need a clear interface contract

What's Included

Core Interface

  • StorageProvider interface with 24 methods (async + sync, sync deprecated for Wave 2 removal)
  • StorageError with typed code and operation fields, sanitized error messages

Built-in Providers

Provider Use Case Notes
FSStorageProvider Default, local development Drop-in for current behavior
InMemoryStorageProvider Testing, ephemeral sessions Map-backed, no disk I/O
SQLiteStorageProvider Embedded, single-file persistence WASM-based, requires init()

Dependency Injection

All public API entry points accept optional StorageProvider parameter with FSStorageProvider as the sensible default. 10 public API files use Pattern A (DI with defaults), 25 internal files use Pattern B (module singletons behind public API). Zero hardcoded instances (Pattern C) found. Full analysis in comments below.

Testing

  • Contract test suite (test/storage-contract.ts) covering all 24 interface methods
  • Tests run against all 3 providers (FS, InMemory, SQLite)
  • 389 tests pass, 6 skipped

Documentation

  • CHANGELOG entry under [Unreleased]
  • SDK README "Storage Abstraction" section with provider comparison + BYO provider example
  • Docs feature page at docs/src/content/docs/features/storage-provider.md with decision matrix
  • Enhanced JSDoc: StorageError class/properties, SQLiteStorageProvider lifecycle, deprecation migration examples for all 12 sync methods
  • Navigation updated, docs-build test updated

Package Exports

  • Added ./storage subpath export to packages/squad-sdk/package.json
  • Enables: import { StorageProvider } from '@bradygaster/squad-sdk/storage'

Samples

  • samples/storage-provider-sqlite/ -- SQLite provider demo
  • samples/storage-provider-azure/ -- Azure Blob Storage provider demo
  • Both demonstrate the DI swap pattern

How to Review

  1. Start with packages/squad-sdk/src/storage/storage-provider.ts -- the interface
  2. Then storage-error.ts -- error handling contract
  3. Then the 3 providers: fs-storage-provider.ts, in-memory-storage-provider.ts, sqlite-storage-provider.ts
  4. Then test/storage-contract.ts and test/storage-provider.test.ts -- contract tests
  5. Then docs: docs/src/content/docs/features/storage-provider.md, README section, CHANGELOG

Breaking Changes

None. FSStorageProvider is the default everywhere -- existing behavior is unchanged. New providers are opt-in via DI.

Related

StorageProvider Dependency Injection Analysis

We audited all FSStorageProvider references outside the storage module to verify the abstraction is properly swappable. Result: clean DI throughout.

Pattern A: Default Parameters (10 files) -- CORRECT DESIGN

Functions/constructors accept StorageProvider as an optional parameter with FSStorageProvider as the sensible default. Callers CAN pass any provider.

Files: config/init.ts, config/models.ts, config/legacy-fallback.ts, config/agent-source.ts, agents/personal.ts, agents/onboarding.ts, agents/lifecycle.ts, agents/history-shadow.ts, agents/index.ts, tools/index.ts

Example:

// Default -- works out of the box
new SquadAgents()

// Custom provider -- fully swappable
new SquadAgents(sqliteProvider, state)

Pattern B: Module-Level Singletons (25 files) -- INTERNAL ONLY

Module-scope const storage = new FSStorageProvider() used by internal functions. These are implementation details behind Pattern A's public API -- not exposed to consumers.

Files: casting/index.ts, resolution.ts, runtime/config.ts, build/bundle.ts, build/release.ts, multi-squad.ts, ralph/index.ts, ralph/capabilities.ts, ralph/rate-limiting.ts, platform/comms.ts, platform/comms-file-log.ts, platform/index.ts, remote/bridge.ts, skills/skill-loader.ts, skills/skill-script-loader.ts, skills/skill-source.ts, streams/resolver.ts, upstream/resolver.ts, marketplace/packaging.ts, sharing/consult.ts, sharing/export.ts, sharing/import.ts, runtime/cross-squad.ts, runtime/scheduler.ts, runtime/squad-observer.ts

Pattern C: Hardcoded -- NONE FOUND

Zero instances of FSStorageProvider hardcoded with no way to override. Every public entry point accepts StorageProvider via DI.

How Samples Prove It

The samples demonstrate the swap works in practice:

  • samples/storage-provider-sqlite: passes SQLiteStorageProvider
  • samples/storage-provider-azure: passes AzureBlobStorageProvider

Verdict

The StorageProvider abstraction follows standard dependency injection with sensible defaults. FSStorageProvider is the default (convenience), not hardcoded (coupling). Any provider implementing the 24-method interface can be injected at every public API boundary.

@diberry diberry marked this pull request as draft March 26, 2026 21:30
@diberry diberry force-pushed the diberry/storage-abstraction-squashed branch from cfc907b to ce8876f Compare March 26, 2026 21:34
@diberry diberry marked this pull request as ready for review March 26, 2026 21:41
larsontim12 pushed a commit to larsontim12/squad that referenced this pull request Mar 27, 2026
…t command (bradygaster#640)

P0: Race condition eliminated (auto-cast in onReady), Ctrl+C aborts init session, orphan .init-prompt cleanup. P1: /init triggers casting, clear empty-roster banner. 3243 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
larsontim12 pushed a commit to larsontim12/squad that referenced this pull request Mar 27, 2026
* test(shell): add auto-cast trigger and /init command coverage

35 new tests in test/init-autocast.test.ts covering the P0/P1 init
reliability fixes from PR bradygaster#640:

- hasRosterEntries predicate: 7 tests (populated/empty/missing Members)
- Auto-cast trigger conditions: 6 tests (fire/no-fire matrix)
- Orphan .init-prompt cleanup: 3 tests (delete/preserve logic)
- /init command triggerInitCast signal: 7 tests (with args/no args/edge)
- triggerInitCast App.tsx dispatch contract: 3 tests (shape/exclusion)
- activeInitSession Ctrl+C abort lifecycle: 5 tests (abort/clear/error)
- handleInitCast .init-prompt consumption: 4 tests (override/cleanup)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(hockney): log auto-cast test coverage learnings

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(shell): P2 cast confirmation before team creation

After the coordinator proposes a team via handleInitCast, the REPL now
shows the formatted proposal and waits for the user to confirm (y/yes)
or reject (n/no) before calling createTeam.

Confirmation is skipped when:
- Auto-cast fires from .init-prompt (user ran squad init "prompt")
- /init "prompt" command (explicit user action)

Freeform REPL messages hitting an empty roster now pause for approval,
preventing garbage casts from vague or accidental prompts.

Implementation:
- pendingCastConfirmation state holds proposal + original parsed input
- handleDispatch intercepts y/n before normal routing
- finalizeCast() extracted as shared helper for both paths
- handleCancel clears pending state on Ctrl+C
- skipCastConfirmation flag on ParsedInput for /init trigger

Closes bradygaster#641

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: update Fenster history and decision for cast confirmation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@diberry diberry marked this pull request as draft March 27, 2026 20:21
@diberry diberry force-pushed the diberry/storage-abstraction-squashed branch 2 times, most recently from 0827911 to f0f8011 Compare March 27, 2026 21:13
@diberry diberry closed this Mar 27, 2026
@diberry diberry reopened this Mar 28, 2026
@diberry diberry force-pushed the diberry/storage-abstraction-squashed branch from f0f8011 to a41a03f Compare March 28, 2026 17:45
diberry pushed a commit to diberry/squad that referenced this pull request Mar 28, 2026
…radygaster#640)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
diberry pushed a commit to diberry/squad that referenced this pull request Mar 28, 2026
…r#640)

## Fix 1: SDK README section
Added 'Storage abstraction' section to packages/squad-sdk/README.md covering:
- What it is (pluggable persistence layer)
- Built-in providers table (FSStorageProvider, InMemoryStorageProvider, SQLiteStorageProvider)
- BYO provider example code
- Links to sample projects

## Fix 2: Docs feature page
Created docs/src/content/docs/features/storage-provider.md with comprehensive coverage:
- Overview paragraph explaining StorageProvider purpose
- Built-in providers section with detailed comparison table
- Create a custom provider section with implementation skeleton
- Decision matrix for choosing the right provider
- Links to sample projects (storage-provider-azure, storage-provider-sqlite)

## Docs sync
Updated test/docs-build.test.ts EXPECTED_FEATURES array to include 'storage-provider' in alphabetical order.
Updated docs/src/navigation.ts to add Storage Provider feature link.

All documentation follows Microsoft Style Guide conventions:
- Sentence-case headings
- Active voice, second person, present tense
- Tables for comparisons, bullets for features
- Concise, scannable format

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
diberry pushed a commit to diberry/squad that referenced this pull request Mar 28, 2026
…radygaster#640)

- StorageError: add class-level JSDoc explaining path sanitization,
  plus JSDoc for code and operation properties
- SQLiteStorageProvider: add comprehensive class-level JSDoc covering
  initialization requirements, concurrency limitations, and DB location;
  enhance init() JSDoc with idempotency and error details
- StorageProvider interface: add migration examples to all 12 deprecated
  sync method JSDoc tags showing the async equivalent call
- Contract tests already exist in test/storage-contract.ts covering all
  3 providers (FS, InMemory, SQLite) with 389 passing tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@diberry diberry force-pushed the diberry/storage-abstraction-squashed branch 4 times, most recently from 4e1b9da to 58cdfcb Compare March 28, 2026 20:31
@diberry
Copy link
Copy Markdown
Collaborator Author

diberry commented Mar 29, 2026

How PR #640 (StorageProvider) and #680 (StateBackend) Work Together

They operate at different abstraction layers — complementary, not competing.

The Layering

Squad Runtime (agents, config, tools, etc.) ↓ calls StateBackend (#680) — WHERE does .squad/ state live? ↓ delegates to StorageProvider (#640) — HOW do we read/write?

What Each Does

PR #640 — StorageProvider PR #680 — StateBackend
Question How do files get read/written? Where does .squad/ state live?
Scope All SDK persistence (generic) Only .squad/ state files
Methods 24 (read, write, append, mkdir, stat, copy, rename…) 6 + doctor (read, write, exists, list, remove)
Implementations FSStorage, InMemory, SQLite OrphanBranch (git plumbing), Filesystem
Solves Testability, cloud deployment, pluggable I/O State destroyed by branch switches (#643), .squad/ in VCS (#498)

How They Compose

  • OrphanBranchBackend uses git plumbing directly — StorageProvider is irrelevant here. It reads/writes blobs via git hash-object, git show, git mktree. No filesystem involved.

  • FilesystemBackend currently uses raw node:fs/promises — but after feat(sdk): StorageProvider abstraction — complete migration + example providers #640 merges, it should be refactored to delegate to StorageProvider instead. This makes it a thin wrapper:

ypescript FilesystemBackend.read(path) → this.storageProvider.read(join(this.root, path))

That gives you the full matrix for free:

StateBackend.resolve() ├── OrphanBranchBackend → git plumbing (no StorageProvider) └── FilesystemBackend → StorageProvider ├── FSStorageProvider (local dev) ├── InMemoryStorageProvider (testing!) └── SQLiteStorageProvider (embedded)

Tension: Duplicated Surface

FilesystemBackend (6 methods, raw node:fs) is almost identical to FSStorageProvider (24 methods, wraps node:fs). Once both merge, FilesystemBackend should become a ~20-line adapter that takes a StorageProvider in its constructor and delegates.

Merge Order

#640 first, then #680 adapts is cleaner — #680's FilesystemBackend can accept StorageProvider from day 1 instead of landing with raw fs and needing a follow-up refactor. Since #680 is marked DO NOT MERGE (POC), this is natural.

Summary

They solve different problems that stack cleanly. StorageProvider = the I/O engine. StateBackend = the location strategy. The filesystem backend is the bridge where they meet.

@diberry
Copy link
Copy Markdown
Collaborator Author

diberry commented Mar 29, 2026

🐕 FIDO — Devil's Advocate Repo Health Review

Verdict: 🟡 CONDITIONAL — Implementation is solid (2,800+ lines of tests, clean DI patterns), but CI blind spots need attention.


🔴 BLOCKING — Fork Branch Missing 2 CI Gates

CI Gate Upstream dev PR Branch
docs-quality
test
publish-policy
changelog-gate ❌ MISSING
exports-map-check ❌ MISSING

The new ./storage subpath export was never validated by the exports-map-check gate. The fork branch diverged before those gates were added. Post-merge they'll work from dev, but the validation window was missed.

Action needed: Manually verify ./storage export resolves correctly, or rebase onto latest dev to pick up the gates.


🟡 CONCERNS

1. New samples are CI-invisiblestorage-provider-sqlite and storage-provider-azure lack build/test scripts. Even with a samples-build gate (PR #674), they'd be skipped.

2. 12 deprecated sync methods with no removal timeline — All marked @deprecated for "Wave 2" but no tracking issue, no target date, no lint rule preventing new sync usage.

3. Test gaps:

  • No unicode path tests (CJK/emoji — SQLite LIKE escaping risk)
  • No provider switching mid-session tests
  • No SQLite close/re-init lifecycle tests
  • No very long path tests (>255 char, OS limits)

4. Module-level singletons in CLIconst storage = new FSStorageProvider() at module scope in nap.ts and start.ts. Pre-existing pattern but makes testing harder.


🟢 STRENGTHS

  • ~205 test cases across contract suite + provider tests + state tests
  • Dependencies correctly placed — sql.js in optionalDependencies (won't bloat installs)
  • Export pattern follows existing conventions (40+ existing subpath exports)
  • No TODO/FIXME comments — clean source with documented limitations
  • DI pattern is correct — FSStorageProvider as default, fully swappable at public API boundaries

Recommended Actions

  1. ✅ Verify ./storage export resolves (node -e "import('@bradygaster/squad-sdk/storage')" after build)
  2. ✅ Add build/test scripts to new samples so CI can validate them
  3. ✅ Create tracking issue for Wave 2 sync method removal
  4. 🟡 Add unicode path tests to contract suite (quick win)

— FIDO, Quality Owner

diberry pushed a commit to diberry/squad that referenced this pull request Mar 29, 2026
Adds CJK, emoji, and accented character path tests to the storage
contract test suite. Tests write, read, exists, list, delete, append,
rename, and copy with unicode paths across all 3 providers (FS,
InMemory, SQLite). Rebased onto upstream/dev to pick up CI gates.

Addresses FIDO review findings on PR bradygaster#640.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@diberry diberry force-pushed the diberry/storage-abstraction-squashed branch from 3da6492 to 18b466a Compare March 29, 2026 14:10
@diberry
Copy link
Copy Markdown
Collaborator Author

diberry commented Mar 29, 2026

✅ FIDO's Findings — Resolved

Finding Status Resolution
🔴 Fork missing changelog-gate + exports-map-check ✅ Fixed Rebased onto upstream/dev — both CI gates now present
🔴 ./storage export never validated ✅ Verified import('@bradygaster/squad-sdk/storage') resolves correctly post-build
🟡 No unicode path tests ✅ Fixed Added 24 tests — CJK, emoji, accented chars across write/read/exists/list/delete/append/rename/copy
🟡 No Wave 2 sync removal tracking ✅ Created diberry#113 tracks sync method removal
🟡 New samples CI-invisible Deferred Tracked in diberry#112 (samples CI enhancements)

Test results: 461 tests pass across all 3 providers (FS, InMemory, SQLite).

— EECOM, Core Dev (reviewed by FIDO, Quality Owner)

@tamirdresher
Copy link
Copy Markdown
Collaborator

Great analysis @diberry — agree completely. StateBackend (#680) sits above StorageProvider (#640) in the stack. Once #640 merges, we'll refactor FilesystemBackend to delegate to StorageProvider instead of raw node:fs. The OrphanBranchBackend stays as-is since it uses git plumbing.

Also — love that you ran FIDO against your own PR and caught the missing CI gates. The guardrails are already paying off! 🎉

Documented this relationship in the RFC issue: #678

diberry pushed a commit to diberry/squad that referenced this pull request Mar 29, 2026
…c lockfile

The SDK and CLI package.json files had committed prerelease versions
(0.9.1-build.1, 0.9.1-build.4) which broke npm workspace resolution.
The CLI dep '>=0.9.0' doesn't match semver prereleases, causing npm to
install a stale published SDK from the registry instead of the local
workspace — that stale copy lacked the storage/state barrel exports,
breaking the build.

Fix: Reset both packages to 0.9.1 (non-prerelease) so workspace
linking works correctly, and regenerate package-lock.json.

Closes bradygaster#640

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
diberry pushed a commit to diberry/squad that referenced this pull request Mar 29, 2026
… gates

Adds 3 new CI validation gates motivated by the PR bradygaster#640 prerelease
version incident where npm silently resolved a stale registry SDK.

- workspace-integrity: verifies lockfile has no stale registry entries
  for workspace packages (zero-install, reads lockfile only)
- prerelease-version-guard: blocks prerelease version suffixes from
  merging to dev/main (zero-install, reads package.json only)
- export-smoke-test: verifies all subpath exports resolve to built
  artifacts after SDK build (lightweight install+build)

All gates follow existing patterns: feature flags (vars.SQUAD_*),
skip labels, three-dot diff for change detection, ::error:: annotations.

Closes #114

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
diberry pushed a commit to diberry/squad that referenced this pull request Mar 29, 2026
Codifies semver versioning rules for SDK and CLI packages:
- MAJOR.MINOR.PATCH only on dev/main (no prerelease suffixes)
- bump-build.mjs -build.N versions are local-only, never committed
- SDK + CLI versions must stay in sync (workspace resolution footgun)
- Surgeon owns version bumps; other agents hands-off
- prerelease-version-guard CI gate enforces the policy

Motivated by PR bradygaster#640 (prerelease broke workspace resolution) and
PR #116 (prerelease leak on release branch).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
diberry pushed a commit to diberry/squad that referenced this pull request Mar 29, 2026
Adds CJK, emoji, and accented character path tests to the storage
contract test suite. Tests write, read, exists, list, delete, append,
rename, and copy with unicode paths across all 3 providers (FS,
InMemory, SQLite). Rebased onto upstream/dev to pick up CI gates.

Addresses FIDO review findings on PR bradygaster#640.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@diberry diberry force-pushed the diberry/storage-abstraction-squashed branch 2 times, most recently from bcb6c89 to f36962b Compare March 29, 2026 20:13
@diberry
Copy link
Copy Markdown
Collaborator Author

diberry commented Mar 29, 2026

PR #640 Status — Ready for Human Review

Single squashed commit on diberry/storage-abstraction-squashed, rebased onto latest upstream/dev.

CI Results (9/9 complete)

Job Status Notes
test 5644+ tests pass
docs-quality
changelog-gate
exports-map-check
publish-policy
workspace-integrity
prerelease-version-guard
export-smoke-test Pre-existing on dev -- @github/copilot-sdk ESM bug (vscode-jsonrpc/node). Identical failure on upstream/dev.
samples-build Pre-existing on dev -- same vscode-jsonrpc bug in streaming-chat sample. 6 passed, 1 failed, 4 skipped.

Team Review

Reviewer Verdict Key Findings
Flight (Lead) ✅ Approve Clean interface design, proper DI, zero breaking changes
FIDO (Quality) 🟡 Approve w/ notes All findings addressed in squashed commit
PAO (DevRel) 🟡 Approve w/ notes All findings addressed in squashed commit
Copilot ⌛ Requested GitHub code review requested

Review Findings — All Fixed

  • ✅ Added StorageError UNKNOWN-code test (FIDO)
  • ✅ Fixed contract header 23 to 24 methods (FIDO)
  • ✅ Added error-inconsistency JSDoc to StorageProvider interface (FIDO)
  • ✅ Added sync method deprecation footnote to feature page (PAO)
  • ✅ Added Azurite dev-dependency install note to Azure sample (PAO)

What Was Done

  1. Rebased onto upstream/dev (resolved package-lock.json conflict)
  2. Regenerated cross-platform lockfile (fixed @rollup/rollup-linux-x64-gnu missing on Linux CI)
  3. Applied all team review fixes
  4. Squashed 11 commits into 1 clean commit
  5. Versions confirmed at 0.9.1 (no prerelease suffix)

Known Issues (not caused by this PR)

@github/copilot-sdk has an ESM import bug: vscode-jsonrpc/node missing .js extension. This affects the ./client export smoke test and streaming-chat sample on Linux CI. Same failure exists on upstream/dev.

@diberry
Copy link
Copy Markdown
Collaborator Author

diberry commented Mar 29, 2026

Pre-existing CI Failures — Need Owner Decision

@bradygaster @tamirdresher — two CI jobs on this PR are failing, but they're not caused by this PR. The same failures exist on dev at 428a20da. No PRs or issues currently track them.

Root Cause

@github/copilot-sdk imports vscode-jsonrpc/node without the .js extension. This breaks ESM module resolution on Linux (CI runs on Ubuntu). It works on Windows/macOS where Node is more lenient.

Affected CI Jobs

Job What fails Impact
export-smoke-test ./client subpath export — loading it triggers the @github/copilot-sdk ESM bug All other 40+ exports pass
samples-build streaming-chat sample test — same SDK import chain 6 samples pass, 1 fails, 4 skipped

Options

  1. Wait for upstream fix@github/copilot-sdk needs to ship a fix (add .js to their ESM imports). Unknown timeline.
  2. Workaround now — Exclude ./client from export-smoke-test and skip streaming-chat sample tests until the SDK is fixed. Quick PR, gets CI green.
  3. Accept as known failures — Merge this PR as-is (7/9 green), track the 2 failures as a separate issue.

What would you like to do?

diberry added a commit that referenced this pull request Mar 30, 2026
…ot-sdk ESM bug

@github/copilot-sdk imports vscode-jsonrpc/node without .js extension,
breaking ESM resolution on Linux CI. This is a pre-existing upstream bug
(same failure on dev at 428a20d).

Workaround: skip affected checks until SDK ships a fix.

Refs: #640 (analysis)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
diberry added a commit that referenced this pull request Mar 30, 2026
…ot-sdk ESM bug

@github/copilot-sdk imports vscode-jsonrpc/node without .js extension,
breaking ESM resolution on Linux CI. This is a pre-existing upstream bug
(same failure on dev at 428a20d).

Workaround: skip affected checks until SDK ships a fix.

Refs: #640 (analysis)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Introduces a pluggable storage abstraction for the Squad SDK:
- StorageProvider interface with 24 async methods + 12 deprecated sync methods
- FSStorageProvider (default), InMemoryStorageProvider, SQLiteStorageProvider
- StorageError with typed error codes and operation context
- Dependency injection throughout all public API entry points
- Contract test suite covering all 3 providers
- CHANGELOG entry, README section, docs feature page
- Sample projects: SQLite and Azure Blob Storage

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@diberry
Copy link
Copy Markdown
Collaborator Author

diberry commented Mar 30, 2026

Rebased onto latest dev to pick up the ESM patch fix from #699. The 2 failing CI checks (export-smoke-test, samples-build) were caused by the vscode-jsonrpc/node ESM bug — now resolved in dev. CI should go green on this run.

@diberry diberry force-pushed the diberry/storage-abstraction-squashed branch from f36962b to 26047dc Compare March 30, 2026 05:45
@bradygaster bradygaster merged commit a386bd8 into bradygaster:dev Mar 30, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants