Skip to content

Replace monolithic ObjectStackKernel with plugin-based MiniKernel architecture#333

Merged
hotlong merged 5 commits intomainfrom
copilot/replace-runtime-kernel-with-mini-kernel
Jan 28, 2026
Merged

Replace monolithic ObjectStackKernel with plugin-based MiniKernel architecture#333
hotlong merged 5 commits intomainfrom
copilot/replace-runtime-kernel-with-mini-kernel

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 28, 2026

Migrates codebase from ObjectStackKernel (monolithic) to ObjectKernel (microkernel) as the primary runtime. ObjectStackKernel is deprecated but remains for backward compatibility.

Architecture

The MiniKernel provides:

  • Plugin lifecycle: init → start → destroy with dependency resolution via topological sort
  • Service registry: Dependency injection container replacing hardcoded engine references
  • Event hooks: Pub/sub for inter-plugin communication
  • Type-safe context: PluginContext with getKernel() for advanced use cases

Changes

New Components

  • AppManifestPlugin: Wraps objectstack.config.ts exports as first-class plugins
  • Enhanced PluginContext: Added getKernel() returning ObjectStackKernel | ObjectKernel
  • Updated ObjectStackRuntimeProtocol: Supports both kernel types via kernel detection

Refactored Modules

  • All examples: msw-react-crud, host, custom-objectql-example now use plugin chaining
  • plugin-msw: Implements both Plugin and RuntimePlugin interfaces
  • Runtime exports: ObjectKernel first, ObjectStackKernel marked @deprecated

Example

Before:

const kernel = new ObjectStackKernel([
  new ObjectQLPlugin(),
  appConfig,
  driver
]);
await kernel.start();

After:

const kernel = new ObjectKernel();
kernel
  .use(new ObjectQLPlugin())
  .use(new DriverPlugin(driver, 'memory'))
  .use(new AppManifestPlugin(appConfig));
await kernel.bootstrap();

Compatibility

Full backward compatibility maintained. Existing code using ObjectStackKernel continues to work unchanged.

Original prompt

使用 mini kenel替换现有runtime kernel,并重购所有模块的代码


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@vercel
Copy link
Copy Markdown

vercel bot commented Jan 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
spec Ready Ready Preview, Comment Jan 28, 2026 3:09am

Request Review

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
Copilot AI changed the title [WIP] Replace existing runtime kernel with mini kernel Replace monolithic ObjectStackKernel with plugin-based MiniKernel architecture Jan 28, 2026
Copilot AI requested a review from hotlong January 28, 2026 03:08
@hotlong hotlong marked this pull request as ready for review January 28, 2026 03:39
Copilot AI review requested due to automatic review settings January 28, 2026 03:39
@github-actions github-actions bot added documentation Improvements or additions to documentation size/l labels Jan 28, 2026
@@ -1,4 +1,4 @@
import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';
import { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin, ObjectQL } from '@objectstack/runtime';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import ObjectQL.

Copilot Autofix

AI 2 months ago

In general, unused imports should be removed from the import list so the code only brings in what it actually uses. This improves readability and avoids potential linting or compilation warnings.

The best fix here is to edit examples/host/src/index.ts and modify the first import statement: remove ObjectQL from the destructured import from @objectstack/runtime, keeping the remaining imported names unchanged. No other code changes or new imports are required, and this will not alter runtime behavior because ObjectQL was never referenced.

Concretely: in examples/host/src/index.ts, line 1 currently imports { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin, ObjectQL }. Replace that line with an import that only includes { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin }.

Suggested changeset 1
examples/host/src/index.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/host/src/index.ts b/examples/host/src/index.ts
--- a/examples/host/src/index.ts
+++ b/examples/host/src/index.ts
@@ -1,4 +1,4 @@
-import { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin, ObjectQL } from '@objectstack/runtime';
+import { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin } from '@objectstack/runtime';
 import { InMemoryDriver } from '@objectstack/driver-memory';
 import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
 
