@konneal/engine 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,8 +6,109 @@ typed tables/formulas/figures, conformance checking by execution, and
6
6
  the measurement gates that keep it honest. Konneal builds the databases
7
7
  and serves the API; publishers own their content, profile and frontend.
8
8
 
9
- Architecture and plan: docs/konneal-extraction-plan.md (and
10
- docs/multi-sdo-architecture.md). The reference deployment is OIML SMART
11
- AI (oimlsmart/ai — the reference profile). This repository was born
12
- from it with history preserved (git filter-repo over the engine
13
- subtrees); the README seed commit was replaced by the extraction.
9
+ ```
10
+ npm install @konneal/engine
11
+ ```
12
+
13
+ BSD-3-Clause. The reference deployment is
14
+ [OIML SMART AI](https://ai.oimlsmart.org).
15
+
16
+ ## What a deployment looks like
17
+
18
+ A publisher's worker is ten lines:
19
+
20
+ ```ts
21
+ // workers/worker_public/src/index.ts — the deployment entry
22
+ import worker, { setProfile } from "@konneal/engine";
23
+ import { PROFILE } from "./profile.gen.ts";
24
+
25
+ setProfile(PROFILE);
26
+
27
+ export default worker;
28
+ ```
29
+
30
+ Everything the publisher owns lives in `profile/*.yaml` — identity,
31
+ datasets, corpora, prompts, thresholds, eval cases. The codegen
32
+ (`gen_profile.mjs`, included) turns the YAML into a committed
33
+ TypeScript module; a drift test keeps both sides honest. The engine
34
+ reads the profile at request time; no publisher fact is hardcoded.
35
+
36
+ The engine also ships the ingest CLI (Python): parse → embed → upsert,
37
+ reading the same profile for its corpora declarations.
38
+
39
+ ## The three packages
40
+
41
+ | Package | What it is |
42
+ |---|---|
43
+ | `@konneal/engine` | The serving Worker + the ingest CLI (this package) |
44
+ | `@konneal/client` | The publisher-site contract: wire types, SSE client, citation chips, typed blocks |
45
+ | `@konneal/create-publisher` | `npm create @konneal/publisher` — scaffolds the whole deployment |
46
+
47
+ Start with the scaffolder: `npm create @konneal/publisher my-sdo
48
+ -- --with-site` writes the profile, the worker entry, the Cloudflare
49
+ wiring, the profile codegen, and (with `--with-site`) a minimal
50
+ Astro+Vue frontend consuming `@konneal/client`.
51
+
52
+ ## The profile (the publisher's single edit surface)
53
+
54
+ | File | Declares |
55
+ |---|---|
56
+ | `publisher.yaml` | id, name, domains, identity issuer, codec, session cookie, features |
57
+ | `datasets.yaml` | what users can scope to (public vs session-gated), per-corpus prompt notes |
58
+ | `corpora.yaml` | the corpus registry — which corpora exist, which indexes serve them |
59
+ | `sources.yaml` | upstream repos the tooling reads (clean corpus, bibliography, terminology, models) |
60
+ | `ui.yaml` | suggestions, model disclosure, smoke probes |
61
+ | `retrieval.yaml` | steering vocabulary, process-intent notes |
62
+ | `prompts.yaml` | the publisher's prompt voice (identity, refusal, examples) |
63
+ | `evals/` | golden cases, annealment probes, ladder — the promotion-gate data |
64
+
65
+ ## Serving architecture
66
+
67
+ - **Retrieval** is a stage registry; the ask path owns composition only
68
+ - **HTTP** is a route table dispatched by both workers
69
+ - Every steering number lives in `THRESHOLDS`; the chunk wire type is
70
+ shared with the Python producer by a contract test
71
+ - **Ports** (`ports/`): ModelRunner, VectorIndex, Kv, Blobs, Runtime —
72
+ the Cloudflare adapters are the only provider-typed module; a purity
73
+ lint enforces it in CI
74
+ - **Publisher purity**: a CI lint fails any publisher string in
75
+ `workers/` outside the codec registry (the identifier grammars)
76
+ - **Feature gates**: `drafts` and `model_plane` are profile-declared,
77
+ off by default
78
+
79
+ ## The ingest CLI
80
+
81
+ ```bash
82
+ pip install git+https://github.com/konneal/engine.git
83
+ python -m ingest.cli parse # corpora → chunks.jsonl + manifest
84
+ python -m ingest.cli embed # embed via the binding's model
85
+ python -m ingest.cli upsert # push vectors + metadata to Vectorize
86
+ ```
87
+
88
+ ## MCP server
89
+
90
+ The package exports `./mcp` — a ten-line entry per deployment serves
91
+ the publisher's public corpus to MCP clients (agent ecosystems).
92
+ Auth is required: the MCP client presents one of the deployment's API
93
+ keys; the same token rides outbound so spend and quota charge that
94
+ key.
95
+
96
+ ## Promotion gates
97
+
98
+ The engine ships the gate harness: a deployment's golden cases and
99
+ annealment probes live in `profile/evals/`; the gate runs them against
100
+ production before any promotion. Answers are witness-checked (the
101
+ answer must contain the expected span, not just score well).
102
+
103
+ ## Repository
104
+
105
+ - `workers/worker_public/` — the public-facing Worker
106
+ - `workers/worker_mcp/` — the MCP server Worker
107
+ - `workers/shared/` — the router, chunk wire type, session
108
+ - `ports/` — the provider seam (interfaces + Cloudflare adapters)
109
+ - `profile/` — the engine's fixture profile (a real deployment carries
110
+ its own; this one exists so tests run against declared data)
111
+ - `profile2/` — the reference matrix's second fixture (a different
112
+ publisher shape; CI proves the engine serves declared profiles)
113
+ - `ingest/` — the Python ingest CLI
114
+ - `tests/` — unit suites (plain node, no network)
@@ -1,3 +1,4 @@
1
+ import { setProfile } from "../../worker_public/src/profile.ts";
1
2
  export interface Env {
2
3
  RAG_BASE: string;
3
4
  /** the deployment's shared D1 (API keys + the derived documents
@@ -8,3 +9,4 @@ declare const _default: {
8
9
  fetch(req: Request, env: Env): Promise<Response>;
9
10
  };
10
11
  export default _default;
12
+ export { setProfile };
@@ -3,7 +3,8 @@ import {
3
3
  } from "../../chunk-ROF3Q7UC.js";
4
4
  import "../../chunk-OCNLV7Q7.js";
5
5
  import {
6
- P
6
+ P,
7
+ setProfile
7
8
  } from "../../chunk-35ODH64W.js";
8
9
 
9
10
  // workers/worker_mcp/src/index.ts
@@ -17,7 +18,7 @@ var rpcError = (id, code, message) => json({ jsonrpc: "2.0", id, error: { code,
17
18
  var publisherId = () => P().publisher.id;
18
19
  var bearer = (req) => (req.headers.get("authorization") ?? "").replace(/^Bearer\s+/i, "").trim();
19
20
  var publisherName = () => P().publisher.name;
20
- var TOOLS = [
21
+ var tools = () => [
21
22
  {
22
23
  name: `${publisherId()}_search`,
23
24
  description: `Search the ${publisherName()} publications corpus. Returns ranked passages with publication identifier, edition, clause and snippet.`,
@@ -107,7 +108,7 @@ var src_default = {
107
108
  server: "rag-mcp",
108
109
  transport: "streamable-http",
109
110
  endpoint: "/mcp",
110
- tools: TOOLS.map((t) => t.name)
111
+ tools: tools().map((t) => t.name)
111
112
  });
112
113
  }
113
114
  if (url.pathname !== "/mcp") return json({ error: "not_found" }, 404);
@@ -130,7 +131,7 @@ var src_default = {
130
131
  serverInfo: { name: "rag-mcp", version: "1.0.0", title: `${P().publisher.product_name} \u2014 public corpus` }
131
132
  });
132
133
  case "tools/list":
133
- return rpcResult(msg.id, { tools: TOOLS });
134
+ return rpcResult(msg.id, { tools: tools() });
134
135
  case "tools/call": {
135
136
  const out = await callTool(env, bearer(req), String(msg.params?.name ?? ""), msg.params?.arguments ?? {});
136
137
  return rpcResult(msg.id, out);
@@ -149,5 +150,6 @@ var src_default = {
149
150
  }
150
151
  };
151
152
  export {
152
- src_default as default
153
+ src_default as default,
154
+ setProfile
153
155
  };
package/package.json CHANGED
@@ -31,7 +31,7 @@
31
31
  "@astrojs/markdown-satteri": "^0.4.1",
32
32
  "@astrojs/mdx": "^4.3.14"
33
33
  },
34
- "version": "0.1.1",
34
+ "version": "0.1.3",
35
35
  "description": "The Konneal engine: the publisher-agnostic build pipeline and API plane for standards intelligence (retrieval, answer contract, verdicts, evaluation).",
36
36
  "license": "BSD-3-Clause",
37
37
  "type": "module",
@@ -14,7 +14,7 @@
14
14
  // server — each request is answered in one JSON response; no sessions.
15
15
  // https://modelcontextprotocol.io spec (2025-06 streamable HTTP).
16
16
 
17
- import { P } from "../../worker_public/src/profile.ts";
17
+ import { P, setProfile } from "../../worker_public/src/profile.ts";
18
18
  import { authenticate } from "../../worker_public/src/lib/http";
19
19
 
20
20
  export interface Env {
@@ -39,7 +39,7 @@ const rpcError = (id: unknown, code: number, message: string) =>
39
39
  const publisherId = () => P().publisher.id;
40
40
  const bearer = (req: Request) => (req.headers.get("authorization") ?? "").replace(/^Bearer\s+/i, "").trim();
41
41
  const publisherName = () => P().publisher.name;
42
- const TOOLS = [
42
+ const tools = () => [
43
43
  {
44
44
  name: `${publisherId()}_search`,
45
45
  description:
@@ -138,7 +138,7 @@ export default {
138
138
  server: "rag-mcp",
139
139
  transport: "streamable-http",
140
140
  endpoint: "/mcp",
141
- tools: TOOLS.map((t) => t.name),
141
+ tools: tools().map((t) => t.name),
142
142
  });
143
143
  }
144
144
 
@@ -168,7 +168,7 @@ export default {
168
168
  serverInfo: { name: "rag-mcp", version: "1.0.0", title: `${P().publisher.product_name} — public corpus` },
169
169
  });
170
170
  case "tools/list":
171
- return rpcResult(msg.id, { tools: TOOLS });
171
+ return rpcResult(msg.id, { tools: tools() });
172
172
  case "tools/call": {
173
173
  const out = await callTool(env, bearer(req), String(msg.params?.name ?? ""), msg.params?.arguments ?? {});
174
174
  return rpcResult(msg.id, out);
@@ -186,3 +186,4 @@ export default {
186
186
  }
187
187
  },
188
188
  };
189
+ export { setProfile };