Skip to content

docs: pitch-first README and plugin authoring guide - #56

Merged
danielgerlag merged 6 commits into
mainfrom
docs/pitch-first-readme
Sep 26, 2026
Merged

danielgerlag merged 6 commits into
mainfrom
docs/pitch-first-readme

Conversation

@danielgerlag

@danielgerlag danielgerlag commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Part of #33

What changed

README.md is rewritten as a front page for newcomers:

  • The pitch, then four one-line points on what the kernel does differently (governance in the kernel, the plugin lifecycle, providers as plugins, versioned distributions), then a status line: alpha, desktop is the reference distribution, macOS primary with Linux in CI, not published to npm, MIT.
  • Run a harness headless quotes examples/headless/src/main.ts exactly.
  • Quickstart is unchanged.
  • Architecture is one paragraph per layer, without the validation rules. The contracts paragraph describes main after refactor(contracts): plugin-owned contracts, part 4 (mcp, mcp-apps, feedback, a2a) #54: the root holds defineCommand, defineEvent and the kernel's schemas (including the MCP server config personas embed), defines no plugin commands, and its only event is borg.channel.inboundMessage. Plugin-owned schemas ship from @borg/plugin-<name>/contract.
  • Boundaries and the desktop app are short summaries that link to docs/. The macOS packaging commands stay. There is a License section.

docs/boundaries.md (new) holds the full boundary rule list from the README, read from scripts/check-plugin-boundaries.mjs and the other two check:boundaries scripts on main. One rule was corrected: ./contract requires the tsconfig named by the package's build script (default tsconfig.main.json) to list src/contract.ts, src/*.ts or src/**/*.ts.

docs/desktop.md (new) holds the desktop setup and feature detail from the README, unchanged.

docs/plugin-authoring.md gets only the same tsconfig correction and a link to docs/boundaries.md.

CONTRIBUTING.md links to docs/boundaries.md and notes the /contract exception to the plugin import rule.

Headless example

  • examples/headless (@borg/example-headless) defines a four-plugin distribution (borg.config.sqlite, borg.secrets.dev, borg.mock-llm, borg.hello), boots it with createKernel() in plain Node, calls borg.hello.getStatus once, and stops. The kernel won't start without a config store and a secret store, which is why those two plugins are in it.
  • To make that work without reaching into package paths, plugins/{config-sqlite,secrets-dev,mock-llm,hello}/package.json now export ./borg.plugin.json. That's the only change outside docs, examples and workspace wiring.
  • examples/* is added to pnpm-workspace.yaml, the vitest include and tsconfig.tests.json. The lockfile diff is the new importer entry only.
  • examples/headless/test/headless.test.ts runs the built dist/main.js and expects borg.hello: Kernel alive. It also checks that the README code block matches the file byte for byte. pnpm test builds first, so both CI jobs run it without a new CI step.

Merge of main

The branch merges origin/main at fa68858 (#54) normally, with no force-push. Nothing in the docs describes plugin schemas as still sitting in the root or points to #31 as in progress.

Gates (local, Linux, Node 24, pnpm 12.0.0)

  • install --frozen-lockfile ✅
  • check:boundaries ✅
  • typecheck ✅
  • test: 140 files, 935 tests, including the example ✅
  • test:e2e (xvfb): 44 passed, 2 skipped, 0 failed ✅

Left for #33

  • ESLint: flat config, a pnpm lint script, and a CI step, in a separate PR.
  • Examples: the examples/ item is covered by examples/headless, which pnpm test runs. A plugin-authoring example (a plugin package under examples/) could follow if wanted.
  • The Linux CI job item was already done by ci: run e2e on Linux and make tray-title assertions platform-aware #43.

Open with what Borg Agent is (kernel plus plugins, bundled as a
distribution), then quickstart, the workspace architecture including
distributions and the @borg/contracts root and capability subpaths, and
every rule scripts/check-plugin-boundaries.mjs enforces. The desktop
app instructions move under a Desktop app section; a few statements
were corrected against the source.

Part of #33
docs/plugin-authoring.md walks through plugins/hello: package layout and
the borg field, the manifest and what PluginManager validates, activation
and the PluginContext permission table, contract.ts and the ./contract
export, import rules, UI registration, tests with createTestHarness, and
declaring a plugin in the borg.desktop distribution.

Part of #33
…ev, mock-llm and hello

A host outside apps/desktop builds a PluginSource from a plugin's static manifest and its main entry. These four packages now export ./borg.plugin.json so a host can require the manifest by package specifier instead of a path into the package. The headless example uses them.

Part of #33
docs/boundaries.md holds every rule scripts/check-plugin-boundaries.mjs and the other two check:boundaries scripts enforce, read from the scripts on main. It also corrects the ./contract tsconfig rule (the tsconfig named by the build script, with src/contract.ts, src/*.ts or src/**/*.ts in include) and lists the contracts subpaths as they are after #54.

docs/desktop.md holds the desktop setup and feature detail unchanged.

docs/plugin-authoring.md gets the same tsconfig correction and links to docs/boundaries.md. CONTRIBUTING.md links to it and states the /contract exception to the plugin import rule.

Part of #33
The README now opens with the pitch, four points on what the kernel does differently, and a status line. It quotes examples/headless/src/main.ts, which defines a four-plugin distribution, boots the kernel in plain Node, sends borg.hello.getStatus, and stops. Architecture is one paragraph per layer, boundaries and the desktop app are short summaries that link to docs/, and there is a License section.

examples/* joins the workspace, the vitest include and tsconfig.tests.json. examples/headless/test/headless.test.ts runs the built example and checks that the README block matches the file, so pnpm test in both CI jobs covers it. The lockfile change is the new importer entry only.

Part of #33
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.

1 participant