EOF
@@ -1,4 +1,4 @@
import { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin, ObjectQL } from '@objectstack/runtime';
import { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin } from '@objectstack/runtime';
import { InMemoryDriver } from '@objectstack/driver-memory';
import { HonoServerPlugin } from '@objectstack/plugin-hono-server';

Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +3 to +10
import {
RuntimePlugin,
RuntimeContext,
Plugin,
PluginContext,
ObjectStackRuntimeProtocol,
ObjectKernel
} from '@objectstack/runtime';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import ObjectKernel.

Copilot Autofix

AI 2 months ago

To fix the unused import, remove ObjectKernel from the import list on line 3 while leaving all actually used imports intact. This will eliminate the unused symbol without affecting existing functionality.

Concretely, in packages/plugin-msw/src/msw-plugin.ts, edit the import from @objectstack/runtime so that ObjectKernel is no longer included in the named imports. No additional code changes or imports are needed, and no other lines must be modified.

Suggested changeset 1
packages/plugin-msw/src/msw-plugin.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/plugin-msw/src/msw-plugin.ts b/packages/plugin-msw/src/msw-plugin.ts
--- a/packages/plugin-msw/src/msw-plugin.ts
+++ b/packages/plugin-msw/src/msw-plugin.ts
@@ -5,10 +5,10 @@
     RuntimeContext, 
     Plugin, 
     PluginContext, 
-    ObjectStackRuntimeProtocol,
-    ObjectKernel 
+    ObjectStackRuntimeProtocol
 } from '@objectstack/runtime';
 
