Skip to content

refactor(storage): drop the barrel and publish narrow entrypoints - #3301

Merged
M4n5ter merged 4 commits into
apache:mainfrom
childrentime:fix/storage-drop-barrel
Aug 24, 2026
Merged

refactor(storage): drop the barrel and publish narrow entrypoints#3301
M4n5ter merged 4 commits into
apache:mainfrom
childrentime:fix/storage-drop-barrel

Conversation

@childrentime

@childrentimechildrentime commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

maka --help printed Node's SQLite ExperimentalWarning to stderr, on a command that never opens a database. Every other CLI entry did the same. This removes the structure that caused it: @maka/storage no longer publishes a barrel, and every consumer imports the narrow entrypoint that owns what it needs.

Fixes#1257

Why the warning was there

Node evaluates a builtin the moment it enters a module graph. A static value import is therefore not a declaration of intent — it is the load:

import{DatabaseSync}from'node:sqlite';// evaluated here

Exactly three modules do this: operational-target-schema.ts, operational-state-backup.ts and session-bundle-policy.ts.

operational-target-schema.ts is the amplifier. operational-state-store.ts imports it — and operational-state-store.ts is imported by roughly forty modules, which is how three import statements reached 45 of the package's modules. The last link is the CLI: cli-core.ts imports @maka/storage to reach resolveMakaDataRoots, a pure path helper, and the barrel's export * surface hands it the whole storage layer, SQLite included, before --help prints a single line.

The alternative this PR chooses against

Review correctly pointed out that removing the barrel is not the only fix, and the smaller one deserves to be stated so the choice here is deliberate. The three static imports above all construct only inside function bodies, and this package already owns a lazy-load seam twice over (loadDatabaseSync() in operational-state-store.ts, loadSqliteModule() in sqlite-session-metadata-store.ts). Converting the three imports to import type plus that seam is a three-file fix that keeps the barrel and silences the warning.

This PR prefers the structural fix because #1257 was already fixed once the small way, and it came back: its guard test asserted an empty stderr, #2710 removed that assertion in a bulk test cleanup, #1994 and #2445 then added static imports, and the warning shipped again. Lazy loading keeps the boundary as a convention each future edit must remember; removing the barrel makes it structural — widening the SQLite surface now requires editing a published entrypoint list in a test and saying why. The two designs buy different things (three files of churn vs. cost made legible at every import site), and a maintainer preferring the minimal fix is a legitimate outcome of this review; I'd then close this and submit the three-file version.

Change

  • Delete packages/storage/src/index.ts and drop ., main and types from the manifest.
  • Publish the modules consumers actually reach as narrow subpaths — the map has 49 entrypoints, and every one of them has a consumer outside the package (six consumer-less entrypoints predate this change and are allowlisted exactly; a new one fails the guard outright).
  • Where the barrel exported hand-picked names rather than a whole module, the newly published subpath carries a facade with exactly those picks, following the existing interaction-store-public idiom. That is now one entrypoint, operational-state-store, where the schema-migration internals stay private. Every other hand-picked module was already surface-neutral, verified by diffing the barrel's picks against each module's runtime exports.
  • No pre-existing entrypoint changes target. The export map only drops . and adds 15 subpaths, which git diff upstream/main...HEAD -- packages/storage/package.json shows directly.
  • Rewrite every consumer onto those subpaths (95 files against current main; the touched files in packages/runtime are all tests, that package's production code is untouched).
  • Two tests moved off the barrel's shape rather than its contents. managed-workspace-baseline now loads every published entrypoint and asserts the union of reachable symbols excludes the internals — a claim that survives a future re-export, which an assertion on the exports map's targets would not. provider-request-capture-artifact reaches its subject directly.

Regression guard

public-entrypoints.test.ts loads all 49 published entrypoints and asserts:

  • the package publishes no . entrypoint and no main/types field;
  • every published target is a file the build actually emits;
  • no source file in the repository imports the bare @maka/storage specifier, side-effect form included — this is the test that would have caught the writer-composition consumer refactor(storage): centralize root writer lifecycle #3295 landed on main while this branch was in review, which merged cleanly and then failed to build;
  • every imported subpath is published, and the set of published-but-unconsumed entrypoints is exactly the six that predate this change;
  • the entrypoints whose module graph reaches node:sqlite are exactly the 29 listed in the test, leaving 20 that are free of it. Reaching node:sqlite is observed through a module.registerHooks resolve hook rather than by matching the warning's text, which Node owns and has already reworded once; probe children are capped at four concurrent.

That list is the package's SQLite boundary written down. Widening it later means editing the list and saying why. (./storage-writer-composition is on it because it statically imports execution-stores and thirteen other SQLite-backed modules.)

Scripts import workspace modules by dist/ file path, outside both the export map and the typechecker — the release smoke script through installed node_modules, the computer-use scripts through relative packages/*/dist paths. release-cli-file-policy.test.mjs walks every script for both forms and asserts each target is a file the build emits.

Rebase onto current main

Rebased from 84fbe05 onto 23c9214 and force-pushed. Most conflicts were main adding the ASF header to files this branch re-imports, and took main's file with the narrow import. Three needed a decision:

  • main grew four new bare @maka/storage importers while this sat in review. All four are on subpaths now — none of them conflicted, public-entrypoints.test.ts is what found them, which is the guard doing the job the refactor(storage): centralize root writer lifecycle #3295 case was added for.
  • ./artifact-store is no longer published. Its only consumer outside the package was the desktop test main deleted, and a new consumer-less entrypoint is what this PR's own guard rejects. The module and its lease-gated write authority stay package-private; its facade is gone, so two facades remain rather than three. sanitizeArtifactName is still reachable through ./artifact-stores, as it already was.
  • ./model-call-ledger joined the consumer-less allowlist untouched by this branch: repairPendingModelCallProjections lost its last caller when canonical-usage-reader was rewritten on main. Retiring a subpath that already shipped is its own compatibility call, so it is listed with that reason recorded in the test.

main's own new entrypoints — ./process-lifetime-file-update-lock and ./stable-storage — both have consumers and carry through unchanged.

Follow-up after review

a2c64e3 answers @M4n5ter's P2. ./credential-store was published before this branch and mapped straight to credential-store.js, so withCredentialFileLock was reachable through it; routing it through a facade made that symbol undefined. That is a contract change to a pre-existing entrypoint and unrelated to removing the barrel — the facade was applying the barrel's picks to an entrypoint the barrel never owned, a rule that belongs to subpaths published here for the first time.

Preserved rather than retired: the subpath points back at credential-store.js, the facade is deleted, and withCredentialFileLock leaves the reachable-symbol denylist because it is public again. Whether the file lock should become package-private stays open as its own change.

Verification

Node v24.11.1, npm 11.19.0 (the pinned packageManager), macOS arm64, at this head. The surfaces are the ones scripts/ci-test-plan.mjs --base 23c9214 --head HEAD selects for this PR: code, astryx_surface, release_contract, cli_package, runtime_host, runtime_sandbox, e2e, storybook, plus workspaces storage, runtime, eval, computer-use, cli, desktop.

CheckResult
ci-test-plan · verify-windows-harness · protocol-epoch-check · ax-tree-audit tests92 pass
windows:inventory · check:asf-npm · check:asf-headerspass (2801 covered / 137 excluded files)
protocol-epoch-check --base HEAD^1pass, no protocol change (epoch 44)
lint · format:checkpass, 2667 / 1611 files
astryx:surface-inventory · astryx:theme -- --checkpass
build · typecheck · knip (desktop, ui)pass
check:release110 pass
workspace test:dist, via CI's own commandsruntime 3003 (2990 pass, 13 skipped) · desktop 1364 · runtime-host 1120 · storage 925 (910 pass, 14 skipped, 1 below) · cli 423 · computer-use 118 · eval 75; core, mcp and ui pass in a full sweep
release:cli:packpass — 13.4 MiB, 6346 files. The tarball ships node_modules/@maka/storage/dist/workspace-root.js and no dist/index.js, which is exactly what the smoke script's changed import needs
release:cli:smokepass — installed the tarball offline and validated bins, Eval assets, native PTY and file locks, the TUI setup path, the managed Runtime Host lifecycle and a controlled model turn
maka --version / --help / run --help stderr0 bytes, no ExperimentalWarning

Not run: Desktop e2e, Storybook smoke and the Linux sandbox smoke. CI runs all three on Linux under xvfb/bubblewrap; this PR touches no renderer, Electron or sandbox code, and the desktop files it does touch are import rewrites covered by the 1364 passing desktop tests, typecheck and knip.

One failure remains, and it is not from this change: @maka/storagemanaged-dependency-environment-crashrejects a second authority for the same storage root in another process. That test treats any child stderr as an error and Node prints the SQLite warning there. Verified to fail identically on 23c9214 in a clean worktree, and CI is green on this head with that suite included, so it is this machine only. The branch alters no dependency manifest either — git diff upstream/main...HEAD -- package.json package-lock.json is empty.

Remaining warning sites

The paths that still emit the warning all genuinely use SQLite, so the warning is expected there:

  • maka eval and maka activate — including their --help, since the command module loads before argument handling;
  • the 29 SQLite-backed entrypoints of @maka/storage;
  • the processes that actually open databases (the Runtime Host child, the Electron main process).

Both existing warning suppressors (loadDatabaseSync, loadSqliteModule) are on main today and survive this PR unchanged.

Compatibility — maintainer sign-off wanted

Two deliberate contract changes, called out for an explicit decision rather than buried in the diff:

  1. Removing . (and main/types) is a breaking change to the package's public surface. @maka/storage is not published independently and every consumer lives in this repository, so the blast radius today is zero — but if the package is ever published on its own, this belongs in the release notes.
  2. Fourteen modules drop from publicly reachable to package-private: artifact-attachments, artifact-store, operational-state-backup, plan-store, provider-request-capture-artifact, session-bundle-canonical-tree, session-bundle-contract, session-bundle-file-service, session-bundle-manifest, session-bundle-ustar, sqlite-artifact-metadata, sqlite-usage-store, task-ledger-store, telemetry-repo. Nothing outside the package imports them; re-publishing any of them later is a one-line exports addition. (artifact-store is the one the rebase moved into this list — sanitizeArtifactName stays reachable through ./artifact-stores, as it already was.)
  3. Four symbols the barrel withheld are still not publicly reachable: migrateOperationalStateDatabaseInternal, inspectOperationalStateSchema and OperationalStateMigrationBlockedError, because ./operational-state-store is new here and its facade publishes only the barrel's picks; and createSqliteArtifactStoreWriteAuthority, because artifact-store is not published at all. The reachable-symbol union test names each one. withCredentialFileLock is deliberately not on this list — see the follow-up below.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code. Claude Fable 5 traced the regression to the barrel, performed the mechanical rewrite, wrote the regression tests, ran the measurements and applied the review follow-ups. Claude Opus 5 rebased onto 23c9214, made the three decisions in the rebase section above, re-ran the verification and updated this description. Each commit carries a Generated-by: Claude Code trailer — please keep it in the squash commit.

A human contributor of record has reviewed the diff, verified the evidence above and decided to submit it.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making the SQLite cost visible at the entrypoint is a real improvement, and public-entrypoints.test.ts stating the boundary out loud is the right instinct — a list a reader can check beats a property nobody can see. I also verified the part that is easiest to get wrong and hardest to check: I resolved every one of the 52 published targets against every @maka/storage import in the tree, symbol by symbol, and found no missing subpath and no missing export. That work is sound.

Three things below will fail CI as filed, so I cannot approve this head. Two of them are invisible from this diff, which is what makes them worth flagging rather than leaving to a red run.

The scope question, which is yours to decide rather than mine. The PR argues that dropping the barrel is what fixes #1257. I do not think that premise holds. There are exactly three static value imports of node:sqlite in the tree — operational-target-schema.ts:1, operational-state-backup.ts:16, session-bundle-policy.ts:4 — and all three only construct inside function bodies. This package already owns the seam for that, twice: loadDatabaseSync() in operational-state-store.ts and loadSqliteModule() in sqlite-session-metadata-store.ts, both lazy-require-plus-suppress-warning. A subagent reports restoring the barrel wholesale, converting those three to import type plus the existing loader, rebuilding, and measuring the barrel no longer pulling in node:sqlite. If that holds, #1257 is a three-file fix and this is an 87-file one.

That does not make this PR wrong. The two designs buy different things: dropping the barrel makes cost legible at the import site, lazy-loading keeps the change surface at three files. AGENTS.md's first principle points at the existing seam, and the PR body's claim that "no lazy-load indirection and no warning suppression are involved" is not accurate about this repository either way — both suppressors are on main today and survive this PR. What I am asking for is that the justification match the actual alternative, so whoever approves this is choosing legibility deliberately rather than believing it was forced.

Two contract decisions a maintainer should sign off on rather than a reviewer: removing . is a breaking change to the package's public surface, and eight modules drop from publicly reachable to package-private, which the title does not mention.

AI disclosure: this review was produced with Claude Code (Opus 5) with a subagent covering security, correctness, integration and simplification. I independently re-derived every finding published here: I confirmed the deep dist/index.js import in the smoke script and the bare @maka/storage specifier on main by reading both files, and I reproduced the formatting failure myself by running this repository's pinned Biome over the two files at this head and diffing its output. The subagent additionally reports building the branch and executing the merge; I did not re-run those. Per AGENTS.md this is not independent human review.

Comment threadpackages/storage/package.json
Comment threadpackages/storage/package.json Outdated
Comment threadpackages/storage/src/__tests__/public-entrypoints.test.ts Outdated
Comment threadpackages/storage/package.json
Comment threadpackages/storage/src/__tests__/managed-workspace-baseline.test.ts Outdated
Comment threadpackages/storage/src/__tests__/public-entrypoints.test.ts Outdated
@childrentime

Copy link
Copy Markdown
ContributorAuthor

@Astro-Han Thanks for the review — every finding was real. All six are addressed at 2d5c2cf, and I've resolved the threads accordingly:

  • Rebased onto main; the writer-composition consumer refactor(storage): centralize root writer lifecycle #3295 added now imports through @maka/storage/storage-writer-composition, and public-entrypoints.test.ts asserts no source file in the repository imports the bare specifier — the test you suggested, and the one that would have caught this without a rebase.
  • The smoke script's deep import points at dist/workspace-root.js, and release-cli-file-policy.test.mjs now walks every importInstalled(..., 'node_modules/@maka/...') literal and asserts the build emits the target. (Asserting against src twins turned out wrong in one case — @maka/runtime's filesystem worker is emitted by a bundling script, not tsc — so the test checks dist, which check:stale keeps honest in check:release.)
  • main/types are dropped, with a test asserting they stay absent and that every exports target is a file the build emits.
  • The internal-symbol assertion now loads all 53 published entrypoints and checks the union of reachable symbols against the internals — your re-export scenario fails it.
  • The SQLite boundary is observed through a module.registerHooks resolve hook; the probe errors loudly if it produces no verdict rather than falling through. ./storage-writer-composition is entry 30 on the list — you were right that it belongs there, it statically imports execution-stores and thirteen other SQLite-backed modules.
  • npm run format fixed both files; format:check is in the validation table now.

On scope: you're right that a three-file lazy-load fix exists, and the PR body now states it explicitly, along with why I still prefer the structural version — #1257 was fixed the small way once and regressed when its guard was deleted in #2710. The breaking . removal and the eight modules going package-private are called out in the description under "maintainer sign-off wanted". If the maintainers prefer the minimal fix, I'll close this and submit the three-file version.

AI disclosure: these follow-ups were implemented with Claude Code (Claude Fable 5); I reviewed the diff and the validation results before pushing.

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 2d5c2cf2d. I dispatched two scoped sub-reviews — integration and simplification/test-quality; I did not run security or resource-bounds dimensions, because an import rewrite has no meaningful surface for either. Everything below I re-derived at this head myself.

All five findings from the previous round are fixed.execution-composition.ts:60 now imports @maka/storage/storage-writer-composition; the smoke script points at dist/workspace-root.js; main/types are gone from the manifest; managed-workspace-baseline.test.ts asserts on the reachable-symbol union rather than a weaker property; and the SQLite probe uses module.registerHooks instead of text matching. I also re-ran the repo-pinned Biome over every changed TS/JS/MJS file outside the apps/desktop/** and packages/ui/** exclusions — byte-identical output, so format:check passes.

I checked the two things that would make a rewrite of this size unsafe, and both are clean. There are zero remaining bare @maka/storage import specifiers anywhere in packages/, apps/ or scripts/ — the four textual hits in scripts/ are package-name list entries, not specifiers. And every subpath any file imports resolves against the new exports map; the set of used subpaths minus the 53 published keys is empty. The one-intent rule holds too: every hunk across the 89 files is an import rewrite, the manifest, the deleted barrel, or a guard for the barrel's absence.

The P1 below is the same mechanism as the smoke-script finding you already accepted and fixed, one file over — a relative reach-in to a dist emit that this PR removes. It is the last one; I grepped the tree to be sure.

Two smaller things that do not warrant their own threads:

apps/desktop/tsconfig.storybook.json:13 still maps @maka/storage to ../../packages/storage/src/index.ts, a file this PR deletes. That config is live in CI — apps/desktop's typecheck runs tsc -p tsconfig.storybook.json --noEmit — but it does not fail today, because nothing in its include set imports @maka/storage. So it is dead config rather than a break. It is worth deleting in this PR anyway: the mapping is non-wildcard, so it would silently shadow the exports map for any future bare import from a story, which is precisely the failure mode this PR exists to remove. The file is not in the diff, hence no inline thread.

The new bare-specifier guard at public-entrypoints.test.ts:120 is, for .ts files, redundant — moduleResolution: "Bundler" already honours exports, so a bare specifier fails npm run typecheck before the guard runs. Its real value is over .mjs/.js, and there it misses the side-effect form import '@maka/storage'; as well as the relative reach-ins the P1 describes. The regression test I suggest on that thread fixes both.

Carrying a P1 → COMMENT. The rest is a clean, well-scoped change and I expect to approve it once the real-model.mjs import is repointed.

AI disclosure: reviewed with Claude Code, including two scoped sub-reviews used as leads. Every finding published here I verified at 2d5c2cf2d myself — I read the deleted barrel's named export lists against the modules they came from, counted external importers per published subpath on the branch, and grepped the tree for surviving packages/storage/dist/ reach-ins. Sub-review findings I could not confirm are not included.

Comment threadscripts/release-cli-file-policy.test.mjs Outdated
Comment threadpackages/storage/package.json Outdated
Comment threadpackages/storage/package.json Outdated
Comment threadpackages/storage/src/__tests__/public-entrypoints.test.ts Outdated
@childrentime

Copy link
Copy Markdown
ContributorAuthor

@Astro-Han All four findings and both of the no-thread notes are addressed at 049e93f:

  • real-model.mjs:13 points at dist/agent-run-store.js, and the file-policy scan now walks every script in scripts/ for both import forms — installed node_modules/@maka/*/dist and relative packages/*/dist — asserting each target is still emitted. I verified the guard by reverting the fix locally: it fails on exactly that line.
  • The five consumer-less session-bundle-* entrypoints are gone; session-bundle-policy stays. public-entrypoints.test.ts now asserts the exact set of published-but-unconsumed entrypoints, allowlisting only the five that predate this PR (your list matched my recount), and separately that every imported subpath is published. The bare-specifier guard also covers the side-effect form now.
  • operational-state-store, artifact-store — and credential-store — publish facades re-exporting exactly the names the barrel picked, following the existing interaction-store-public idiom, and the reachable-symbol union test names all five withheld symbols. Credential-store is one you didn't flag: I re-derived the barrel-picks-vs-module-exports diff for every published hand-picked module, and withCredentialFileLock was the only other widened symbol — its own doc comment says it is deliberately not on the public surface. Everything else was surface-neutral.
  • SQLite probes run at most four concurrent.
  • The dead storybook path mapping is deleted (its tsc -p tsconfig.storybook.json --noEmit still passes), and knip over apps/desktop and packages/ui is clean.

Counts in the PR body are updated: 48 entrypoints, 30 SQLite-backed, 18 free, 13 modules package-private.

AI disclosure: implemented and self-reviewed with Claude Code (Claude Fable 5); I reviewed the diff and validation before pushing.

@Astro-HanAstro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at 049e93fdf. I reviewed only the delta from 2d5c2cf2d — one commit, nine files — and every finding from the last round is fixed, several of them better than what I asked for.

The P1 is closed at its cause rather than at the symptom. real-model.mjs:13 now points at dist/agent-run-store.js, and release-cli-file-policy.test.mjs no longer reads one file for one literal shape: it walks every script for both the node_modules/@maka/*/dist/*.js and the relative packages/*/dist/*.js forms and asserts each target exists. That closes the whole class, which is what makes it a fix rather than a patch.

The surface-widening P2 got the right treatment. Rather than narrowing by convention, artifact-store-public.ts, operational-state-store-public.ts and credential-store-public.ts re-export exactly the sets the deleted barrel published, and package.json repoints the three subpaths at them — I diffed each against the barrel's old export lists and they match name for name. managed-workspace-baseline.test.ts then asserts the withheld internals stay unreachable, so the narrowing is enforced rather than documented. You also found withCredentialFileLock, which I had missed; that is a fourth internal on the same footing as the three I named.

The consumer-less entrypoints are gone, and the guard that replaces them is stronger than the assertion I suggested: PREEXISTING_UNCONSUMED_ENTRYPOINTS is exact in both directions, so gaining a consumer forces removing the entry and publishing a new consumer-less subpath fails outright, with the comment stating the list may only shrink. That converts a one-time cleanup into an invariant. The dead tsconfig.storybook.json mapping is deleted, and mapWithConcurrency caps the probe children at 4 — the number AGENTS.md actually names.

I re-verified rather than taking the delta on trust: every external @maka/storage/* import in this branch falls inside the narrowed surfaces, ./session-bundle-policy keeps its one real consumer, and the repo-pinned Biome produces byte-identical output for all seven changed TS/JS/MJS files outside the apps/desktop/** and packages/ui/** exclusions.

No findings at this head.

AI disclosure: reviewed with Claude Code. I diffed each new *-public.ts against the deleted barrel's export lists myself, re-scanned the branch for external imports of the repointed subpaths, and ran the read-only Biome check against the head content. The approval is mine and rests on those checks.

@Astro-Han

Copy link
Copy Markdown
Contributor

Hi — this PR conflicts with current main and cannot be merged as-is.

I tested a rebase onto current main locally (in a throwaway worktree — your branch was not touched). It stops on these files:

  • apps/desktop/src/main/client-settings-effects.ts
  • apps/desktop/src/main/mcp-ipc-main.ts
  • apps/desktop/src/main/new-session-project.ts
  • apps/desktop/src/main/runtime-host-boot.ts
  • …(more)

These are real source conflicts, so they need your judgement rather than a mechanical rebase — please rebase onto current main and resolve them yourself, then push. Once the branch is conflict-free and CI is green on the new head, I will pick it up for review.

git fetch upstream && git rebase upstream/main
# resolve, then
git push --force-with-lease

Thanks for the contribution — happy to help if any conflict is unclear.


AI-assisted maintenance note, not a review. It does not count as the required human review under CONTRIBUTING.md §Review.

@childrentime
childrentimeforce-pushed the fix/storage-drop-barrel branch from 049e93f to d35c1c3CompareAugust 24, 2026 04:27

@zhiiwzhiiw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incremental re-review at exact head d35c1c3615707bdfeb9786e469ab637b1af7892e (previous approval was on 049e93fd; this pass covers only what changed between them, plus re-verifying the load-bearing gate).

The boundary is enforced, not transcribed.public-entrypoints.test.ts does not pin a copied count: only the declared entrypoints load node:sqlite loads every published entrypoint in a child process with a module.registerHooks resolve hook and asserts the measured set equals the declared list exactly, both directions. A pure-type entrypoint that accidentally drags in node:sqlite tomorrow fails this test. published entrypoints and their consumers match exactly separately fails on any new consumer-less entrypoint. I ran the suite at this head: 5/5 green.

Import hygiene: scanned every published entrypoint's source for re-exports — all within-package, or explicit Core type flows (deep-research-store@maka/core/deep-research-run, project-catalog@maka/core/project). No consumer resolves a type through a package that doesn't own it. Residual honesty: a semantically wrong-but-typecheck-compatible import can't be ruled out mechanically; I found none in the changed files.

Number note: the first commit's message says "exactly 28 of the 54 published entrypoints load node:sqlite". At this head the map publishes 49 entrypoints and the declared SQLite set holds 29 — the message numbers describe the first commit's state, not the head's. The test is the authority and it is enforced; the prose is stale. Cosmetic, not blocking.

Gate:package / audit / test all completed/success on the exact head; head re-polled at review time, unchanged, MERGEABLE.

No new findings in the incremental surface.

简体中文

增量复审:边界测试是真门禁(子进程实测每个 entrypoint 是否加载 node:sqlite,与声明列表双向精确相等),不是把现状抄成期望值;我本地在 exact head 跑了 5/5 绿。重导出扫描无跨包类型偷渡。首条提交信息里的 28/54 数字是旧状态的快照,与 head(49/29)不符——纯文案陈旧,不阻断。增量面无新 finding。

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed exact head d35c1c3615707bdfeb9786e469ab637b1af7892e. The root-barrel removal is structurally sound: runtime reachability contracts from 272 exported names to 216, the automatic root-to-SQLite evaluation path disappears, the dependency-cycle count does not increase, and a clean synthetic merge with current main passes the Storage, Desktop, CLI, entrypoint, and release-policy checks I ran.

One existing subpath is silently contracted, so my result is COMMENT with 1×P2.

简体中文

我审查了精确提交 d35c1c3615707bdfeb9786e469ab637b1af7892e。删除根 barrel 的整体结构是成立的:运行时可达导出从 272 个收缩到 216 个,根入口自动加载 SQLite 的路径消失,依赖环数量没有增加;与当前 main 的干净合并结果也通过了我运行的 Storage、Desktop、CLI、入口点及发布策略检查。

但一个既有子路径被静默收缩,因此本次结论为 COMMENT,1×P2

Comment threadpackages/storage/package.json Outdated

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed exact head a2c64e319d739d1c37f7d4a70bf4d073c794f15b. The previous credential-store compatibility finding is closed: the pre-existing ./credential-store target is restored, withCredentialFileLock is again reachable as a function, the narrowing facade is deleted, and the baseline test no longer encodes the incompatible contraction. I reviewed the complete one-commit delta and found no new issue.

The validated merge with main at f7d4957fe866c303588355bfa7c069f26325a691 passed the Storage entrypoint and boundary checks (27/27), direct subpath import, and the full Storage suite apart from one assertion coupled to Node's experimental-warning stderr; that assertion passes in isolation with warnings suppressed. Current main has since advanced only in four unrelated UI/CLI files, with no overlap with this PR's Storage changes, and GitHub reports the PR mergeable. Exact-head hosted package, audit, and test checks are all terminal green.

No remaining P0–P3 finding.

简体中文

已复审精确提交 a2c64e319d739d1c37f7d4a70bf4d073c794f15b。此前 credential-store 兼容性问题已经关闭:既有 ./credential-store 入口恢复到原目标,withCredentialFileLock 再次以函数形式可达,收窄 facade 已删除,基线测试也不再把不兼容的收缩编码为期望行为。我完整审查了这一个新增提交,没有发现新问题。

main 的已验证合并结果通过了 Storage 入口和边界检查(27/27)、直接子路径导入及完整 Storage 测试;其中只有一条依赖 Node 实验性警告 stderr 的断言失败,该断言在屏蔽警告后单独运行通过。此后当前 main 只改动了 4 个无关的 UI/CLI 文件,与本 PR 的 Storage 变更没有重叠,GitHub 也报告可合并。精确 head 的托管 packageaudittest 均已终态成功。

没有剩余的 P0–P3 问题。

@M4n5ter
M4n5terforce-pushed the fix/storage-drop-barrel branch from a2c64e3 to a19c64cCompareAugust 24, 2026 10:39
childrentimeand others added 4 commits August 24, 2026 18:40
`maka --help` printed Node's SQLite ExperimentalWarning to stderr, on a
command that never opens a database. The cause was structural, not local:
`@maka/storage` published one `export *` barrel, and `cli-core.ts` imported
it to reach `resolveMakaDataRoots`. Three modules in that barrel's graph take
a static value import of `node:sqlite`, and Node evaluates a builtin the
moment it enters a module graph, so every consumer of the barrel loaded
SQLite whether or not it wanted a database.
`operational-target-schema.ts` was the amplifier: `operational-state-store.ts`
imports it, and roughly forty modules import that, which is how three import
statements reached 45 of the package's 110 modules and 24 of the barrel's 43
export entries.
Remove the barrel instead of working around it. `.` is gone from the exports
map, `src/index.ts` is deleted, and the 20 modules that consumers actually
reached through it are published as narrow subpaths. This is already the
prevailing convention here — `root-authority` has 141 call sites and
`execution-stores` 108, against 31 non-test sites on the bare specifier.
The three static `node:sqlite` imports stay exactly as they were. They are
honest: those modules do need SQLite. What changes is that needing SQLite is
now visible in the import path, so `@maka/storage/workspace-root` costs
nothing and `@maka/storage/session-store` costs what it should. No lazy-load
indirection and no warning suppression are involved.
`public-entrypoints.test.ts` pins the boundary: no `.` export, and exactly 28
of the 54 published entrypoints load `node:sqlite`. Widening that set now
requires editing the list and saying why.
Two tests moved off the barrel's shape rather than its contents:
`managed-workspace-baseline` asserted internals were absent from the barrel
object and now asserts their modules are absent from the exports map;
`provider-request-capture-artifact` reaches its subject directly.
Generated-by: Claude Code
… guards
- Point the release smoke script's deep import at dist/workspace-root.js,
which owns resolveMakaDataRoots now that dist/index.js is not emitted,
and guard every such by-path import with a release file-policy test.
- Import openStorageWriterComposition through its published subpath; the
bare specifier resolved to the removed barrel entrypoint after apache#3295.
public-entrypoints.test.ts now rejects bare @maka/storage imports
anywhere in the tree, so the next stale-merge of this kind fails a test
instead of a build.
- Add ./storage-writer-composition to SQLITE_BACKED_ENTRYPOINTS: it
statically imports execution-stores and thirteen other SQLite-backed
modules.
- Detect the SQLite boundary with a module.registerHooks resolve hook
instead of matching Node's ExperimentalWarning text, which Node 26 has
already reworded.
- Drop the dangling main/types manifest fields and assert that every
published entrypoint target is emitted by the build.
- Assert internals stay private by loading every published entrypoint and
checking the union of reachable symbols, not the export map's targets,
so a future re-export cannot leak them silently.
- Run Biome over the two files format:check rejected.
Generated-by: Claude Code
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Repoint the real-model computer-use script at dist/agent-run-store.js;
the release file-policy test now walks every script for both the
node_modules and the relative packages/*/dist import forms and asserts
each target is still emitted, which catches this whole class.
- Publish operational-state-store and credential-store through facades
that re-export exactly the names the deleted barrel picked. The
schema-migration internals and the credential file lock return to
package-private. artifact-store needs no facade: nothing outside the
package imports it on current main, so it is not published at all and
the lease-gated write authority stays private with the rest of the
module. The reachable-symbol union test names all five withheld symbols.
- Drop the five session-bundle entrypoints with no consumer outside the
package; public-entrypoints.test.ts now asserts the exact set of
consumer-less entrypoints, allowlisting only those that predate this
change, and that every imported subpath is published.
- Extend the bare-specifier guard to the side-effect import form and cap
the SQLite probe children at four concurrent.
- Delete the storybook path mapping to the removed src/index.ts.
Generated-by: Claude Code
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`./credential-store` was a published subpath before this branch and mapped
straight to `credential-store.js`, so `withCredentialFileLock` was reachable
through it. Routing it through a facade turned that symbol into `undefined` —
a contract change to a pre-existing entrypoint, and one that has nothing to
do with removing the barrel.
The facade was applying the barrel's picks to an entrypoint the barrel never
owned. That rule is right for the subpaths this branch publishes for the
first time, where the surface is still being chosen; it is not a reason to
narrow one that already shipped. Whether the file lock should be
package-private is a separate compatibility decision, and stays open.
The export map now only drops `.` and adds subpaths — no pre-existing
entrypoint changes target, which one command shows:
git diff upstream/main...HEAD -- packages/storage/package.json
`withCredentialFileLock` also leaves the reachable-symbol denylist in
`managed-workspace-baseline`, because it is publicly reachable again, exactly
as it was before this branch.
Generated-by: Claude Code
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@M4n5ter
M4n5terforce-pushed the fix/storage-drop-barrel branch from a19c64c to fbb2a55CompareAugust 24, 2026 10:41

@M4n5terM4n5ter left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified at exact head fbb2a55 after rebasing onto the updated main history. The conflict resolution preserves main's preferred-path project-catalog registration coverage while retaining this PR's narrow Storage subpath imports. Storage passed 945 tests (929 passed, 16 skipped), the focused Storage entrypoint/boundary suite passed 27/27, the Runtime Host conflict-focused suite passed 3/3, and the Storage and Runtime Host builds completed successfully. All three exact-head hosted checks are terminal and successful, the current main check is terminal and successful, the current merge tree is clean, and there are no unresolved review threads.

@M4n5ter
M4n5ter merged commit 1053c19 into apache:mainAug 24, 2026
3 checks passed
Sign up for freeto 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.

fix(cli): avoid node:sqlite ExperimentalWarning on non-SQLite storage imports

4 participants

@childrentime@Astro-Han@zhiiw@M4n5ter