# KlynEditor plugin architecture

KlynEditor is a plugin Workbench. The application core contains the shell,
dependency-injection context, extension contracts and shared editor services.
Language-specific and UML implementations live exclusively below
`tools/editor/plugins/<plugin-id>/src`.

The standard distribution includes dedicated Klyn, C/C++, Java, Python,
JavaScript, CSS, HTML, Markdown, XML and UML plugins. The Markdown editor uses
one source buffer and exposes bottom `Markdown`, `Split` and `Preview` modes.

Runtime discovery scans archive files only. A plugin source directory is a
build input and is never loaded directly by the Workbench.

## Artifact formats

- `.kar` is a portable ZIP archive containing `plugin.json` and Klyn `.kn`
  sources. It is compiled and loaded on demand.
- `.kab` is a platform-specific ZIP archive containing the same manifest,
  `binary.json`, precompiled Klyn native objects, and their generated concrete
  generic dependencies. Compatibility is checked against the operating system,
  architecture, Klyn version and compiler object ABI before any object is loaded.
  `binary.json` also records one stable, relative source identity per object. The
  JIT uses those identities throughout transitive dependency resolution and
  reuses compatible concrete units already supplied by the host process.

When both artifacts exist, the loader selects a compatible `.kab`. An
incompatible binary falls back to the matching `.kar`.

## Build

The normal CMake build incrementally generates all plugin artifacts:

```bash
cmake --build build
```

The dedicated target can be requested explicitly:

```bash
cmake --build build --target KlynEditorPlugins
```

The direct Klyn entry point is also available:

```bash
klyn tools/editor/BuildPlugins.kn
```

The automated KlynEditor build currently creates `<plugin-id>.kar` beside each
plugin source folder. Klyn distributions install the Workbench, its plugin SDK
sources and these portable archives under `tools/editor`. Automatic `.kab`
generation is temporarily paused; the native archive command remains available
for explicit format validation.

Individual plugins can be packaged directly through the official compiler
options:

```bash
klyn --build-kar -o tools/editor/plugins/example.kar tools/editor/plugins/example
klyn --build-kab -o tools/editor/plugins/example.kab tools/editor/plugins/example
```

Use `--rebuild --build-kab` when native objects must be regenerated
unconditionally. Without `-o`, the archive is written beside the plugin
directory using the `id` declared in `plugin.json`.

## Lifecycle

1. `KarPluginLoader` validates and extracts artifacts under the versioned Klyn
   cache (`Application.properties["klyn.cacheDirectory"]/editor/plugins`).
2. `KarClassLoader` loads source or native objects into the active Klyn runtime.
3. `KlynEditorPluginRegistry` resolves plugin dependencies.
4. `DIContext` constructs the entry class, injects `context` and `workbench`,
   and invokes lifecycle annotations.
5. The registry calls `activate()`.
6. Shutdown calls `deactivate()` in reverse dependency order, then closes the
   DI context.

Project templates and project-specific context actions are plugin
contributions. The Workbench has no language or UML identifier switch.
Run commands, lexical declaration modes, identifier rules, keywords, built-in
types, comments and string delimiters are contributions as well. Built-in
types use their own semantic color and remain distinct from language keywords.
The Klyn contribution also declares indentation-scoped KQL keywords and value
types, while compiler diagnostics for `query:` blocks follow the same LSP path
as ordinary Klyn errors.
Completion, navigation and project-wide rename therefore consume the same
plugin syntax profile; adding a new technology does not require editing
`KlynEditorWorkbench` or its refactoring service.


Plugin archive paths are validated as relative paths before use. Loaded Klyn
types live for the process lifetime, so a plugin that fails during activation
keeps a `FAILED` handle and cannot be reloaded under the same identifier until
the Workbench restarts.
