# KL4A > KL4A (Knowledge Layer For Agents) — the local-first, open-source workbench that turns SOPs, policies, and procedures into grounded, human-reviewed Knowledge Bundles. ## Home ### Home # KL4A *Knowledge Layer For Agents — an independent open-source project.* **Create OKF-compliant knowledge bundles from your SOP docs, and enable your agents to use them.** Your organization's SOPs, policies, procedures, regulations, and standards live in Word docs, PDFs, and wikis — written for humans, not for agents. KL4A reads them, proposes structured knowledge, and puts a person in front of every claim before an agent can act on it. What comes out the other side is a **Knowledge Bundle**: - Every claim traces back to the exact source text it came from. - Nothing an agent can act on until a person has reviewed it. - Plain files, git-diffable, no lock-in — built on [OKF](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf), the open format this project implements. (KL4A is not affiliated with or endorsed by the OKF project.) It doesn't claim to mine everything in a document — known gaps are tracked in the repo. **Ground it. Review it. Then trust it.** ## Built for knowledge engineers KL4A is for the person who owns turning a folder of SOPs into something an agent can be trusted against: ingest a document set, inspect what got extracted and why, work through review until the bundle is clean, and hand it off — to an agent, an MCP server, or an enterprise import. You review the knowledge once, so you don't have to review every answer forever. That review happens once, at authoring time, on a bounded set of extracted claims — not at runtime, on every answer an agent gives. It's also usable without a knowledge engineer in the room: - **SOP & policy owners** see exactly what was extracted, verify it against source evidence, and approve, reject, or correct it — no CLI required. - **Agent developers** search knowledge items, resolve citations, and retrieve source-grounded context locally, via CLI, MCP, or the bundle's plain files. ## What it does - **Structure** — sources become OKF-native bundles agents can query directly. - **Ground** — every claim keeps its exact source span, or is flagged when one can't be matched. - **Review** — nothing becomes accepted knowledge until a person approves, rejects, defers, edits, or comments on it. - **Consume** — agents query the bundle via CLI, agent chat, or MCP; export to Graph JSON or RDF/TTL when other tooling needs it. ## Reference bundle A synthetic, fully worked GLP-1 healthcare example lives at [`examples/glp1-healthcare`](https://github.com/CogniSwitch/KL4A/tree/main/examples/glp1-healthcare). It includes: - Multiple SOP-like sources - Evidence-backed proposed knowledge - Persisted human-in-the-loop review states - Conflict and freshness reports - OKF, Graph JSON, and RDF exports ## Where this fits !!! info "Free and complete on its own" KL4A handles extraction, evidence grounding, and human review. Free. Local-first. Yours to run anywhere, forever. Deterministic enforcement, cross-bundle reasoning, audit trails, and governed multi-tenant operation in production are a separate, deliberately out-of-scope concern — a downstream layer this project doesn't try to be. KL4A is a tool for the layer where ontology projects actually fail — this is how your SOPs get ready for that layer, whether or not you ever adopt anything downstream of it. See [Governance](GOVERNANCE.md) for exactly where that line sits, why, and who maintains this project. ## Guides - **[Why This Exists](WHY.md)** — why KL4A exists and why it's open. - **[Quickstart](quickstart.md)** — install and open the desktop app, first bundle. - **[Desktop UI Guide](DESKTOP_UI_GUIDE.md)** — the desktop app: browsing, review, ingest, and the agent chat. - **[Architecture](ARCHITECTURE.md)** — how the pieces fit together, linking down to the deeper design docs. - **[FAQ](FAQ.md)** — common setup and ingestion problems. ## Project - **[Contributing](CONTRIBUTING.md)** — dev setup, tests, PR process, DCO sign-off. - **[Governance](GOVERNANCE.md)** — project governance and the open-source/enterprise boundary. - **[License](https://github.com/CogniSwitch/KL4A/blob/main/LICENSE)** — Apache-2.0. - **[GitHub repository](https://github.com/CogniSwitch/KL4A)** --- *KL4A · Apache-2.0 · maintainers & boundary: see [Governance](GOVERNANCE.md)* ## Why This Exists ### Why This Exists # Why We Built This ## Agents need somewhere to get the rules from That agents need a knowledge layer is no longer the interesting question. Which layer is the right one still is, and nobody has the full answer yet. What organizations have today is knowledge written for people. SOPs, policies, procedures, regulations and standards live as Word documents and PDFs, sitting in folders on Google Drive, on SharePoint, or on somebody's laptop. Source code lives the same way, in folders on GitHub. That folder is the structure everyone already uses, and it works. Most current tooling starts from a different assumption: foundation models are strong at natural language, so you can point one at a natural-language source and let it work things out. For anything that has to be followed exactly, that assumption breaks down. Ask an agent to apply a procedure and you often get an answer that reads well and is wrong in a way nobody catches until it matters. ## What this project does about it This is a transformation, not a new system to adopt. Your documents stay where they are. The workbench reads them, proposes structured knowledge from what it finds, and puts a person in front of every proposal before anything is accepted. What comes out is a set of plain files in a folder, next to the documents they came from. There is no database and nothing to migrate onto. It is a small change to your setup and a large change in how an agent behaves against the same material. Two properties carry the weight. **Every claim keeps the text it came from.** A knowledge item is not a summary that has floated free of its source. It carries the exact span it was derived from, or it is flagged when that span could not be matched. When an agent answers from a bundle, you can follow the answer back to the sentence in the original document. **Nothing is usable until a person approves it.** Extraction proposes. A reviewer approves, rejects, defers, edits or comments, and that decision is recorded in the bundle along with who made it and why. This is not a rubber stamp over runtime output. It happens once, over a bounded set of claims, before anything goes into service. ## Why it is open source A bundle is only trustworthy if you can read it without us. The format is plain Markdown with YAML frontmatter, so a text editor or `grep` is enough to inspect what an agent is being told. A claim about provenance that you cannot verify yourself is not much of a claim. Keeping bundle creation and review open also keeps us honest about where the commercial line sits — see [Governance](GOVERNANCE.md) for exactly where that boundary is drawn and why. --- # What We Think of OKF OKF, the Open Knowledge Format, is an open standard published by Google Cloud for representing knowledge as Markdown files with YAML frontmatter, organized in directories. We did not invent it and we are not trying to replace it. ## Its minimalism is the point OKF asks for very little. A small set of required keys is enough for interoperability, and beyond that a bundle may carry additional frontmatter keys and body sections without breaking anything that consumes it. That restraint is the most attractive thing about it. A standard that specifies everything up front tends to specify the wrong things, because the people writing it are guessing about uses that do not exist yet. A standard that specifies the minimum leaves room for practice to decide. There is an obvious risk, which is fragmentation: everyone extends in their own direction and interoperability becomes theoretical. Our expectation runs the other way. As more people build against it, agreement should form about what is genuinely needed, and more of it should become required. We would rather take part in that than wait for it to settle. ## A conformant bundle is not automatically a useful one Meeting the format and being useful to an agent are different achievements. Google's own repository ships reference implementations and worked example bundles alongside the specification, which suggests they see the same gap. Our work sits in that gap. We stay inside the format and add depth: evidence spans, review state with reviewer rationale, decision rules that can be checked mechanically, and conflict and freshness reporting. All of it lives under our own namespace, as the standard's extension rules allow, so a bundle we produce stays readable by any OKF consumer that has never heard of us. Whether we have added the *right* depth is genuinely open. Some of it may turn out to be more than anyone needs, and some of it may be too thin. That gets settled by people using it, not by us asserting it. ## What we are betting on Version 0.2 introduced fields concerned with provenance and trust. Those are the fields we have built around, because the problem we care about is not retrieving relevant text. It is being able to say where a claim came from and who checked it. If you are comparing this against other OKF tooling, that emphasis is the difference worth looking at. ## What interoperability buys The reason to stay inside a shared format rather than invent our own is straightforward. If the structure is the same everywhere, one organization's agent can read another organization's knowledge without a bespoke integration for every pair. Enterprises will need access control and exposure rules layered on top, and those are their decisions to make. The path has to exist first. ## Where we would like help A few questions we would rather answer with the community than on our own: - What should become required in a future revision of the format? - Do decision rules belong in the format itself, or in a layer above it? - How should confidence be expressed? Ours is currently a placeholder and we know it. - Which parts of our extension are worth proposing upstream? We would rather be told we got this wrong early than be right in private. ## Quickstart ### Quickstart # Quickstart KL4A is a native desktop app. Install it, open it, and everything else — creating a bundle, ingesting sources, reviewing mined knowledge, exporting, talking to the agent — happens inside the app itself. There's no CLI you need to touch to get started. ## Get the app | Platform | Download | |---|---| | **Windows** | [⬇ Installer (`.exe`)](https://github.com/CogniSwitch/KL4A/releases/download/0.0.1-alpha/KL4A.Workbench_0.0.1-alpha_x64-setup.exe) | | **macOS** | [⬇ Disk image (`.dmg`)](https://github.com/CogniSwitch/KL4A/releases/download/0.0.1-alpha/KL4A.Workbench_0.0.1-alpha_universal.dmg) — universal, runs on Apple Silicon and Intel | | **Linux** | [⬇ AppImage](https://github.com/CogniSwitch/KL4A/releases/download/0.0.1-alpha/KL4A.Workbench_0.0.1-alpha_amd64.AppImage) | !!! warning "The builds aren't code-signed yet" No Apple Developer ID or Windows signing certificate is set up for this project yet, so your OS will warn you on first launch: - **macOS** — Gatekeeper blocks it as "from an unidentified developer". Right-click the app in Finder and choose **Open** (once), or run `xattr -cr` on it. - **Windows** — SmartScreen shows "Windows protected your PC". Click **More info** → **Run anyway**. - **Linux** — mark the AppImage executable first: `chmod +x KL4A*.AppImage`. ## First launch On first launch you land on the bundle picker. Create a new bundle, point it at a folder of SOPs/policies/procedures (Markdown, DOCX, or PDF), and the app walks you through the rest: ingest → inspect what got mined and why → review (approve, reject, defer, edit, comment) → export. See the [Desktop UI Guide](DESKTOP_UI_GUIDE.md) for a full screen-by-screen tour. ## A richer example Once you're comfortable with the app, open the included **GLP-1 Healthcare SOP** reference bundle — a finished, evidence-linked bundle with persisted review states, conflict/freshness reporting, and full OKF/graph/RDF export: → **[examples/glp1-healthcare](https://github.com/CogniSwitch/KL4A/tree/main/examples/glp1-healthcare)** ## Next steps - [Desktop UI Guide](DESKTOP_UI_GUIDE.md) — the desktop app, screen by screen. - [MCP Server](MCP_SERVER.md) — connecting an agent to a bundle you've built. - [FAQ.md](FAQ.md) — common setup and ingestion problems. - [Contributing](CONTRIBUTING.md) — if you want to work on KL4A itself. ## Guides ### Desktop UI Guide # Desktop UI Guide This guide walks through every screen of the KL4A Workbench desktop app. It's a Tauri v2 native shell: a React single-page app talks directly, in-process, to a Rust command layer — no HTTP server, no sidecar process, no separate runtime to install. See the [Quickstart](quickstart.md) for how to get the app. !!! note "About the images below" All but one are real screenshots of the app running against the `examples/glp1-healthcare` bundle. Only the Degraded recovery screen is still an illustrative wireframe, not a real screenshot — labeled as such. Swap it for a real capture whenever convenient: drop a PNG named `degraded.png` into `images/desktop-ui/` and update the reference below. ## Getting started Launch the built executable directly. With no arguments, it opens a `SOP Knowledge Workbench` folder in your home directory, created automatically if it doesn't exist yet — that's the on-disk default folder name; the app's own UI is branded KL4A Workbench throughout. To point it at a different folder instead, either pass the folder as the first command-line argument or set the `SOPKB_BUNDLE_DIR` environment variable before launching. A **workbench root** is any folder whose `knowledge-bundles/` subdirectory holds one or more bundles. The app always opens at the **Bundles** screen for that root; picking (or creating) a bundle there is how you get into everything else. ## Layout Every screen shares the same frame: a left sidebar and a main content area to its right. The sidebar has four parts, top to bottom: - A header with the app mark and, once a workbench root is open, whether it's in single-bundle or multi-bundle mode. - **Overview**, pinned above everything else once a bundle is selected — it's the bundle's dashboard, not a workflow step, so it doesn't belong to any of the phase groups below it. - The rest of the bundle-scoped navigation, grouped by workflow phase — **Build** (Ingest, Sources), **Understand** (Knowledge, Concepts), **Govern** (Agent) — scrollable independently of the rest of the sidebar. - **Bundles** and **Settings**, pinned to the bottom behind a divider, always visible regardless of whether a bundle is open. | Screen | What it's for | |---|---| | [Bundles](#bundles) | Every bundle in this workbench root, create/open/delete | | [Overview](#overview) | Bundle stats at a glance, plus the full set of generated reports | | [Ingest sources](#ingest-sources) | Run scan → normalize → mine → validate on a folder or uploaded files | | [Sources](#sources) | Every ingested document, its parse health, and per-source actions | | [Knowledge](#knowledge) | Browse or search every mined knowledge item, with section coverage | | [Concepts](#concepts) | Every entity knowledge has been resolved into | | [Agent](#agent) | Chat against the bundle's knowledge and decision rules, with per-chat memory | | [Settings](#settings) | LLM provider profiles, prompts, MCP wiring, diagnostics — not bundle-scoped | Two more screens are reached only by drilling into something above, not from the sidebar: a source's detail view (from Sources) and a knowledge item's review view (from Knowledge, Sources, or Concepts). ## Bundles The landing screen for a workbench root: every bundle found under `knowledge-bundles/`, as cards in a grid (toggle to a list view; both choices, plus your last sort mode, persist between launches). Each card shows the bundle's title, source count, knowledge-item count, and status, with **Open** and **Delete**. Sort by folder name, title, or creation date (newest first by default), either direction. Above the grid: a field to type a different workbench root path (**Switch**) or pick one with a native folder dialog (**Browse…**), and a field to create a new bundle by title. ![Bundles screen: workbench-root switcher and new-bundle field above a grid of bundle cards, each with source/knowledge-item counts and Open/Delete](images/desktop-ui/bundles.png) !!! warning "Deleting a bundle is permanent" The confirmation dialog requires typing the bundle's exact title to proceed, and says so plainly: this deletes the bundle and everything in it — sources, knowledge items, reviews, exports — and cannot be undone. A bundle that failed to load shows its error inline on the card instead of an Open button, rather than silently disappearing from the list. ## Ingest sources Runs the ingestion pipeline — scan, normalize, mine, validate — against a folder or files you supply from inside the app. - **Source** — **Pick files…** / **Pick folder…** (native pickers) or drop in a **fallback source folder path**; picking a folder overrides any staged files for that run entirely. Supports `.md`, `.txt`, `.docx`, `.pdf`. - **Pipeline steps** — four checkboxes, each labeled with exactly what it does: *Scan*, * Normalize (wipes normalized text first)*, *Mine (rewrites items.json — invalidates existing reviews)*, *Validate*. Steps the last run already completed successfully come pre-unchecked, with a note explaining why — you can always recheck them. - **Mining provider** — a dropdown of whatever LLM profiles are configured in Settings, plus `fixture` as a zero-dependency offline option. - **Preview source changes** shows what would change without requiring confirmation; **Run pipeline** is gated behind an explicit confirmation checkbox in addition to picking at least one step. A run can be cancelled mid-flight (cooperatively — it finishes its current step first). - **Result** — stat tiles for whatever actually ran: files uploaded, sources scanned, sections normalized, items mined, validation errors/warnings. ![Ingest sources screen: source picker and mining-provider dropdown, the four pipeline-step checkboxes, Preview/Run buttons, and staged files ready to run](images/desktop-ui/ingest.png) !!! warning "Scan, Normalize, and Mine each discard prior state for what they touch" Scan wipes each source's recorded state before rescanning it; Normalize wipes normalized text before re-deriving it; Mine rewrites the bundle's knowledge items and invalidates existing reviews on them. This is why **Run pipeline** needs its own confirmation checkbox, separate from just selecting steps. ## Sources Every source document ingested into the bundle, with parse health and management actions. **Reveal bundle folder** opens the bundle's directory on disk; **Force resync** re-derives the OKF bundle without a full ingest run. A banner links to the Ingest screen while a run is in progress, or summarizes the last run's result when it's not. The table: title (with a **Retired** chip if applicable), type, parse status, size, warning count, section count, and per-row actions — **View** (opens the source's detail screen), **View run** (jumps to the ingest run that produced it), **Retire**. A section count of exactly 1 is flagged, because it usually means the source's text never split on real headings and became one undifferentiated section — a real signal worth checking, not a cosmetic warning. Retiring a source is explained plainly in its own confirmation dialog: the original file, normalized text, and evidence all stay on disk, and any still-active knowledge items mined from it just stop appearing in the default agent context. There's no un-retire button yet, but nothing is deleted. ![Sources screen: utility buttons above a table of every source with parse status, warnings, section count, and View/View run/Retire actions](images/desktop-ui/sources.png) ### Source detail Opened from a Sources row. The source's normalized text on the left (truncated by default, with a toggle to show it in full), its section table of contents on the right, and below both, every knowledge item mined from this source with a link into that item's review. ![Source detail screen: normalized text on the left, section table of contents on the right, evidence table of knowledge items below](images/desktop-ui/viewer.png) ## Knowledge Every mined knowledge item in the bundle, searchable across subject, predicate, object, or source text. A coverage bar up top shows what fraction of the bundle's sections have at least one knowledge item, with a list of any sections that still have none. The results table shows subject, predicate, object (truncated, full text on hover), review status, a confidence meter, and a link into that item's review. Search hits show fewer fields than the full list (no confidence, source text shown as "evidence" instead) since search results come from a different, lighter-weight lookup. ![Knowledge screen: search box and section-coverage bar above a table of subject/predicate/object/status/confidence](images/desktop-ui/knowledge.png) ### Review Opened from any knowledge item — Knowledge, Sources, or Concepts. The full item: subject, predicate, confidence, object, and source text, each individually editable; the relation as a plain sentence; any decision rules that apply; and the review actions — **Approve**, **Reject**, **Defer**, **Comment** — each requiring a short rationale, with every past action listed below as an immutable history (reviewer, timestamp, rationale). ![Review screen: the item's editable fields, review-action buttons with a rationale field, and the review history below](images/desktop-ui/review.png) !!! note "Review decisions can be changed at any time" Approving, rejecting, or deferring an item is never final — you can move it between those three states as many times as you need to, and every change is kept in the history below rather than overwriting it. Editing a field's value is the one action that stays locked once an item is approved or rejected; defer it first to reopen editing. ## Concepts Every concept — entity — the bundle's knowledge has been resolved into, as a grid of cards. Each card shows the concept's label, how many knowledge items and decision rules reference it, and a small pill per review status present among those items (e.g. "approved: 4"). ![Concepts screen: a grid of concept cards, each with item/rule counts and review-status pills](images/desktop-ui/concepts.png) ### Concept detail Opened from a Concepts card: every knowledge item tied to this concept (with a review link each) and every decision rule that applies to it. ![Concept detail screen: the concept's knowledge items on top, its decision rules below](images/desktop-ui/concept-detail.png) ## Agent A chat interface for asking scenario questions against the bundle's knowledge and decision rules, with separate, persisted chats and a choice of answer providers. - A left rail lists your chats (newest active first, titled from each chat's first question), with **+ New chat** and, once you have any history, **Clear all chat history**. - Each response shows which provider answered, a summary of how many knowledge items/concepts were used, and — for the tool-using provider — a collapsible trace of what it looked up before answering. - **Task context** pins which predefined scenario the next question draws from ("Auto" matches it automatically). - The composer has a **Provider** dropdown — `context` (no LLM call), `azure-llm`, or `azure-llm` with tool lookups — and a checkbox, **"Allow proposed/draft knowledge in the answer"**. ![Agent screen: chat list and task-context pins on the left, the conversation and composer (provider dropdown, proposed-knowledge checkbox) on the right](images/desktop-ui/agent.png) !!! note "The proposed-knowledge checkbox is a real filter, not a suggestion" Unchecking it excludes proposed/draft items from what's retrieved and answered from entirely, for every provider — not just a hint passed to the model. Leave it unchecked (the default) to keep answers grounded only in reviewed knowledge. !!! warning "Clearing chat history is bundle-wide" **Clear all chat history** deletes every chat's turns, not just the one you're currently viewing, and can't be recovered. ## Overview The bundle's landing dashboard — pinned at the very top of the sidebar, above the phase groups, since it's a dashboard rather than a workflow step. A row of stat tiles up top — sources (with a parse-status breakdown), knowledge items (with a review-status breakdown), concepts, and validation errors/warnings — each linking into the relevant screen; the validation tile jumps to the Validation tab below instead. Every number here is read from the same commands the other screens already call independently, so it always matches what they show. Below the tiles, a tab strip holds the bundle's generated reports (freshness, conflicts, extraction summary, review summary, validation) as rendered Markdown. A report that hasn't been generated yet for this bundle shows as dimmed and unavailable rather than being hidden. ![Overview screen: stat tiles for sources, knowledge items, concepts, and validation above a report tab strip and its rendered Markdown](images/desktop-ui/overview.png) ## Settings Configuration for LLM providers and app-wide preferences — the one screen reachable without any bundle open, since most of it isn't bundle-scoped. - **Reviewer name** and **parallel LLM requests** (how many sections/sources are sent to the LLM at once during Normalize and Mine; default 6) — simple saved preferences. - **Prompts reference** — read-only, shows the actual built-in prompt text used at each pipeline step. - **Bundle prompt overrides** — per-bundle mining/chat prompt overrides; each shows the built-in default it would replace, and wins over a profile-level override when set. - **LLM profiles** — create, edit, test, delete, and set a default among named provider profiles (base URL, model, auth, timeouts, reasoning effort, an API key field that's never pre-filled or shown unmasked, plus per-profile prompt overrides). A field currently overridden by an environment variable is shown dimmed with an explanation, since editing it here has no effect until that variable is unset. - **MCP invocation** — the exact command to expose the current bundle over MCP to an external agent host, with a copy button, plus per-client auto-configuration for MCP-capable tools detected on the machine (backing up any existing config entry with the same name first) or a manual snippet for ones that aren't auto-detected. - **Diagnostics** — exports a zip with app/OS info, the startup log, and a redacted settings summary for troubleshooting. It never includes API keys. ![Settings screen: reviewer name and worker-count fields, the prompts reference, and the LLM profiles list](images/desktop-ui/settings.png) ## Recovering from a broken workbench root If the app can't open a workbench root at all — the folder was moved, deleted, or its manifest is malformed — it shows a plain recovery screen instead of the sidebar and a broken view: the actual error, a field to point at a different folder (**Switch**, or **Browse…** for a native picker), and **Retry** to re-attempt the same root. ![Degraded recovery screen: no sidebar, a centered card with the actual error, a folder field, and Switch/Retry/Browse actions (illustrative wireframe, not a real screenshot)](images/desktop-ui/degraded.svg) ### MCP Server # MCP Server KL4A ships a built-in [Model Context Protocol](https://modelcontextprotocol.io/) server, so any MCP-capable agent or editor can connect straight to a bundle — no separate integration to build. ## `sopkb-mcp [--enable-review-notes]` `sopkb-mcp` is a standalone binary — there is no `sopkb-cli mcp` subcommand — that serves the Model Context Protocol tool surface over stdio (JSON-RPC), for connecting an MCP-capable agent/editor to a bundle. | Argument | Required | Default | Notes | |---|---|---|---| | `bundle_dir` | yes | — | | | `--enable-review-notes` | no | off (flag) | Without this flag, the mutating `review.note` tool is not advertised/callable and any attempt raises `review.note is disabled; start with --enable-review-notes`. All other tools are read-only by default. | This command doesn't open a network port — it's a stdio server: it reads one JSON-RPC request per line from stdin and writes one response per line to stdout. You don't run it by hand day to day; an MCP client spawns it as a subprocess and owns its stdin/stdout. Point your client's config at it: ```json { "mcpServers": { "kl4a": { "command": "sopkb-mcp", "args": ["/absolute/path/to/demo-bundle"] } } } ``` Use an absolute path for the bundle — the client launches the process from its own working directory, not the bundle's. `"command": "sopkb-mcp"` only resolves if `sopkb-mcp` is on the `PATH` the client's subprocess inherits, which isn't guaranteed for a build-from-source checkout; if it can't be found, point `command` at the built binary directly instead (e.g. `v2/sopkb-rust/target/debug/sopkb-mcp.exe` on Windows, `v2/sopkb-rust/target/debug/sopkb-mcp` on macOS/Linux). In Claude Code, the equivalent one-liner is: ```console $ claude mcp add kl4a -- sopkb-mcp /absolute/path/to/demo-bundle ``` The piped example below drives the same protocol by hand — useful for verifying the server works before wiring up a client, not the day-to-day usage path. Real captured output, run against a one-line "New hires must confirm identity before systems access is granted" demo bundle: ??? example "Example — piping two JSON-RPC requests over stdin" ```console $ printf '%s\n%s\n' \ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \ '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"bundle.describe","arguments":{}}}' \ | sopkb-mcp demo-bundle ``` ```json {"id": 1, "jsonrpc": "2.0", "result": {"capabilities": {"tools": {}}, "instructions": "Ground every answer only in what these tools return — never in general/internet/training-data knowledge, even when labeled as such. Call knowledge.search (or agent.context) first; if nothing relevant comes back, say explicitly that this knowledge base has no grounded answer for that part instead of filling the gap. Always show the actual facts too: alongside any summary or paraphrase, quote the raw evidence/source_text returned by knowledge.search or evidence.get verbatim, and cite the knowledge item, section, or source it came from. If a knowledge.search result carries rule_ids, or knowledge.get/agent.context shows a decision_rules entry, that item is governed by a structured condition/obligation/otherwise rule — fetch it (knowledge.get for the item, or agent.context for the task) and apply that rule's logic wherever it's applicable to the question, rather than answering from the prose evidence alone.", "protocolVersion": "2024-11-05", "serverInfo": {"name": "sopkb", "version": "0.0.1-alpha"}}} {"id": 2, "jsonrpc": "2.0", "result": {"content": [{"text": "{\n \"id\": \"demo-bundle\",\n \"knowledge_item_count\": 1,\n \"profile\": \"sop-knowledge-bundle\",\n \"source_count\": 1,\n \"status\": \"draft\",\n \"title\": \"Demo Bundle\"\n}", "type": "text"}]}} ``` (one JSON-RPC response object per line, in request order — note the real `initialize` response also carries an `instructions` string laying out the grounding contract for the connecting agent, not shown in earlier drafts of this page) The same read-only functions are also exposed as plain `sopkb-cli` subcommands (`knowledge search`, `agent context`, `relations search`, ...), callable outside an MCP client. ### Architecture Overview # Architecture Overview This is a short, public-facing tour of how KL4A fits together. For full detail — the product requirements, the implementation design, and the normative bundle spec — see the deeper docs linked at the end of each section; this page intentionally does not duplicate them. ## The shape of the system ```mermaid flowchart TD A["Source documents
(.md, .txt, .docx, .pdf)"] -- "sopkb-cli scan" --> B["Inventory
(checksummed originals)"] B -- "sopkb-cli normalize" --> C["Normalized Markdown
+ sections"] C -- "sopkb-cli mine
--provider fixture | azure-llm" --> D["Proposed knowledge items
(evidence-linked)"] D -- "sopkb-cli review
approve | reject | defer | comment | edit" --> E["Reviewed knowledge"] E -- "sopkb-cli validate" --> F["Validation / freshness
/ conflict reports"] F -- "sopkb-cli export
--format ..." --> G["OKF-native bundle
(canonical)"] G --> H["Graph JSON / RDF-TTL
(derivative)"] G --> I["Desktop app / sopkb-server
(browse, review, ingest,
agent chat)"] G --> J["sopkb-mcp
(MCP server:
read-only agent tool surface)"] classDef box stroke-width:1.5px,rx:8,ry:8; class A,B,C,D,E,F,G,H,I,J box; ``` ??? note "Diagram as a linear list (for screen readers, or if you copied the diagram's text)" Copying text out of a Mermaid diagram (or reading it with a screen reader) pulls out node labels and edge labels as two separate groups, not in visual reading order. Here's the same pipeline top to bottom: 1. **source documents** (.md, .txt, .docx, .pdf) 2. → `sopkb-cli scan` → **inventory** (checksummed originals) 3. → `sopkb-cli normalize` → **normalized Markdown + sections** 4. → `sopkb-cli mine --provider fixture|azure-llm` → **proposed knowledge items** (evidence-linked) 5. → `sopkb-cli review` → **reviewed knowledge** 6. → `sopkb-cli validate` → **validation / freshness / conflict reports** 7. → `sopkb-cli export --format ...` → **OKF-native bundle** (canonical), which then feeds three things in parallel: - **Graph JSON / RDF-TTL** (derivative) - the desktop app, or `sopkb-server` for a browser-based deployment (browse, review, ingest, agent chat) - `sopkb-mcp` (MCP server: read-only agent tool surface) !!! note "No database. Network calls depend on which surface you use, and which provider it defaults to." Everything left of `sopkb-server`/`sopkb-mcp` is implemented as a plain CLI pipeline over files on disk — there is no database anywhere in this path. Whether a network call happens depends on the mining/agent provider, and **both surfaces lean toward the network-dependent path by default**: - **CLI** (`sopkb-cli mine`, no `--provider` given): defaults to `azure-llm` — it calls Azure OpenAI. Pass `--provider fixture` for a zero-dependency, offline run. (`sopkb-cli normalize` is the exception: it does default to `fixture`.) - **Desktop app's Ingest sources screen**: the **Mining provider** dropdown defaults to `azure-llm` once a default LLM profile is configured on the Settings screen; with no profile configured it stays on `fixture`. Both fail closed (they error rather than silently proceeding) if the profile's credentials aren't set, so there's no silent leak absent configuration. Pick `fixture` explicitly (CLI flag or dropdown) for a fully offline run. ## Bundle store A **SOP Knowledge Bundle** is a directory created by `sopkb-cli init`: a fixed set of subdirectories (`sources/`, `sections/`, `concepts/`, `knowledge/`, `relations/`, `rules/`, `evidence/`, `tasks/`, `references/`, `authored/`, `reports/`) plus a `manifest.yaml`. The bundle root itself is the canonical, OKF-compliant artifact — Markdown documents with YAML frontmatter, cross-linked to each other. A `.sopkb/` subdirectory holds implementation state (JSON indexes, upload staging, caches) that is derived from, and re-synced into, the canonical Markdown on every mutating command. → Full normative shape: [`OKF_BUNDLE_SPEC.md`](OKF_BUNDLE_SPEC.md). ## Mining / extraction `sopkb-cli mine` turns normalized section text into **proposed knowledge items**, each an evidence-linked subject/predicate/object claim with a source span, confidence score, and `review_status: proposed`. Two providers exist today: | Provider | Default | Implementation | Dependencies / network | Behavior | |---|---|---|---|---| | `fixture` | Opt-in on the CLI (`--provider fixture`); in the desktop app's Ingest sources screen it's what the dropdown falls back to when no LLM profile is configured. | `v2/sopkb-rust/crates/sopkb-mining/src/mine_fixture.rs` | Zero dependencies, deterministic, offline | Regex-based obligation-sentence detection | | `azure-llm` | Yes on the CLI (`sopkb-cli mine`'s `--provider` default), and in the desktop app's Ingest sources screen once an LLM profile is configured on the Settings screen. | `v2/sopkb-rust/crates/sopkb-mining/src/okf_author.rs` | Azure OpenAI's Responses API | LLM-authored path that also emits full OKF documents (concepts, decision rules) alongside knowledge items | Both write the same underlying `KnowledgeItem` shape, so downstream review, export, and agent consumption are provider-agnostic. This mining-provider axis is unrelated to how the desktop app's **Agent** screen evaluates a scenario against already-mined knowledge — that's a separate call, not a user-facing provider choice, and not how knowledge is *extracted*. See [DESKTOP_UI_GUIDE.md](DESKTOP_UI_GUIDE.md#agent). ## Review Human-in-the-loop review (`sopkb-cli review`, or the Review panel on the desktop app's Knowledge screen) is first-class, not a preview feature: approve, reject, defer, comment, and edit actions are all persisted as review events with reviewer identity and rationale (`v2/sopkb-rust/crates/sopkb-review/src/review.rs`). Approved and rejected are terminal states. Review state flows directly into validation reports and into `has_review` edges in graph exports — there's no separate publish step. ## Export `sopkb-cli export` re-syncs the canonical OKF bundle and additionally writes derivative formats — Graph JSON and RDF/Turtle — under a sibling `exports/` directory (`v2/sopkb-rust/crates/sopkb-export/src/bundle_export.rs`, with `graph.rs` and `rdf.rs` for the derivative formats). The OKF bundle itself never requires "exporting" to be useful; these are additional representations for graph tooling and the enterprise import path. ## Web server and MCP server The desktop app is the primary UI and calls these crates directly through Tauri commands — no HTTP, no sidecar process. For a browser-based deployment there's `sopkb-server` (`v2/sopkb-rust/bin/sopkb-server`), an axum app that serves the same frontend plus the full pipeline, review, and agent chat over HTTP — bound to `127.0.0.1:4173` by default and gated behind a generated token. `sopkb-mcp` (`v2/sopkb-rust/bin/sopkb-mcp`) — a standalone binary, not a `sopkb-cli` subcommand — exposes a read-only-by-default Model Context Protocol tool surface (bundle/sources/sections/knowledge/evidence/conflicts/freshness/citations/agent/relations) over JSON-RPC/stdio, with an explicit `--enable-review-notes` opt-in for the one mutating tool. → Desktop app screens: [`DESKTOP_UI_GUIDE.md`](DESKTOP_UI_GUIDE.md). → MCP server: [`MCP_SERVER.md`](MCP_SERVER.md). ## Agent consumption The `sopkb-agent` crate (`v2/sopkb-rust/crates/sopkb-agent`) provides task-scoped context retrieval (`agent.context`, `agent.tasks`, `agent.guide`) and RDF-compatible relation traversal (`relations.search`, `relations.neighborhood`), usable identically from the CLI, the desktop app's Agent screen, or MCP. So an agent gets the same evidence-grounded, review-aware context regardless of integration surface. ## Where this stops !!! note "Out of scope" This project owns bundle **creation and export**. It does not implement multi-tenant governance, RBAC, audit trails, or hosted APIs at organizational scale — that boundary, and why it's drawn there, is covered in [Governance](GOVERNANCE.md). ## Further reading - [`OKF_BUNDLE_SPEC.md`](OKF_BUNDLE_SPEC.md) — the normative bundle shape. ### FAQ # FAQ / Troubleshooting This page covers the desktop app specifically — for CLI-only usage, error text may differ slightly since the CLI and the app resolve settings through the same underlying config layer but surface errors differently. ## Getting started ### The bundle picker says "No bundles found in this workbench root." or "Could not load bundles" The app only recognizes a **Workbench root** — a folder whose `knowledge-bundles/` subdirectory contains one or more bundles (`/knowledge-bundles//`). Selecting a folder that has no `knowledge-bundles/` subdirectory populated with bundles (including a bundle directory itself, or `knowledge-bundles/` directly instead of its parent) produces the empty state — "No bundles found in this workbench root." — not an error, since the scan itself succeeded and just found nothing. **"Could not load bundles"** is a different, harder failure — the bundle listing call itself failed — worth reporting as a bug if you hit it. ## Ingesting sources ### A `.docx` or `.pdf` source fails to ingest, or shows no extracted content Both formats are supported by the desktop app. If ingestion fails outright, that's worth reporting as a bug. If it succeeds but the source ends up with no usable content, the source is marked with a parse failure and a warning rather than aborting the whole ingest run — check the **Sources** screen for the source's warning text, which will read one of: - `PDF text extraction produced no content` - `DOCX text extraction produced no content` This means the file parsed, but no text could be pulled from it — the most common cause is a scanned or image-only PDF (no OCR is performed) or an empty/corrupt document. Markdown/plain-text sources never hit this path. ## Mining and LLM setup ### Ingest screen shows "No LLM provider configured yet — set one up in Settings to enable LLM-based mining." The **Mining provider** dropdown on the Ingest screen defaults to `azure-llm` once an LLM profile exists, but falls back to `fixture` — and shows this message instead of the dropdown — when no usable profile is configured yet. **The fastest fix is usually to avoid this entirely.** Leave the provider on **fixture**: zero setup, no key, no network call. It extracts obligation-shaped sentences with plain pattern matching. (Only `fixture` and `azure-llm` are valid providers — the dropdown never offers a third option, so you can't hit an "invalid provider" error from the UI; it only surfaces if you're scripting directly against `sopkb-cli`.) If you do want LLM-based mining: open **Settings** → **LLM profiles** → **+ New profile**, and fill in **Name**, **Base URL**, and **Model** (all three are required — the Save button stays disabled until they're non-blank), plus **Auth style**, **Max output tokens**, **Timeout (seconds)**, **Reasoning effort**, and **API key** as needed. Use **Test** on the saved profile to verify the connection before mining against it. One thing worth knowing about precedence: a field with an **"env override active"** badge next to it (shown on Base URL and API key) means an environment variable is currently overriding whatever you type there — editing it in the UI has no effect until that environment variable is unset. Env vars always win over a saved profile value. ## Review ### The Approve/Reject/Defer/Edit buttons are greyed out on a knowledge item Once a knowledge item has been **approved** or **rejected** on the Review screen, that status is terminal by design — the app disables those actions based on the item's `allowed_actions` rather than letting you attempt one and fail. Only **comment** stays available on a terminal item. This is intentional: it keeps a reviewed item's history unambiguous. If you need to revise an approved/rejected item, that's a deliberate re-ingest decision, not a review action — re-run mining on the source to regenerate the underlying knowledge item. (The backend error behind this, if you're scripting against `sopkb-cli` instead: `cannot change terminal review status: approved`.) ## Settings and data ### Where are my saved settings and API key actually stored? `~/.sopkb/settings.json` (override the location with the `SOPKB_SETTINGS_PATH` environment variable — the Settings screen's intro text states the actual path in effect). The API key is stored in plaintext there, not encrypted; the file is chmod'd `0600` (owner read/write only) on macOS/Linux, but this tightening doesn't happen on Windows — there's no equivalent step in the code for that platform. --- Found a gap that's not on this page? Please [open an issue](https://github.com/CogniSwitch/KL4A/issues/new/choose). ## Reference ### OKF Bundle Spec # KL4A OKF Bundle Spec Status: draft Spec version: 0.2.0 Target OKF version: 0.2

OKF — Open Knowledge Format

an open standard published by Google Cloud

OKF is not a format invented by this project. This document's bundle shape is built on OKF's core model — YAML-frontmatter Markdown documents and the same `okf_version` root-declaration mechanism defined in Google's spec — and extends it with KL4A-specific fields kept under this project's own `sopkb` namespace, per OKF's own extension rules (producers may add unknown keys; consumers must preserve them). This is not a claim of full drop-in conformance with every field Google's spec defines (for example, this document's `generated.actor`/`generated.date` fields use different key names than OKF's `generated.by`/`generated.at`, and this bundle's directory layout is more prescriptive than OKF's directory-agnostic model) — it is a deliberate alignment with a real external standard's core mechanism, not merely a shared name. This document specifies the canonical KL4A bundle shape on top of that standard. OKF is not merely an export format. Exports are for additional representations such as Graph JSON, RDF/Turtle, package archives, or downstream system-specific formats. ## 1. Design Principle !!! abstract "Design Principle" Everything provided as a KL4A knowledge bundle MUST be OKF-compliant. The workbench MAY maintain implementation indexes, caches, upload staging, and run logs, but those implementation artifacts MUST NOT be the canonical knowledge bundle. They MUST either: - be derived from the OKF documents; - live under an implementation namespace such as `.sopkb/`; or - be explicitly marked as non-canonical runtime state. ## 2. Terms OKF bundle : The canonical KL4A directory containing Markdown documents with YAML frontmatter, cross-links, evidence, relations, rules, and agent task contexts. Implementation state : Derived JSON indexes, caches, upload staging, validation logs, UI chat history, and temporary files used by the workbench. Knowledge piece : A reviewable assertion mined or authored from source evidence. Knowledge Relation : An RDF-compatible subject-predicate-object assertion connected to a knowledge piece and evidence span. Decision rule : A task-usable rule derived from or attached to a knowledge piece. Evidence : A source span supporting a knowledge piece, Knowledge Relation, and any derived rule. Normative keywords such as **MUST**, **SHOULD**, and **MAY** are used intentionally. ## 3. Canonical Bundle Shape The canonical bundle root is the bundle directory itself: ```text sop-knowledge-bundle/ index.md manifest.yaml log.md sources/ index.md .md originals/ normalized/ sections/ index.md / .md concepts/ index.md .md knowledge/ index.md .md relations/ index.md .md rules/ index.md .md evidence/ index.md .md tasks/ index.md .md references/ index.md agent-guide.md authored/ index.md ... reports/ validation.md freshness.md conflicts.md extraction_summary.md review_summary.md .sopkb/ inventory.json sections.json items.json entities.json triples.json reviews.json llm_authoring.json agent_chat.json source_versions.json source_events.json document_contexts.json uploads/ cache/ ``` Rules: | Path | Rule | |---|---| | `index.md`, `manifest.yaml`, and the OKF document directories | Canonical. | | `sources/originals/` and `sources/normalized/` | MAY be included for provenance and reproducibility. | | `reports/` | SHOULD contain human-readable Markdown reports. | | `.sopkb/` | Implementation state. SHOULD be derivable from canonical OKF documents where possible. | Workbench-local bundle registries SHOULD use this directory shape: ```text workbench/ knowledge-bundles/ / manifest.yaml index.md ... exports/ / graph/ graph.json triples.ttl export_summary.md ``` `workbench/knowledge-bundles//` is the OKF-native bundle. `workbench/exports//` contains derivative exports and is not the primary OKF model. ## 4. Export Semantics !!! note "Export is not what makes a bundle OKF" `sopkb-cli export` MUST NOT be required to create an OKF bundle. The bundle is already OKF. `sopkb-cli export` is reserved for derivative or packaged representations. Implemented today: ```text sopkb-cli export --format graph-json sopkb-cli export --format rdf ``` (`zip`/package and other downstream-specific formats are anticipated by this spec's design but not yet implemented — passing an unrecognized format token is silently ignored rather than erroring.) Export lands in a sibling `exports/` directory next to the bundle, not inside it — ``'s parent gets an `exports//` subdirectory (or, if the bundle sits under a `knowledge-bundles/` folder, the export lands under that folder's own parent instead, keeping `exports/` and `knowledge-bundles/` as siblings): ```text exports//graph/graph.json exports//graph/triples.ttl exports//export_summary.md ``` An `okf` export MAY exist only as a packaging/copy operation, not as the step that creates OKF compliance. ## 5. Common Markdown Document Contract Every canonical non-index Markdown document SHOULD include YAML frontmatter followed by a human-readable Markdown body. Common frontmatter fields: ```yaml type: SOP Knowledge Piece title: Human title description: Short description resource: relative-or-local-resource tags: [] status: stable generated: actor: sopkb/0.0.1 date: "2026-07-31" sources: - id: src-... title: Source title resource: ../sources/.md sopkb: {} ``` Rules: | Field | Requirement | Description | |---|---|---| | `type` | MUST | Identify the document class. | | `title` | MUST | Be human readable. | | `resource` | SHOULD | Point to the primary related resource. | | `tags` | SHOULD | Include useful query/filter labels. | | `status` | SHOULD | Be one of `stable`, `draft`, or `deprecated`. | | `generated.actor` / `generated.date` | SHOULD | Identify the generator. | | `sources` | SHOULD | Be present when a document is traceable to source material. | - KL4A extensions MUST live under the `sopkb` namespace. - Unknown frontmatter fields MUST be preserved by tools that update OKF documents. ## 6. Root Index `index.md` MUST declare the OKF version: ```yaml --- okf_version: "0.2" --- ``` The body MUST link to: - `sources/index.md` - `sections/index.md` - `concepts/index.md` - `knowledge/index.md` - `relations/index.md` - `rules/index.md` - `evidence/index.md` - `tasks/index.md` - `references/agent-guide.md` It SHOULD include a bundle summary with source, section, and knowledge-piece counts. ## 7. Manifest `manifest.yaml` MUST describe the OKF bundle and available derivative exports. Example: ```yaml id: glp1-healthcare-sop version: 0.0.1 title: GLP-1 Healthcare SOP Bundle profile: sop-knowledge-bundle profile_version: 0.2.0 okf_version: "0.2" status: draft created_at: "2026-07-29T00:00:00Z" updated_at: "2026-07-29T00:00:00Z" sources: - id: primary-care-sop-glp1 type: docx path: sources/primary-care-sop-glp1.md exports: - type: rdf path: ../exports/glp1-healthcare-sop/graph/triples.ttl - type: graph_json path: ../exports/glp1-healthcare-sop/graph/graph.json ``` The manifest MUST NOT list OKF as an export required for normal bundle use. ## 8. Source Documents Path: ```text sources/.md ``` Type: ```yaml type: SOP Source ``` Required `sopkb` fields: ```yaml sopkb: source_id: checksum: sha256:... original_path: sources/originals/ normalized_path: sources/normalized/__v.md mime_type: null size_bytes: null # Source-versioning fields (immutable-source-versioning feature): source_version_id: __v active_version_id: __v version_number: 1 versions: [__v1, ...] lifecycle_status: active ``` `normalized_path` is version-qualified (`__v.md`), not a flat `.md` — each new source version normalizes to its own file rather than overwriting the previous one. The body MUST include: - links to normalized section documents derived from the source; - links to knowledge pieces derived from the source. ## 9. Section Documents Path: ```text sections//.md ``` Type: ```yaml type: SOP Section ``` Required `sopkb` fields: ```yaml sopkb: section_id: source_id: ordinal: 1 normalized_path: sources/normalized/__v.md # Source-versioning fields: source_version_id: __v lifecycle_status: active ``` The body MUST include: - a link back to the source document; - links to knowledge pieces mined from the section; - a source excerpt. ## 10. Knowledge Piece Documents Path: ```text knowledge/.md ``` Type: ```yaml type: SOP Knowledge Piece ``` Required `sopkb` fields: ```yaml sopkb: knowledge_item_id: source_id: section_id: review_status: proposed confidence: 0.7 span_status: exact evidence: ../evidence/.md knowledge_relation: ../relations/.md decision_rules: - ../rules/.md structured_statement: subject: Tirzepatide predicate: is_deferred_to object: Endocrinology # Source-versioning / knowledge-lifecycle fields: source_version_id: __v lifecycle_status: active supersedes: null superseded_by: null ``` The body MUST include: - a structured statement table; - a link to the subject concept; - a link to evidence; - a link to the Knowledge Relation; - links to decision rules when present; - source context with citation text. Review status mapping: | `review_status` | Mapped `status` | |---|---| | `proposed` | `draft` | | `deferred` | `draft` | | `approved` | `stable` | | `edited` | `stable` | | `rejected` | `deprecated` | Human review metadata SHOULD be represented with `verified` frontmatter when a knowledge piece is approved or edited. ## 11. Knowledge Relation Documents Path: ```text relations/.md ``` Type: ```yaml type: SOP Knowledge Relation ``` Required `sopkb` fields: ```yaml sopkb: relation: id: type: Knowledge Relation subject: id: label: Tirzepatide text: Tirzepatide okf_path: concepts/.md predicate: id: predicate-is-deferred-to text: is_deferred_to object: id: object-endocrinology text: Endocrinology label: Endocrinology knowledge_piece_id: evidence_id: review_status: proposed confidence: 0.7 rdf_compatible: true ``` The body MUST include: - the subject, predicate, and object assertion; - a link to the connected knowledge piece; - a link to evidence; - links to decision rules when present. Knowledge Relations are the OKF-wrapped RDF compatibility layer. They MUST remain connected to their supporting knowledge piece and evidence. ## 12. Decision Rule Documents Path: ```text rules/.md ``` Type: ```yaml type: SOP Decision Rule ``` Required `sopkb` fields: ```yaml sopkb: rule: id: title: Rule title type: SOP Decision Rule condition: fact: agent_is_tirzepatide label: Agent is tirzepatide operator: is_true obligation: action: defer_to_endocrinology fact: tirzepatide_deferred_to_endocrinology label: Tirzepatide is deferred to Endocrinology knowledge_item_id: source_id: section_id: review_status: proposed confidence: 0.7 evidence_id: relation_id: okf_path: rules/.md knowledge_piece: ../knowledge/.md knowledge_relation: ../relations/.md evidence: ../evidence/.md ``` The body MUST include: - the condition when present; - the obligation; - the review status; - links to the connected knowledge piece, Knowledge Relation, and evidence. ## 13. Evidence Documents Path: ```text evidence/.md ``` Type: ```yaml type: SOP Evidence ``` Required `sopkb` fields: ```yaml sopkb: knowledge_item_id: source_id: section_id: span_status: exact start_pos: 650 end_pos: 735 ``` The body MUST include: - the evidence span; - links to the supported knowledge piece and Knowledge Relation. ## 14. Concept Documents Path: ```text concepts/.md ``` Type: ```yaml type: SOP Concept ``` Required `sopkb` fields: ```yaml sopkb: concept_id: ``` The body MUST include: - links to related knowledge pieces; - links to related Knowledge Relations; - links to source sections when available. Concepts are cross-source graph anchors. If the same concept appears across multiple source documents, the concept document SHOULD link to all related knowledge pieces and relations. ## 15. Agent Task Documents Path: ```text tasks/.md ``` Type: ```yaml type: SOP Agent Task Context ``` Required `sopkb` fields: ```yaml sopkb: task_id: eligibility-check query_terms: - eligibility - identity - contraindication - clinical review agent_cli: sopkb agent context --task eligibility-check ``` The body MUST describe how an agent retrieves task context and uses returned Knowledge Relations and evidence. ## 16. Agent Guide Path: ```text references/agent-guide.md ``` Type: ```yaml type: SOP Agent Guide ``` The guide MUST state: - use the bundle as read-only unless a human review workflow enables writes; - retrieve task-scoped context through CLI or MCP; - resolve evidence before making claims; - treat Knowledge Relations as RDF-compatible assertions connected to evidence; - do not infer human approval from generated/proposed knowledge. ## 17. RDF and Graph Derivatives Graph JSON and RDF/Turtle are derivative exports from the OKF bundle: ```text workbench/exports//graph/ graph.json triples.ttl ``` `triples.ttl` MUST model Knowledge Relations as RDF-compatible assertions and SHOULD include: - `sopkb:KnowledgeRelation` - `sopkb:Concept` - `sopkb:RelationObject` - links to knowledge pieces; - links to evidence; - review status; - decision rules when present. ## 18. Validation Expectations An OKF bundle SHOULD pass these structural checks: - required canonical directories exist; - root `index.md` declares `okf_version`; - every non-index Markdown document has frontmatter with `type`; - knowledge pieces link to evidence and a Knowledge Relation; - relations are marked `rdf_compatible: true`; - concepts link back to knowledge and relations; - decision rules link back to knowledge, relation, and evidence; - agent guide exists; - implementation state under `.sopkb/` does not override canonical OKF documents; - no canonical document depends on a live LLM or hosted service to be read. ## 19. Implementation State The implementation now materializes the OKF Markdown tree at the bundle root and writes derived JSON indexes and upload staging under `.sopkb/`. Implementation rules: 1. Generate the OKF Markdown tree at the bundle root. 2. Keep implementation JSON files and upload staging under `.sopkb/`. 3. Keep `sources/originals/` and `sources/normalized/` as provenance assets. 4. Make CLI, web, MCP, and agent APIs read canonical OKF documents or `.sopkb` indexes derived from them. 5. Keep derived JSON indexes as caches that can be rebuilt from OKF. 6. Reserve `sopkb-cli export` for `graph-json`, `rdf`, archive/package, and downstream-specific formats. ## 20. Implementation Mapping Target implementation entry points: | Component | Path | Notes | |---|---|---| | Bundle creation | `v2/sopkb-rust/crates/sopkb-workbench/src/bundles.rs`, `.../ingest.rs` | | | OKF document writer | `v2/sopkb-rust/crates/sopkb-export/src/sync.rs` | `sync_okf_bundle()` writes the canonical OKF tree directly at the bundle root (`export_dir = bundle_dir`) — this is done, not pending. | | Agent consumption layer | `v2/sopkb-rust/crates/sopkb-derive/src/context.rs` | | | MCP read-only layer | `v2/sopkb-rust/bin/sopkb-mcp/src/` (`jsonrpc.rs`, `tools.rs`) | | | Structural tests | `v2/sopkb-rust/crates/sopkb-export/tests/phase5_v1_diff.rs`, `.../sopkb-derive/tests/phase4_v1_diff.rs` | Byte-level differential tests against the frozen reference output checked into the fixtures tree. | ### Bundle Compatibility Policy # Bundle Compatibility Policy ## 1. Why This Is Separate From Software SemVer `sopkb` (the software) and the SOP Knowledge Bundle / OKF-based bundle format (the artifact) are versioned independently, on purpose. The bundle is meant to be a **durable artifact**. Once someone builds a bundle: - reviews it - checks it into Git - hands it to an agent - exports it toward an enterprise import path That bundle needs to keep working, keep being readable, and keep being loadable by the tools that produced it, largely independent of how fast the `sopkb` software itself is moving. If bundle-format compatibility were tied to the software's SemVer number, a routine `0.0.1 -> 0.1.0` software release (which, pre-1.0, carries no strong compatibility guarantee at all per `docs/RELEASE_PROCESS.md`) could silently invalidate every bundle a user has already built. That is the outcome this policy exists to prevent: !!! warning "The rule this policy enforces" A minor software version bump must never silently break an existing bundle's schema. Any bundle-breaking change must be a deliberate, documented, versioned event in the bundle format's own numbering — not a side effect of a software release. ## 2. Current Bundle Format Version The canonical bundle shape is specified in `docs/OKF_BUNDLE_SPEC.md`. As of this writing, that document states: ```text Status: draft Spec version: 0.2.0 Target OKF version: 0.2 ``` That spec is explicitly marked `draft` and is expected to keep evolving prior to a 1.0 bundle-format release, independent of the `sopkb` software version (currently `0.0.1`). Manifests already carry their own `profile_version` field (see `manifest.yaml`'s `profile: sop-knowledge-bundle` / `profile_version` in `docs/OKF_BUNDLE_SPEC.md` Section 7), separate from `okf_version` and from the software version recorded under `generated.actor` (e.g. `sopkb/0.0.1`). ## 3. Versioning Scheme for the Bundle Format The SOP Knowledge Bundle format has its own `MAJOR.MINOR` version, independent of the `sopkb` software's SemVer: ```text bundle format version: MAJOR.MINOR ``` There is no `PATCH` component: bundle-format changes are structural (directory layout, frontmatter contract, required fields, id semantics), not the kind of thing that has a meaningful patch-level fix distinct from a minor revision. A change either alters the schema (bump `MINOR` or `MAJOR`) or it doesn't (no version change, e.g. wording-only spec clarifications that don't change what a valid bundle looks like). | Bump | Meaning | Examples | |------|---------|----------| | **`MINOR`** | Backwards-compatible bundle-format change. Existing bundles at the previous minor version remain valid and readable by tooling that supports the new minor version. | Adding a new optional frontmatter field; adding a new optional document type; adding a new `reports/` file. | | **`MAJOR`** | Breaking bundle-format change. A bundle built under the old major version is not guaranteed to validate or be consumable as-is under tooling that only supports the new major version without migration. | Renaming/removing a required frontmatter field; changing the canonical directory shape; changing id derivation rules; changing what `rdf_compatible: true` implies structurally. | This bundle-format version is recorded today as the `Spec version` field in `docs/OKF_BUNDLE_SPEC.md` and should also be reflected in each bundle's `manifest.yaml` via its `profile_version` field, so a bundle is self-describing about which schema revision it was written against. The separate `okf_version` field tracks alignment with the external Open Knowledge Format standard and is not the same axis as `profile_version`; both may need to be read together when reasoning about compatibility. ## 4. Breaking-Change Policy !!! danger "Breaking change — requires a `MAJOR` bump" A bundle-format change is a breaking change if it would cause any of the following for a bundle that validated successfully under the previous version: - A required canonical directory or file (e.g. `index.md`, `manifest.yaml`, a document under `knowledge/`, `evidence/`, `relations/`) is removed, relocated, or renamed. - A required `sopkb` frontmatter field for an existing document type is removed, renamed, or given a different meaning. - A previously valid document would fail bundle validation (`sopkb-cli validate`) under the new spec without modification. - The semantics of an existing field change such that old and new bundles disagree on meaning for the same field name (e.g. a status enum value is redefined rather than extended). - id derivation for `source_id`, `knowledge_item_id`, `concept_id`, etc. changes such that previously generated ids no longer resolve consistently. !!! success "Non-breaking change — `MINOR` bump, or no bump" A change is non-breaking if it only adds optional structure that old bundles simply don't have yet, or clarifies wording without changing what a conformant bundle must contain. Any change proposed against `docs/OKF_BUNDLE_SPEC.md` should be classified against this list as part of its review, and the `Spec version` header in that document should be updated accordingly in the same change. ## 5. Migration Note Requirement !!! warning "Migration note required for every `MAJOR` bump" Every breaking (`MAJOR`) bundle-format change MUST ship with a migration note. Concretely: - A short Markdown migration note describing: - what changed - why - which bundles are affected (by prior bundle-format version) - the concrete steps (manual or via a `sopkb-cli migrate`-style tool, once one exists) to bring an existing bundle up to the new format version - The migration note should live alongside the bundle-format history (for example under a `docs/bundle-migrations/` directory, added when the first breaking change actually happens) and should be linked from the updated `docs/OKF_BUNDLE_SPEC.md`. - The corresponding software release notes (`docs/releases/.md`, see `docs/RELEASE_PROCESS.md`) should call out that a bundle-format breaking change shipped in that release and link to the migration note. No `MAJOR` bundle-format bump should land without this note. A `MINOR` bump does not require a migration note, since existing bundles remain valid. ## 6. Relationship to Software Releases - A software release (`sopkb` version bump per `docs/RELEASE_PROCESS.md`) and a bundle-format version bump are independent events. A software patch or minor release can ship with no bundle-format change at all. - When a software release does change the bundle-format version, that must be stated explicitly in that release's notes under `docs/releases/`, including the old and new bundle-format version and whether it was a `MINOR` (non-breaking) or `MAJOR` (breaking, migration note required) bundle-format bump. - Software pre-1.0 status (see `docs/RELEASE_PROCESS.md`) does not relax this policy. Even while `sopkb` is `0.x`, bundle-format breaking changes still require a bundle-format `MAJOR` bump and a migration note — the two version numbers are deliberately decoupled in both directions. ## 7. Pre-1.0 Bundle Format Expectations The bundle format is currently pre-1.0 (`0.2.0` per `docs/OKF_BUNDLE_SPEC.md`, status `draft`). Users should expect the schema may still shift as the format matures toward a `1.0` bundle-format release, at which point the compatibility guarantees in Section 4 above become the project's durable commitment. Until then, breaking changes are still governed by this policy (classified, versioned, and given a migration note) — "pre-1.0" describes how much change to expect, not a waiver of the process for making that change. ## Release Notes ### v0.0.1 # KL4A v0.0.1 **This is the initial public release of KL4A.** It is being published for the first time as an open-source project, and this document is written for people encountering it that way — not as changelog entry #13 of an internal tool. Everything below has been built and exercised against an internal milestone test suite ahead of this release, so the project is not starting from a blank slate. But this is the first time it is being handed to anyone outside the team that built it. If you're new here: KL4A is a local-first tool for turning enterprise SOPs, policies, and procedures into structured, reviewable "SOP Knowledge Bundles" — plain files on disk, readable by humans, git- friendly, and consumable by AI agents — with a human-in-the-loop review step between "the model proposed this" and "this is trusted knowledge." ## What's in v0.0.1 **Bundle lifecycle.** `sopkb-cli init` creates a bundle with a manifest and the standard source/section/concept/knowledge directory layout. `sopkb-cli scan` inventories markdown, DOCX, and PDF source documents with stable, checksum-backed source ids, and cleans up entries for files that have since disappeared. `sopkb-cli normalize` splits normalized source text into sections. `sopkb-cli validate` checks manifest and bundle integrity. **Human-in-the-loop review.** `sopkb-cli review` supports approving, rejecting, deferring, commenting on, and editing mined knowledge items. Every action is recorded as a review event with a reviewer, a rationale, and a before/after diff when something is edited. Once an item is approved or rejected, it's terminal — no further mutating actions apply to it — and edits are restricted to an allow-listed set of fields. Review state shows up both in validation reports and as `has_review` edges in graph exports, so "what got approved and by whom" is never just implicit in a UI. **A local web workbench.** Beyond the CLI, `sopkb` ships a local HTTP app covering: - sources - ingest - a document viewer - knowledge browsing - concepts - review - an agent-chat surface - reports - a graph view - export — all scoped to a bundle. Ingest works from either a source folder or direct upload. A multi-bundle index page lists everything under a workbench root. Nothing here requires a hosted backend. **A real reference bundle, not a toy.** `examples/glp1-healthcare` is an end-to-end, buildable bundle that runs the full pipeline: - scan - normalize - mine - review (with approvals, rejections, deferrals, and edits) - validate - export to graph JSON and RDF — over its markdown sources, including freshness metadata and conflict reporting. (DOCX and PDF ingestion is supported by `scan`/`normalize`; this checked-in bundle just doesn't include binary sources.) It's meant to be a credible example of what a finished bundle looks like, not a synthetic demo. **An MCP server.** `sopkb-mcp` exposes a read-only-by-default Model Context Protocol tool surface: - `bundle.describe` - `knowledge.search` - `evidence.get` - `agent.context` - `relations.search` - `agent.guide` — plus a JSON-RPC `tools/call` handler. Mutating tools like `review.note` stay disabled unless a host explicitly turns them on. Calling an unknown tool returns a proper JSON-RPC error rather than failing silently. This is the project's most direct answer to "how does an AI agent actually use one of these bundles" without requiring a custom integration per agent framework. **OKF-formatted export and agent consumption.** Exported bundles follow an Open Knowledge Format (OKF) directory layout: - sources - sections - concepts - knowledge - relations - rules - evidence - tasks - references — with cross-linked frontmatter and a dedicated agent guide document. CLI commands (`sopkb-cli agent tasks`, `sopkb-cli agent context`, `sopkb-cli relations search`, `sopkb-cli relations neighborhood`) and the `sopkb-agent` crate let a downstream agent pull task-scoped knowledge, decision rules, evidence, and relation traversals, including free-text matching from a scenario description to relevant concepts. A worked set of queries (`examples/glp1-healthcare/agent_queries.md`, with captured output in `sample_agent_query_results.json`) shows this against the reference bundle. !!! note "Milestone numbering" For anyone who goes looking at the test suite or internal history: M4, M6, M7, and M8 were intentionally skipped in the internal roadmap. There's no missing or lost work behind those numbers — they were simply never used. ## What's explicitly out of scope right now This is a workbench for *building* SOP knowledge bundles, not a governed enterprise knowledgebase, and v0.0.1 does not try to be one. !!! warning "Not included in v0.0.1" Specifically, this release does not provide: - enterprise role-based access control (RBAC), - tenant isolation, - production decision trace or interaction trace, - enterprise lifecycle workflows, - governed publication into a live knowledgebase, - hosted multi-tenant deployment, - production compliance approval workflows, - enterprise API access to governed knowledge, - proprietary graph-layer mapping into any specific enterprise product. Those capabilities are intentionally left to a separate governed enterprise runtime that can import bundles produced here — this project's job stops at producing a well-reviewed, well-evidenced, portable bundle. ## A caveat on the bundle format !!! warning "Bundle format is still draft" The SOP Knowledge Bundle / OKF-based format that this tool produces is currently at spec version `0.2.0` and marked `draft` (see `docs/OKF_BUNDLE_SPEC.md`). It is versioned independently from the `sopkb` software itself — see `docs/BUNDLE_COMPATIBILITY_POLICY.md` for how that works — precisely because we expect the bundle schema to keep evolving before it reaches a 1.0 bundle-format release. If you build bundles against v0.0.1, expect that a future bundle-format change could require a documented migration step. We will call out any breaking bundle-format change explicitly in that release's notes, with a migration note, rather than letting it happen silently under a routine software version bump. ## Where to discuss this release Questions, feedback, and "here's how we're using it" reports are all welcome in GitHub Discussions on this repository. --- If you're active in the knowledge-graph/OKF community, the LLM-agent ecosystem, or the MCP ecosystem, we'd appreciate a pointer to this release — the built-in MCP server, in particular, is a genuine differentiator worth a look if you're building agents that need governed, evidence-linked SOP knowledge rather than raw RAG over documents. ## Project ### Contributing # Contributing Thanks for considering a contribution to KL4A. This document covers dev setup, running tests, coding style, the PR process, and DCO sign-off. ## Repository layout Everything shippable lives under `v2/`: | Path | What it is | |---|---| | `v2/sopkb-rust` | The Cargo workspace: the `sopkb-*` library crates plus the `sopkb-cli`, `sopkb-mcp`, and `sopkb-server` binaries. | | `v2/desktop-tauri` | The Tauri v2 desktop shell (KL4A Workbench). A **standalone** Cargo project with its own `Cargo.lock` and release profile — deliberately not a member of the workspace above. | | `v2/frontend` | The React + Vite UI, built into `v2/desktop-tauri/dist` and embedded in the app. | ## Dev setup You need a stable Rust toolchain (edition 2021, `rust-version` 1.77) and Node 20. ```bash # Rust workspace: CLI, MCP server, web server, and all library crates cd v2/sopkb-rust cargo build --workspace --all-targets # Frontend cd ../frontend npm ci npm run build # writes v2/desktop-tauri/dist # Desktop app (run from v2/desktop-tauri; needs the frontend built first) cd ../desktop-tauri npx --yes @tauri-apps/cli@^2 dev # or `build` for an installer ``` On Linux the Tauri build additionally needs the webkit2gtk stack — `libwebkit2gtk-4.1-dev`, `libappindicator3-dev`, `librsvg2-dev`, `patchelf`, `libxdo-dev`, `libssl-dev`. See `.github/workflows/linux-appimage.yml` for the exact package list CI installs. ## Running tests ```bash cd v2/sopkb-rust cargo test --workspace cd ../frontend npm test # vitest ``` Please add or update tests for any behavior change, and make sure the Rust suite passes locally before opening a PR. Two things worth knowing about the current state of CI, so a red or green run doesn't mislead you: - **CI covers `v2/sopkb-rust` only** (`ci.yml` runs `cargo build` + `cargo test` across a Linux/macOS/Windows matrix). The frontend's vitest suite and the desktop crate's tests are not wired into CI yet — run them locally. - **`cargo test --workspace` in CI carries a `--skip` list** of known-failing tests, listed explicitly in `ci.yml` with the reasoning inline. They're skipped visibly rather than deleted or masked. If your change fixes one, remove it from that list in the same PR. ### The `phaseN_*` test naming convention Several test files are named `phase_.rs` — `phase4_v1_diff.rs`, `phase5_export_bundle.rs`, `phase8_reference_diff.rs`, and so on. The `N` is the phase of the build-out the test was written for. A `*_v1_diff` or `*_reference_diff` test asserts that the output is **byte-for-byte identical** to a frozen reference output checked into the fixtures tree for the same input. They're differential tests, not ordinary unit tests, and a failure usually means real output drift rather than a broken assertion. Feature-scoped tests use plain descriptive names instead (`cli_integration.rs`, `docx_fixtures.rs`, `golden_roundtrip.rs`). ## Coding style ```bash cd v2/sopkb-rust cargo fmt --all # format cargo clippy --workspace --all-targets -- -D warnings cd ../frontend npm run lint # oxlint ``` Note that the `lint.yml` workflow is **non-blocking today** (`continue-on-error: true`): `cargo fmt --all -- --check` currently fails against the existing tree, which has never been uniformly rustfmt'd. Please format the code you touch, but don't take a green lint badge as proof the whole tree is clean, and don't reformat unrelated files in a feature PR — a tree-wide format pass should be its own commit. ## PR process 1. Fork/branch, make your change, and add/update tests. 2. Run `cargo test --workspace` and format/lint locally. 3. Open a PR describing what changed, why, and how you tested it. 4. Update user-facing docs if you changed CLI flags, the bundle schema, the desktop UI, or MCP tools. The docs site is built from `docs/` by `mkdocs.yml`; a new page needs a `nav` entry there to be reachable. 5. A maintainer will review; see [Governance](GOVERNANCE.md) for how decisions get made and response-time expectations (best-effort, no SLA). ### Checklist - [ ] Read this document. - [ ] Commits are signed off (`git commit -s`) per the DCO requirement below. - [ ] Tests added/updated, and `cargo test --workspace` passes locally. - [ ] Format/lint run over the code you touched. - [ ] Docs updated if user-facing behavior changed. - [ ] No secrets, real credentials, or non-synthetic PII anywhere in the diff, including fixtures and examples. ## DCO sign-off This project uses the **Developer Certificate of Origin (DCO)** instead of a Contributor License Agreement (CLA). It's a lighter-weight way of recording that you have the right to submit your contribution under the project's license, without a separate signed document. Sign off every commit with: ```bash git commit -s -m "Your commit message" ``` The `-s` flag appends a line to your commit message: ```text Signed-off-by: Your Name ``` That line is your certification that you wrote the change (or otherwise have the right to submit it) under the terms of the [Developer Certificate of Origin](https://developercertificate.org/), and that you're contributing it under this project's license ([Apache-2.0](https://github.com/CogniSwitch/KL4A/blob/main/LICENSE)). It uses the name and email from your local `git config user.name` / `user.email`, so make sure those are set to something real and identifiable — anonymous or obviously fake sign-offs won't be accepted. If you forgot `-s` on a commit already made, amend it: `git commit --amend -s` (for the most recent commit), or use `git rebase --exec 'git commit --amend --no-edit -s' ` for a range. PRs with unsigned commits will be asked to add sign-off before merge. ### Governance # Governance This document explains how KL4A (Knowledge Layer For Agents) is run, who makes decisions, how the open-source project relates to CogniSwitch's commercial product, and how to reach the people behind it. It exists because trust has to be explicit, not assumed. If you're deciding whether to build on this project, contribute to it, or depend on it in production, you should be able to answer "what happens to this over time?" without guessing. ## 1. The open-source / enterprise boundary CogniSwitch maintains this project and also sells a commercial product, **CS Governed KB**. That relationship creates an obvious risk for an open-source project: features get held back, quietly degraded, or slowly migrated behind a paywall to push adoption toward the paid product. We are committing, in public, to not doing that. The boundary below is the actual boundary — not a starting point that shrinks over time. ### 1.1 Stays open-source, forever The following are core to what this project is and will not be removed, crippled, or turned into a paid feature: - **Bundle creation** — inventorying, normalizing, and AI-assisted mining of SOP/policy/procedure documents into proposed knowledge. - **Extraction** — evidence-grounded knowledge proposals with source provenance, derivation tracking, and confidence. - **Human-in-the-loop review** — approve, reject, edit, defer, and comment on proposed knowledge, with reviewer rationale and review state stored in the bundle itself, not in a hosted service. - **Export** — OKF-based bundle files, graph JSON, RDF/TTL, and validation reports, in the bundle format described in [`OKF_BUNDLE_SPEC.md`](OKF_BUNDLE_SPEC.md). - **Local agent / MCP consumption** — CLI tools and an MCP server for agents to describe, search, and cite a finished bundle without going through any CogniSwitch service. A Knowledge Bundle produced by this project must remain fully useful — readable, reviewable, exportable, and agent-queryable — without CS Governed KB or any other CogniSwitch product. That's a design constraint, not a promise we're making lightly. ### 1.2 Enterprise-only by design **CS Governed KB** is a separate, commercial product that imports the bundles this project produces and operationalizes them. It is enterprise-only by design, not by artificial restriction, because it solves problems that are specific to running governed knowledge in production across an organization: - **RBAC** — role-based access control over who can see, edit, or publish governed knowledge. - **Tenancy** — multi-tenant isolation for hosted deployments. - **Governed lifecycle** — publication workflows, policy gates, and lifecycle states beyond local HITL review. - **Audit and decision trace** — persistent decision trace and interaction trace suitable for compliance and audit requirements. - **Hosted multi-tenancy** — running the governed knowledgebase as a hosted service with API-first access for agents, apps, and workflows. None of these are things a local, single-tenant, file-based OSS workbench should try to be. If you don't need them, you never have to think about CS Governed KB at all. ### 1.3 How this boundary changes If this boundary ever shifts, it will shift by a documented change to this file with a rationale in the commit/PR description and in the project's release notes — not silently, and not by a feature just disappearing from a release. ## 2. Maintainer roles This is an early-stage project. Governance is intentionally lightweight — enough structure to be predictable, not so much that it slows the project down before it has a community to serve. - **Maintainers** are the people with merge rights on this repository. Maintainers review and merge pull requests, cut releases, and are responsible for the direction of the OSS project. - **Triage** (issues and PR labeling, reproduction, first response) may be done by maintainers or by contributors explicitly given triage access. Anyone can help triage informally by commenting on issues even without that access. - Until the contributor base grows, CogniSwitch engineers are the de facto maintainers. The current list of people with merge rights is the set of people with write access to this repository on GitHub; we'll list maintainers by name here once the group stabilizes beyond the founding team. **Response-time expectations:** this project is maintained **best effort, with no SLA**. Issues and PRs will be looked at, but there is no guaranteed turnaround time. If something is urgent for your use case, say so in the issue — it helps prioritization, but it doesn't change the underlying best-effort commitment. ## 3. Communication channels - **GitHub Issues** — bug reports and well-scoped feature requests. - **GitHub Discussions** — the primary channel for questions, design discussion, proposals, and anything that isn't a crisp bug report. This is the channel to use if you're unsure where something belongs. We don't currently run a Discord or Slack for this project. A chat channel may be added later if someone — maintainer or community member — commits to actually monitoring it. Until that happens, assume no such channel exists, regardless of what you might find referenced elsewhere. ## 4. Decision-making Kept deliberately pragmatic for a project at this stage: - **Day-to-day changes** (bug fixes, small features, docs) are decided by normal PR review. Any maintainer approval is sufficient to merge. - **Larger or ambiguous changes** (new export formats, changes to the bundle profile, anything touching the OSS/enterprise boundary in Section 1) should start as a GitHub Discussion or an issue describing the proposal before a PR is opened, so the reasoning is visible before the implementation is. - **Disagreements among maintainers** are resolved by discussion and rough consensus. If consensus doesn't emerge, the maintainer who owns the area of the codebase in question makes the call, and reasoning is recorded in the issue or PR. - **Escalation:** if a decision affects the OSS/enterprise boundary itself, it is escalated to CogniSwitch's project leadership for a public, documented resolution — it does not get decided quietly inside a single PR. This process is intentionally small. As the contributor base grows, expect this document to grow with it — including a real maintainer list, and possibly a more formal proposal process. Any such change will itself go through the process described above.