+
 export interface MSWPluginOptions {
     /**
      * Enable MSW in the browser environment
EOF
@@ -5,10 +5,10 @@
RuntimeContext,
Plugin,
PluginContext,
ObjectStackRuntimeProtocol,
ObjectKernel
ObjectStackRuntimeProtocol
} from '@objectstack/runtime';


export interface MSWPluginOptions {
/**
* Enable MSW in the browser environment
Copilot is powered by AI and may make mistakes. Always verify output.
@hotlong hotlong merged commit 5220890 into main Jan 28, 2026
15 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request successfully migrates the codebase from the monolithic ObjectStackKernel to a plugin-based ObjectKernel (MiniKernel) architecture while maintaining full backward compatibility.

Purpose: Replace the monolithic kernel with a modular, plugin-based microkernel that provides better separation of concerns, dependency injection, and lifecycle management.

Changes:

  • Introduced ObjectKernel with plugin lifecycle management (init → start → destroy) and topological dependency resolution
  • Created AppManifestPlugin to wrap app configurations as first-class plugins
  • Updated ObjectStackRuntimeProtocol to support both legacy and new kernel types
  • Migrated all examples and documentation to demonstrate the new architecture

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/runtime/src/types.ts Added getKernel() method to PluginContext for advanced plugin use cases; updated RuntimeContext to accept both kernel types
packages/runtime/src/protocol.ts Implemented kernel type detection and dual-path support for both ObjectStackKernel and ObjectKernel
packages/runtime/src/objectql-plugin.ts Added compatibility check to handle both kernel types in legacy install method
packages/runtime/src/mini-kernel.ts Added getKernel() implementation to PluginContext
packages/runtime/src/kernel.ts Added comprehensive deprecation documentation with migration examples
packages/runtime/src/index.ts Reordered exports to promote ObjectKernel first, marked ObjectStackKernel as deprecated
packages/runtime/src/app-manifest-plugin.ts New plugin that wraps app manifests with schema registration and data seeding capabilities
packages/runtime/README.md Completely updated documentation with new architecture, migration guide, and best practices
packages/plugin-msw/src/msw-plugin.ts Implemented dual interface support for both Plugin and RuntimePlugin patterns
examples/msw-react-crud/src/mocks/browser.ts Migrated to use ObjectKernel with plugin chaining pattern
examples/host/src/index.ts Migrated to use ObjectKernel with AppManifestPlugin for each app
examples/host/debug-registry.ts Updated to use new kernel and plugin architecture
examples/custom-objectql-example.ts Updated to demonstrate custom ObjectQL instance with new kernel

Comment on lines +54 to +58
// Check if data already exists
const existing = await objectql.find(seed.object, { top: 1 });
if (existing.length === 0) {
ctx.logger.log(`[AppManifestPlugin] Inserting ${seed.records.length} records into ${seed.object}`);
for (const record of seed.records) {
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The seed data check only verifies if the object has any records (top: 1), not whether the specific seed records already exist. This means if ANY data exists in the object, the seed data will never be inserted, even if those specific records are missing. Consider implementing a more precise check, such as checking for specific record IDs or using a dedicated seeding flag/table to track which seed sets have been applied.

Suggested change
// Check if data already exists
const existing = await objectql.find(seed.object, { top: 1 });
if (existing.length === 0) {
ctx.logger.log(`[AppManifestPlugin] Inserting ${seed.records.length} records into ${seed.object}`);
for (const record of seed.records) {
ctx.logger.log(`[AppManifestPlugin] Processing seed data for object ${seed.object}`);
for (const record of seed.records) {
let shouldInsert = true;
// If the seed record declares an 'id', perform a targeted existence check.
if (record && typeof record === 'object' && 'id' in record) {
try {
const existing = await objectql.find(seed.object, {
filter: { id: (record as any).id },
top: 1,
});
shouldInsert = existing.length === 0;
} catch (lookupError) {
ctx.logger.warn(
`[AppManifestPlugin] Failed to check for existing record in ${seed.object}`,
lookupError,
);
// If the existence check fails, fall back to attempting an insert.
shouldInsert = true;
}
}
if (shouldInsert) {

Copilot uses AI. Check for mistakes.
name = 'msw';
export class MSWPlugin implements Plugin, RuntimePlugin {
name = 'com.objectstack.plugin.msw';
version = '1.0.0';
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The MSWPlugin should declare a dependency on the ObjectQL plugin since it creates an ObjectStackRuntimeProtocol that requires ObjectQL to be available. Add dependencies = ['com.objectstack.engine.objectql'] to ensure proper initialization order. Without this, the plugin might start before ObjectQL is initialized, causing runtime errors.

Suggested change
version = '1.0.0';
version = '1.0.0';
dependencies = ['com.objectstack.engine.objectql'];

Copilot uses AI. Check for mistakes.
Comment on lines +181 to +184
// TODO: Implement proper ID-based lookup once ObjectQL supports it
// For now, this is a limitation of the current ObjectQL API
const results = await ql.find(objectName, { top: 1, filter: { id } });
return results[0];
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

The getData implementation should use ObjectQL's findOne method instead of find with a filter. ObjectQL provides a findOne method (as seen in packages/objectql/src/index.ts) that is designed for ID-based lookups and will be more efficient. Change line 183 to use: return await ql.findOne(objectName, id);

Suggested change
// TODO: Implement proper ID-based lookup once ObjectQL supports it
// For now, this is a limitation of the current ObjectQL API
const results = await ql.find(objectName, { top: 1, filter: { id } });
return results[0];
return await ql.findOne(objectName, id);

Copilot uses AI. Check for mistakes.
@@ -1,4 +1,4 @@
import { ObjectStackKernel, ObjectQLPlugin, ObjectQL } from '@objectstack/runtime';
import { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin, ObjectQL } from '@objectstack/runtime';
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

Unused import ObjectQL.

Suggested change
import { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin, ObjectQL } from '@objectstack/runtime';
import { ObjectKernel, ObjectQLPlugin, DriverPlugin, AppManifestPlugin } from '@objectstack/runtime';

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +9
ObjectStackRuntimeProtocol,
ObjectKernel
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

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

Unused import ObjectKernel.

Suggested change
ObjectStackRuntimeProtocol,
ObjectKernel
ObjectStackRuntimeProtocol

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/l

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants