This file is the scope contract for the Fict monorepo. It exists to make one decision structural instead of relying on day-to-day discipline: which surfaces are part of the product Fict promises to keep, and which are not.
Adding surface is cheap (especially with AI assistance). Keeping surface is not: every published package is a version, a changelog, a CI lane, and a bug inbox. The default in this repo is contract minimalism — expansion must be justified; contraction is free.
Status: active (Steps 1–6 landed). This file separates the standing scope rule from the historical migration checklist below. The tiers and enforcement rules in this document now describe the live tree; the remaining work is graduation of individual Preview surfaces, not the migration itself.
A surface belongs in Core if and only if:
- It serves the single thesis — compiler-first fine-grained reactivity with fail-closed guarantees, authored as plain TSX; and
- Removing it breaks the thesis (not merely "it's useful"); and
- It has converged enough to be held to the guarantee bar
(
strictGuarantee, reactivity-guarantee-matrix, api-freeze-v1).
Fail any of the three → it is not Core. It is demoted, not deleted.
| Tier | Held to guarantee bar? | Versioning | Published? | Meaning |
|---|---|---|---|---|
| Core | ✅ yes | Lockstep (fixed) |
✅ public | The thesis. npm i fict @fictjs/vite-plugin is exactly this set. |
| Satellite | ❌ no (own contract) | Independent (0.x ok) |
✅ public | Real product, but allowed to lag/iterate without dragging Core. |
| Preview | ❌ no — no semver | Rides host package | experimental entry or default-off option |
Aspirational surface. May change or be removed at any time. |
| Internal | ❌ no | Not released (ignore) |
🚫 private, or store-distributed (not npm) |
Dev scaffolding and store/marketplace-distributed tooling. Not a changeset-released npm library. |
| Package | Tier | Notes |
|---|---|---|
fict |
Core | Public API surface. Only ., /jsx-runtime, /jsx-dev-runtime, /plus, /advanced are guaranteed; /experimental/loader is Preview. |
@fictjs/runtime |
Core | Reactive graph + fine-grained DOM. |
@fictjs/compiler |
Core | OXC/Rust analysis and lowering plus the eight lockstep native platform packages. The thesis lives here. |
@fictjs/vite-plugin |
Core | The delivery mechanism. Without it nobody can use Fict. |
@fictjs/eslint-plugin |
Core | Mirrors compiler diagnostics — part of the fail-closed DX, not an add-on. |
@fictjs/ssr |
Satellite | renderToString/renderToStream/renderToPipeableStream are supported. Snapshot/resume/PPR behavior is Preview (see below). |
@fictjs/router |
Satellite | A router may lag Core. Best candidate to invite a second maintainer (reduces truck factor). |
@fictjs/testing-library |
Satellite | Adoption-enabling; frozen API, downstream of runtime stability. |
@fictjs/webpack-plugin |
Satellite | Official Webpack 5 compiler adapter; independently versioned so it does not expand the Core lockstep train. |
@fictjs/devtools |
Internal | Browser extension / Vite auto-inject — a private distribution artifact, not an npm library. Feature-frozen. |
@fictjs/vscode-extension |
Internal | Private editor extension distributed through the VS Code Marketplace, not npm. Feature-frozen. |
@fictjs/playground |
Internal | Private dev/demo tool. |
fict-docs-site |
Internal | Already private. |
Fict 0.31 is Rust-only. The final legacy preset release is 0.30.1; it is not a
workspace package, Core member, publish target, or supported 0.31 rollback path.
Applications that still require it must pin their complete Fict dependency set
to 0.30.1, as recorded by
ADR-0003.
These are explicitly not under semver and not under the guarantee bar. See docs/PREVIEW.md for the policy and the required degradation contract.
@fictjs/ssr/experimental:renderToPartial(partial prerendering), off the@fictjs/ssrmain export.fict/experimental/loaderand@fictjs/runtime/experimental/loader: the resumable loader, QRL handler extraction, and SSR snapshot schema. SSR and compiler participation is enabled only by default-off Preview options such asincludeSnapshot: trueandresumable: true.
Preview graduation does not block Core 1.0. Core can reach 1.0 while these surfaces remain Preview, and the Core compatibility promise excludes them. The machine-readable boundary is maturity.json.
- Version lockstep = Core membership. The
fixedarray in .changeset/config.json is the Core list. Satellites are absent from bothfixedandignore(independent). Internal packages are inignoreand/or"private": true. "Independent" describes the release decision and bump train, not a rule that Satellite and Core version strings must always differ. A Satellite may have the same numeric version when its own changes warrant that release; it must not be bumped merely because Core moves. Production dependencies from Satellites to Core therefore use compatibleworkspace:ranges rather than the exact-versionworkspace:*protocol. - Guarantee bar applies to Core only.
strictGuarantee, the guarantee matrix, and API-freeze cover Core packages. Satellites/Preview document their own, weaker, contract. - Preview callables are reachable only through an
experimentalentrypoint plus an@experimentalJSDoc tag, never from a package's main export. Cross-cutting Preview behavior may use default-off Preview options on a supported host API only when each option is tagged@experimentaland the stable default does not emit or consume the Preview protocol. - Core and Preview release independently. maturity.json
must match the Changesets Core fixed group, and every Preview surface must
declare
core1ReleaseBlocking: false.
The MCP server and agent skill library are tooling for AI agents to consume Fict. For a project with ~zero production users, carrying them inside the core monorepo as versioned product packages is a second, implicit thesis ("AI-native distribution is the GTM").
A solo project cannot carry two core theses. Pick one:
- If compiler-first reactivity is primary (the assumption here) → MCP/skill tooling lives outside this monorepo. It must not compete with Core for attention or version surface.
- If AI-native distribution is primary → that is a different project; do not let it share one maintainer's attention with the compiler.
Decision (2026-05): primary thesis is compiler-first reactivity. The MCP server and skill library have moved to standalone repos (
mcp/andskill/, remotesfictjs/mcpandfictjs/skill) and are no longer packages in this monorepo.
Before publishing any new package or version-locked surface, answer in the PR description: "Does this enter Core? If not, why must it be published at all (vs.
private, vs. an independent0.xsatellite)?"Default answer is do not publish / private / independent
0.x. Expansion requires an explicit, written justification. Contraction does not.
Tracks the move from "13 lockstep 0.21.0 packages" to "Core lockstep + a ring
of independent satellites + ignored internal tooling."
[x]means committed. Steps 1–2 landed atomically (SCOPE.md + docs/PREVIEW.md +.changeset/config.jsonin one commit), so the docs never describe a config that isn't in the tree.
- Step 1 — Define tiers (this file + docs/PREVIEW.md).
- Step 2 — Encode Core via changesets.
fixedreduced to the five Core public surfaces plus the compiler's eight native distribution packages;ssr/router/testing-librarymoved to independent versioning; then-internalmcp/skillwere temporarily added toignorebefore their standalone repo split. (See.changeset/config.json.) - Step 3 — Move Preview off stable-looking exports. Added the
@fictjs/ssr/experimentalentrypoint and movedrenderToPartialthere, off the@fictjs/ssrmain export (engine extracted to the internalrender-coremodule;.re-exports only the supported surface). The resumable loader moved from stable-looking/loadersubpaths tofict/experimental/loaderand@fictjs/runtime/experimental/loader; snapshot emission is now explicit (includeSnapshot: true). - Step 4 — Move agent tooling out of the monorepo.
@fictjs/mcpand@fictjs/skillwere first privatized, then migrated into standalone repos (mcp/andskill/). They no longer participate in this monorepo's workspace, Changesets config, or Turbo graph. - Step 5 — Preview degradation contracts. The current failure behavior is audited and test-backed in preview-degradation-audit.md, including explicit legacy snapshot migration, one-shot application-owned CSR handoff after loader cleanup, sibling-scope isolation for resume failures, and streaming sink-error cleanup. The contract does not claim automatic CSR or ErrorBoundary routing for QRL failures.
- Step 6 — Re-tier docs. SSR docs (deployment, resume-stability,
performance, SEO) now carry a maturity banner:
@fictjs/ssris a Satellite and resume/PPR are Preview. Tier-0 docs (semantics, diagnostics, guarantee matrix, compiler spec) remain Core (unchanged).
Remaining for Preview graduation, not Core 1.0: the degradation-contract migration work is complete. Graduation still requires the other docs/PREVIEW.md gates (frozen API shape and a frozen snapshot-schema compatibility window). When those land, collapse this block to the map + rule as the standing contract.