@bradheitmann/odin-sentinel 0.2.1

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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +285 -0
  3. package/dist/src/bin/index.d.ts +2 -0
  4. package/dist/src/bin/index.js +17 -0
  5. package/dist/src/bin/index.js.map +1 -0
  6. package/dist/src/mcp/server.d.ts +2 -0
  7. package/dist/src/mcp/server.js +159 -0
  8. package/dist/src/mcp/server.js.map +1 -0
  9. package/dist/src/protocol/index.d.ts +2 -0
  10. package/dist/src/protocol/index.js +2 -0
  11. package/dist/src/protocol/index.js.map +1 -0
  12. package/dist/src/protocol/repository.d.ts +16 -0
  13. package/dist/src/protocol/repository.js +103 -0
  14. package/dist/src/protocol/repository.js.map +1 -0
  15. package/dist/src/protocol/schemas.d.ts +64 -0
  16. package/dist/src/protocol/schemas.js +39 -0
  17. package/dist/src/protocol/schemas.js.map +1 -0
  18. package/dist/src/protocol/service.d.ts +52 -0
  19. package/dist/src/protocol/service.js +322 -0
  20. package/dist/src/protocol/service.js.map +1 -0
  21. package/dist/src/protocol/validators.d.ts +16 -0
  22. package/dist/src/protocol/validators.js +56 -0
  23. package/dist/src/protocol/validators.js.map +1 -0
  24. package/dist/src/protocol/version.d.ts +1 -0
  25. package/dist/src/protocol/version.js +26 -0
  26. package/dist/src/protocol/version.js.map +1 -0
  27. package/docs/guides/quick-start.md +74 -0
  28. package/docs/guides/recommended-starter-team.md +35 -0
  29. package/docs/reference/client-compatibility.md +59 -0
  30. package/docs/reference/cost-and-privacy.md +35 -0
  31. package/docs/reference/distribution.md +74 -0
  32. package/docs/reference/public-surface-audit.md +133 -0
  33. package/package.json +69 -0
  34. package/protocol/SCP.md +34 -0
  35. package/protocol/closeout.yaml +20 -0
  36. package/protocol/delegation.yaml +38 -0
  37. package/protocol/model-profiles.yaml +63 -0
  38. package/protocol/receipts/boot-receipt.yaml +23 -0
  39. package/protocol/receipts/team-manifest.yaml +9 -0
  40. package/protocol/roles.yaml +62 -0
  41. package/protocol/topology.yaml +22 -0
  42. package/scripts/audit/public-surface.mjs +67 -0
  43. package/scripts/audit/verify-pack.mjs +71 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ODIN Sentinel contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,285 @@
1
+ # ODIN Sentinel
2
+
3
+ **Multi-harness terminal-pane team builder and orchestrator.**
4
+
5
+ ODIN Sentinel is a portable control layer for visible agent teams running across
6
+ terminal panes, local CLIs, editors, and MCP-capable harnesses. It does not try
7
+ to be another agent. It gives the agents a room, a roster, and a way to work
8
+ without dissolving into chatter.
9
+
10
+ The questions are practical. Who is here? What role do they hold? Who may
11
+ delegate? Who may verify? What changed, what passed, what failed, and how does
12
+ the session end without leaving a pane stack full of unfinished business?
13
+
14
+ ODIN starts with shape: an executive office, development pods, and ODIN
15
+ roles across the mesh. Then it provides the protocol pieces that keep the shape
16
+ honest: startup packets, role contracts, model and harness defaults, delegation
17
+ envelopes, receipts, manifests, and closeout checklists.
18
+
19
+ No hand-copied ritual. No private lore. Any MCP-capable harness can ask. Codex,
20
+ Claude, Droid, Crush, Goose, Zed, OpenCode, or a client written in Rust, Go,
21
+ Zig, or WebAssembly all fit the same boundary when they can launch or bridge
22
+ stdio MCP. These are examples, not bundled dependencies. One server. Many
23
+ harnesses. Same map, same names, same flame.
24
+
25
+ The repository is named `odin-sentinel` to avoid confusion with the Odin
26
+ programming language.
27
+
28
+ For a recommended first team, see
29
+ [docs/guides/recommended-starter-team.md](docs/guides/recommended-starter-team.md).
30
+
31
+ ## Terms
32
+
33
+ - ODIN Sentinel: this MCP server and its portable team-coordination protocol.
34
+ - SCP: Sentinel Coordination Protocol, the ODIN startup, delegation, receipt,
35
+ manifest, and closeout contract. It is not Secure Copy.
36
+ - CMUX: a compatible terminal-pane control surface. ODIN can support CMUX-style
37
+ teams, but CMUX is not required by this repository.
38
+ - Harness: a local agent runtime, CLI, editor integration, or MCP client.
39
+
40
+ ## How It Works
41
+
42
+ ```text
43
+ MCP-capable clients
44
+ ┌─────────────────────────────────────┐
45
+ │ Codex │ Claude │ Droid │ Crush │ UI │
46
+ └───┬──────┬────────┬───────┬─────┬───┘
47
+ │ │ │ │ │
48
+ └──────┴────────┴───────┴─────┘
49
+
50
+
51
+ ┌───────────────────┐
52
+ │ odin-sentinel │
53
+ │ MCP server │
54
+ └─────────┬─────────┘
55
+
56
+ ┌───────────────────┼───────────────────┐
57
+ ▼ ▼ ▼
58
+ ┌───────────┐ ┌───────────┐ ┌────────────┐
59
+ │ Resources │ │ Tools │ │ Exports │
60
+ │ protocol │ │ validate │ │ standalone │
61
+ │ roles │ │ startup │ │ protocol │
62
+ │ topology │ │ closeout │ │ snapshots │
63
+ └───────────┘ └───────────┘ └────────────┘
64
+ │ │ │
65
+ └───────────────────┼───────────────────┘
66
+
67
+ ┌─────────────────────────┐
68
+ │ Visible role topology │
69
+ │ EXEC PM, EXEC ODIN, │
70
+ │ TEAM PM, TEAM ODIN, │
71
+ │ DEV, QA, SHADOW │
72
+ └─────────────────────────┘
73
+ ```
74
+
75
+ ## Provided MCP Resources
76
+
77
+ - `odin://protocol/main` - core coordination protocol
78
+ - `odin://protocol/roles` - generic role contracts
79
+ - `odin://protocol/topology` - executive office, pod, and ODIN mesh defaults
80
+ - `odin://protocol/model-profiles` - recommended starter model/harness profiles
81
+ - `odin://protocol/closeout` - continuity parking and full shutdown checklists
82
+ - `odin://protocol/delegation` - visible-role delegation contract
83
+ - `odin://protocol/receipts/boot` - boot receipt template
84
+ - `odin://protocol/receipts/team-manifest` - team manifest template
85
+
86
+ ## Provided MCP Tools
87
+
88
+ - `odin.get_version`
89
+ - `odin.get_startup_packet`
90
+ - `odin.get_role_profile`
91
+ - `odin.validate_boot_receipt`
92
+ - `odin.validate_team_manifest`
93
+ - `odin.get_delegation_packet`
94
+ - `odin.validate_delegation_packet`
95
+ - `odin.get_closeout_checklist`
96
+ - `odin.get_runtime_notice`
97
+ - `odin.export_protocol_snapshot`
98
+
99
+ ## Self-Contained Protocol
100
+
101
+ ODIN Sentinel must not depend on external local extensions. Concepts such as
102
+ delegation, handoff discovery, startup topology, model/harness profiles, receipt
103
+ validation, and closeout are implemented as MCP resources and tools inside this
104
+ server.
105
+
106
+ A client may have other local extensions installed, but those extensions are optional
107
+ and cannot be required for the ODIN Sentinel protocol to work.
108
+
109
+ ## Client Compatibility
110
+
111
+ ODIN Sentinel is implemented in TypeScript and runs on Node.js, but MCP clients
112
+ can be written in Rust, Zig, Go, WebAssembly, Python, or any other environment
113
+ that can speak MCP over stdio.
114
+
115
+ The boundary is plain MCP JSON-RPC:
116
+
117
+ ```text
118
+ native / WASM / CLI client
119
+
120
+ │ MCP over stdio
121
+
122
+ node dist/src/bin/index.js
123
+ ```
124
+
125
+ For clients that cannot spawn stdio subprocesses, use a host bridge or consume
126
+ the fallback files returned by `odin.export_protocol_snapshot`.
127
+
128
+ See [docs/reference/client-compatibility.md](docs/reference/client-compatibility.md).
129
+ For the current release-surface inventory, see
130
+ [docs/reference/public-surface-audit.md](docs/reference/public-surface-audit.md).
131
+
132
+ ## Install
133
+
134
+ For a step-by-step setup, see [docs/guides/quick-start.md](docs/guides/quick-start.md).
135
+
136
+ For local source builds:
137
+
138
+ ```bash
139
+ pnpm install
140
+ pnpm run build
141
+ ```
142
+
143
+ After the package is published, MCP clients can use the package directly:
144
+
145
+ ```bash
146
+ pnpm dlx odin-sentinel
147
+ ```
148
+
149
+ or:
150
+
151
+ ```bash
152
+ npx -y odin-sentinel
153
+ ```
154
+
155
+ See [docs/reference/distribution.md](docs/reference/distribution.md).
156
+
157
+ ## Run Over stdio
158
+
159
+ ```bash
160
+ pnpm run dev
161
+ ```
162
+
163
+ After building:
164
+
165
+ ```bash
166
+ node dist/src/bin/index.js
167
+ ```
168
+
169
+ When installed from a package, the executable names are:
170
+
171
+ ```bash
172
+ odin-sentinel
173
+ odin-sentinel-mcp
174
+ ```
175
+
176
+ ## Example MCP Client Configuration
177
+
178
+ ```json
179
+ {
180
+ "mcpServers": {
181
+ "odin-sentinel": {
182
+ "command": "node",
183
+ "args": ["/absolute/path/to/odin-sentinel/dist/src/bin/index.js"]
184
+ }
185
+ }
186
+ }
187
+ ```
188
+
189
+ For local development, clients that support direct command execution can use:
190
+
191
+ ```json
192
+ {
193
+ "mcpServers": {
194
+ "odin-sentinel": {
195
+ "command": "pnpm",
196
+ "args": ["exec", "tsx", "/absolute/path/to/odin-sentinel/src/bin/index.ts"]
197
+ }
198
+ }
199
+ }
200
+ ```
201
+
202
+ ## Harness Setup Notes
203
+
204
+ MCP-capable harnesses should point at the built stdio server:
205
+
206
+ ```text
207
+ node /absolute/path/to/odin-sentinel/dist/src/bin/index.js
208
+ ```
209
+
210
+ Common config shapes:
211
+
212
+ - Claude/Cursor-style: add `odin-sentinel` under `mcpServers`.
213
+ - Codex CLI: use `codex mcp add odin-sentinel -- node /path/to/dist/src/bin/index.js`.
214
+ - Droid CLI: use `droid mcp add odin-sentinel node /path/to/dist/src/bin/index.js --type stdio`.
215
+ - OpenCode-style: add a local `mcp.odin-sentinel` command entry.
216
+ - Goose-style: add an enabled `type: mcp` extension entry.
217
+ - Zed-style: add an enabled custom `context_servers.odin-sentinel` entry.
218
+
219
+ These are MCP client patterns, not a compatibility certification for every
220
+ release of every harness. For harnesses without discoverable MCP configuration,
221
+ use the self-contained protocol snapshot from `odin.export_protocol_snapshot`
222
+ or a thin prompt that directs the agent to an MCP-capable host bridge.
223
+
224
+ ODIN Sentinel does not provide hosted inference and should not cost the
225
+ maintainer money when users run it locally. See
226
+ [docs/reference/cost-and-privacy.md](docs/reference/cost-and-privacy.md).
227
+
228
+ ## Startup Defaults
229
+
230
+ Fresh startup returns an executive office plus one development pod unless the
231
+ user or a handoff overrides it.
232
+
233
+ Executive office:
234
+
235
+ - `A/EXEC-PM`
236
+ - `A/EXEC-ODIN`
237
+ - `A/EXEC-ASST`
238
+ - `A/EXEC-RSCH`
239
+ - `A/EXEC-QA`
240
+
241
+ Development pod:
242
+
243
+ - `<TEAM>/TEAM-PM`
244
+ - `<TEAM>/ODIN`
245
+ - `<TEAM>/DEV-1`
246
+ - `<TEAM>/QA-1`
247
+ - `<TEAM>/SHADOW-1`
248
+
249
+ ## Closeout Modes
250
+
251
+ - `PARK_FOR_CONTINUITY`: keep role slots open and park occupants.
252
+ - `FULL_SESSION_SHUTDOWN`: quit occupants, verify exit, and close panes except
253
+ the final user-designated surface.
254
+
255
+ ## Development
256
+
257
+ Source layout:
258
+
259
+ - `src/bin/` - stdio entry point
260
+ - `src/mcp/` - MCP resource and tool adapter
261
+ - `src/protocol/` - ODIN protocol loading, packet construction, and validation
262
+ - `protocol/` - portable protocol data
263
+ - `docs/guides/` - onboarding and starter team guidance
264
+ - `docs/reference/` - compatibility, distribution, cost, and privacy notes
265
+ - `scripts/audit/` - package and public-surface release checks
266
+
267
+ ```bash
268
+ pnpm run typecheck
269
+ pnpm test
270
+ pnpm run build
271
+ pnpm run validate
272
+ ```
273
+
274
+ ## Open Source Hygiene
275
+
276
+ This repository is intended to become public later. Do not commit:
277
+
278
+ - personal file paths
279
+ - account names
280
+ - tokens, keys, or credentials
281
+ - project-specific handoff content
282
+ - private account details
283
+
284
+ Keep protocol files generic and put local deployment details in untracked client
285
+ configuration.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createServer } from "../mcp/server.js";
4
+ async function main() {
5
+ const server = createServer();
6
+ const transport = new StdioServerTransport();
7
+ await server.connect(transport);
8
+ }
9
+ try {
10
+ await main();
11
+ }
12
+ catch (error) {
13
+ const message = error instanceof Error ? error.message : "Unknown startup failure";
14
+ console.error(`odin-sentinel failed to start: ${message}`);
15
+ process.exitCode = 1;
16
+ }
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/bin/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,CAAC;IACH,MAAM,IAAI,EAAE,CAAC;AACf,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;IACnF,OAAO,CAAC,KAAK,CAAC,kCAAkC,OAAO,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(): McpServer;
@@ -0,0 +1,159 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import YAML from "yaml";
3
+ import { VERSION, exportProtocolSnapshot, getCloseoutChecklist, getDelegationPacket, getRoleProfile, getRuntimeNotice, getStartupPacket, loadProtocolData, validateBootReceipt, validateDelegationPacket, validateTeamManifest } from "../protocol/service.js";
4
+ import { bootReceiptInputShape, closeoutChecklistInputShape, delegationPacketInputShape, recordInputShape, roleProfileInputShape, startupPacketInputShape, teamManifestInputShape } from "../protocol/schemas.js";
5
+ function jsonText(value) {
6
+ return {
7
+ content: [
8
+ {
9
+ type: "text",
10
+ text: JSON.stringify(value, null, 2)
11
+ }
12
+ ]
13
+ };
14
+ }
15
+ function textResource(uri, text, mimeType) {
16
+ return {
17
+ contents: [
18
+ {
19
+ uri,
20
+ mimeType,
21
+ text
22
+ }
23
+ ]
24
+ };
25
+ }
26
+ function yamlResource(value) {
27
+ return YAML.stringify(value);
28
+ }
29
+ function registerProtocolResources(server) {
30
+ const resources = [
31
+ {
32
+ name: "protocol-main",
33
+ uri: "odin://protocol/main",
34
+ title: "ODIN Sentinel Protocol",
35
+ description: "Portable ODIN/SCP coordination protocol.",
36
+ mimeType: "text/markdown",
37
+ read: () => loadProtocolData().protocol
38
+ },
39
+ {
40
+ name: "delegation",
41
+ uri: "odin://protocol/delegation",
42
+ title: "Delegation Contract",
43
+ description: "Native ODIN delegation packet contract and validation rules.",
44
+ mimeType: "application/yaml",
45
+ read: () => yamlResource(loadProtocolData().delegation)
46
+ },
47
+ {
48
+ name: "boot-receipt",
49
+ uri: "odin://protocol/receipts/boot",
50
+ title: "Boot Receipt Template",
51
+ description: "Required startup receipt fields for visible ODIN/SCP roles.",
52
+ mimeType: "application/yaml",
53
+ read: () => yamlResource(loadProtocolData().bootReceipt)
54
+ },
55
+ {
56
+ name: "team-manifest",
57
+ uri: "odin://protocol/receipts/team-manifest",
58
+ title: "Team Manifest Template",
59
+ description: "Required team topology manifest fields for ODIN/SCP startup.",
60
+ mimeType: "application/yaml",
61
+ read: () => yamlResource(loadProtocolData().teamManifest)
62
+ },
63
+ {
64
+ name: "roles",
65
+ uri: "odin://protocol/roles",
66
+ title: "ODIN Role Contracts",
67
+ description: "Generic role definitions and authority defaults.",
68
+ mimeType: "application/yaml",
69
+ read: () => yamlResource(loadProtocolData().roles)
70
+ },
71
+ {
72
+ name: "topology",
73
+ uri: "odin://protocol/topology",
74
+ title: "Default Topology",
75
+ description: "Executive office, development pod, and ODIN mesh defaults.",
76
+ mimeType: "application/yaml",
77
+ read: () => yamlResource(loadProtocolData().topology)
78
+ },
79
+ {
80
+ name: "model-profiles",
81
+ uri: "odin://protocol/model-profiles",
82
+ title: "Model Harness Profiles",
83
+ description: "Default model and harness profile map.",
84
+ mimeType: "application/yaml",
85
+ read: () => yamlResource(loadProtocolData().modelProfiles)
86
+ },
87
+ {
88
+ name: "closeout",
89
+ uri: "odin://protocol/closeout",
90
+ title: "Closeout Protocol",
91
+ description: "Continuity parking and full shutdown checklists.",
92
+ mimeType: "application/yaml",
93
+ read: () => yamlResource(loadProtocolData().closeout)
94
+ }
95
+ ];
96
+ for (const resource of resources) {
97
+ server.registerResource(resource.name, resource.uri, {
98
+ title: resource.title,
99
+ description: resource.description,
100
+ mimeType: resource.mimeType
101
+ }, (uri) => textResource(uri.href, resource.read(), resource.mimeType));
102
+ }
103
+ }
104
+ export function createServer() {
105
+ const server = new McpServer({
106
+ name: "odin-sentinel",
107
+ version: VERSION
108
+ });
109
+ registerProtocolResources(server);
110
+ server.registerTool("odin.get_delegation_packet", {
111
+ title: "Get Delegation Packet",
112
+ description: "Build a self-contained visible-role delegation packet without relying on outside local extensions.",
113
+ inputSchema: delegationPacketInputShape
114
+ }, (input) => jsonText(getDelegationPacket(input)));
115
+ server.registerTool("odin.validate_delegation_packet", {
116
+ title: "Validate Delegation Packet",
117
+ description: "Check a delegation packet for required ODIN fields and role-separation warnings.",
118
+ inputSchema: recordInputShape
119
+ }, (input) => jsonText(validateDelegationPacket(input.packet)));
120
+ server.registerTool("odin.get_version", {
121
+ title: "Get ODIN Sentinel Version",
122
+ description: "Return server and protocol version metadata."
123
+ }, () => jsonText({ name: "odin-sentinel", version: VERSION }));
124
+ server.registerTool("odin.get_runtime_notice", {
125
+ title: "Get Runtime Notice",
126
+ description: "Return cost, privacy, inference, telemetry, and standalone runtime boundaries."
127
+ }, () => jsonText(getRuntimeNotice()));
128
+ server.registerTool("odin.get_startup_packet", {
129
+ title: "Get Startup Packet",
130
+ description: "Return a generic SCP/ODIN startup packet for a role and pod count.",
131
+ inputSchema: startupPacketInputShape
132
+ }, (input) => jsonText(getStartupPacket(input)));
133
+ server.registerTool("odin.get_role_profile", {
134
+ title: "Get Role Profile",
135
+ description: "Return the authority profile for a generic ODIN/SCP role.",
136
+ inputSchema: roleProfileInputShape
137
+ }, (input) => jsonText(getRoleProfile(input.role)));
138
+ server.registerTool("odin.validate_boot_receipt", {
139
+ title: "Validate Boot Receipt",
140
+ description: "Check a boot receipt for required ODIN/SCP fields and basic authority warnings.",
141
+ inputSchema: bootReceiptInputShape
142
+ }, (input) => jsonText(validateBootReceipt(input.receipt)));
143
+ server.registerTool("odin.validate_team_manifest", {
144
+ title: "Validate Team Manifest",
145
+ description: "Check a team manifest for required ODIN/SCP topology fields.",
146
+ inputSchema: teamManifestInputShape
147
+ }, (input) => jsonText(validateTeamManifest(input.manifest)));
148
+ server.registerTool("odin.get_closeout_checklist", {
149
+ title: "Get Closeout Checklist",
150
+ description: "Return the checklist for continuity parking or full session shutdown.",
151
+ inputSchema: closeoutChecklistInputShape
152
+ }, (input) => jsonText(getCloseoutChecklist(input.mode)));
153
+ server.registerTool("odin.export_protocol_snapshot", {
154
+ title: "Export Protocol Snapshot",
155
+ description: "Return generated fallback protocol files for clients that cannot use MCP."
156
+ }, () => jsonText({ version: VERSION, files: exportProtocolSnapshot() }));
157
+ return server;
158
+ }
159
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EACL,OAAO,EACP,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,qBAAqB,EACrB,2BAA2B,EAC3B,0BAA0B,EAC1B,gBAAgB,EAChB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,wBAAwB,CAAC;AAEhC,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;aACrC;SACF;KACF,CAAC;AACJ,CAAC;AAWD,SAAS,YAAY,CAAC,GAAW,EAAE,IAAY,EAAE,QAAgB;IAC/D,OAAO;QACL,QAAQ,EAAE;YACR;gBACE,GAAG;gBACH,QAAQ;gBACR,IAAI;aACL;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,yBAAyB,CAAC,MAAiB;IAClD,MAAM,SAAS,GAAmB;QAChC;YACE,IAAI,EAAE,eAAe;YACrB,GAAG,EAAE,sBAAsB;YAC3B,KAAK,EAAE,wBAAwB;YAC/B,WAAW,EAAE,0CAA0C;YACvD,QAAQ,EAAE,eAAe;YACzB,IAAI,EAAE,GAAG,EAAE,CAAC,gBAAgB,EAAE,CAAC,QAAQ;SACxC;QACD;YACE,IAAI,EAAE,YAAY;YAClB,GAAG,EAAE,4BAA4B;YACjC,KAAK,EAAE,qBAAqB;YAC5B,WAAW,EAAE,8DAA8D;YAC3E,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,UAAU,CAAC;SACxD;QACD;YACE,IAAI,EAAE,cAAc;YACpB,GAAG,EAAE,+BAA+B;YACpC,KAAK,EAAE,uBAAuB;YAC9B,WAAW,EAAE,6DAA6D;YAC1E,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,WAAW,CAAC;SACzD;QACD;YACE,IAAI,EAAE,eAAe;YACrB,GAAG,EAAE,wCAAwC;YAC7C,KAAK,EAAE,wBAAwB;YAC/B,WAAW,EAAE,8DAA8D;YAC3E,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,YAAY,CAAC;SAC1D;QACD;YACE,IAAI,EAAE,OAAO;YACb,GAAG,EAAE,uBAAuB;YAC5B,KAAK,EAAE,qBAAqB;YAC5B,WAAW,EAAE,kDAAkD;YAC/D,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC;SACnD;QACD;YACE,IAAI,EAAE,UAAU;YAChB,GAAG,EAAE,0BAA0B;YAC/B,KAAK,EAAE,kBAAkB;YACzB,WAAW,EAAE,4DAA4D;YACzE,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,QAAQ,CAAC;SACtD;QACD;YACE,IAAI,EAAE,gBAAgB;YACtB,GAAG,EAAE,gCAAgC;YACrC,KAAK,EAAE,wBAAwB;YAC/B,WAAW,EAAE,wCAAwC;YACrD,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,aAAa,CAAC;SAC3D;QACD;YACE,IAAI,EAAE,UAAU;YAChB,GAAG,EAAE,0BAA0B;YAC/B,KAAK,EAAE,mBAAmB;YAC1B,WAAW,EAAE,kDAAkD;YAC/D,QAAQ,EAAE,kBAAkB;YAC5B,IAAI,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAC,QAAQ,CAAC;SACtD;KACF,CAAC;IAEF,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,CAAC,gBAAgB,CACrB,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,GAAG,EACZ;YACE,KAAK,EAAE,QAAQ,CAAC,KAAK;YACrB,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;SAC5B,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC,CACpE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,eAAe;QACrB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAElC,MAAM,CAAC,YAAY,CACjB,4BAA4B,EAC5B;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,oGAAoG;QACjH,WAAW,EAAE,0BAA0B;KACxC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAChD,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,iCAAiC,EACjC;QACE,KAAK,EAAE,4BAA4B;QACnC,WAAW,EAAE,kFAAkF;QAC/F,WAAW,EAAE,gBAAgB;KAC9B,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAC5D,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;QACE,KAAK,EAAE,2BAA2B;QAClC,WAAW,EAAE,8CAA8C;KAC5D,EACD,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAC5D,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,yBAAyB,EACzB;QACE,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,gFAAgF;KAC9F,EACD,GAAG,EAAE,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CACnC,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,yBAAyB,EACzB;QACE,KAAK,EAAE,oBAAoB;QAC3B,WAAW,EAAE,oEAAoE;QACjF,WAAW,EAAE,uBAAuB;KACrC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAC7C,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,uBAAuB,EACvB;QACE,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,2DAA2D;QACxE,WAAW,EAAE,qBAAqB;KACnC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAChD,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,4BAA4B,EAC5B;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,iFAAiF;QAC9F,WAAW,EAAE,qBAAqB;KACnC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CACxD,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,6BAA6B,EAC7B;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,8DAA8D;QAC3E,WAAW,EAAE,sBAAsB;KACpC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAC1D,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,6BAA6B,EAC7B;QACE,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EAAE,uEAAuE;QACpF,WAAW,EAAE,2BAA2B;KACzC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CACtD,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,+BAA+B,EAC/B;QACE,KAAK,EAAE,0BAA0B;QACjC,WAAW,EAAE,2EAA2E;KACzF,EACD,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,CAAC,CACtE,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { VERSION, createProtocolService, exportProtocolSnapshot, getCloseoutChecklist, getDelegationPacket, getRoleProfile, getRuntimeNotice, getStartupPacket, validateBootReceipt, validateDelegationPacket, validateTeamManifest } from "./service.js";
2
+ export type { CloseoutMode, DelegationPacketInput, ProtocolData, RuntimeNotice, StartupPacket, StartupPacketInput, ValidationResult } from "./service.js";
@@ -0,0 +1,2 @@
1
+ export { VERSION, createProtocolService, exportProtocolSnapshot, getCloseoutChecklist, getDelegationPacket, getRoleProfile, getRuntimeNotice, getStartupPacket, validateBootReceipt, validateDelegationPacket, validateTeamManifest } from "./service.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/protocol/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACrB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,16 @@
1
+ export declare const REQUIRED_PROTOCOL_FILES: string[];
2
+ export type ProtocolData = {
3
+ protocol: string;
4
+ roles: Record<string, unknown>;
5
+ topology: Record<string, unknown>;
6
+ modelProfiles: Record<string, unknown>;
7
+ closeout: Record<string, unknown>;
8
+ delegation: Record<string, unknown>;
9
+ bootReceipt: Record<string, unknown>;
10
+ teamManifest: Record<string, unknown>;
11
+ };
12
+ export type ProtocolRepository = {
13
+ load(): ProtocolData;
14
+ path(...segments: string[]): string;
15
+ };
16
+ export declare function createFileProtocolRepository(rootDir?: string): ProtocolRepository;
@@ -0,0 +1,103 @@
1
+ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import YAML from "yaml";
5
+ import { requireRecord } from "./validators.js";
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+ export const REQUIRED_PROTOCOL_FILES = [
8
+ "protocol/SCP.md",
9
+ "protocol/roles.yaml",
10
+ "protocol/topology.yaml",
11
+ "protocol/model-profiles.yaml",
12
+ "protocol/closeout.yaml",
13
+ "protocol/delegation.yaml",
14
+ "protocol/receipts/boot-receipt.yaml",
15
+ "protocol/receipts/team-manifest.yaml"
16
+ ];
17
+ function missingProtocolFiles(root) {
18
+ return REQUIRED_PROTOCOL_FILES.filter((file) => !existsSync(join(root, file)));
19
+ }
20
+ function protocolRootCandidate(root) {
21
+ try {
22
+ const canonicalRoot = realpathSync(root);
23
+ return missingProtocolFiles(canonicalRoot).length === 0 ? canonicalRoot : undefined;
24
+ }
25
+ catch {
26
+ return undefined;
27
+ }
28
+ }
29
+ function requireProtocolRoot(root, label) {
30
+ let canonicalRoot;
31
+ try {
32
+ canonicalRoot = realpathSync(root);
33
+ }
34
+ catch {
35
+ throw new Error(`${label} is not readable: ${root}`);
36
+ }
37
+ const missing = missingProtocolFiles(canonicalRoot);
38
+ if (missing.length > 0) {
39
+ throw new Error(`${label} is missing required protocol files: ${missing.join(", ")}`);
40
+ }
41
+ return canonicalRoot;
42
+ }
43
+ function findRootDir() {
44
+ if (process.env.ODIN_SENTINEL_ROOT) {
45
+ return requireProtocolRoot(process.env.ODIN_SENTINEL_ROOT, "ODIN_SENTINEL_ROOT");
46
+ }
47
+ const candidates = [
48
+ join(__dirname, ".."),
49
+ join(__dirname, "..", ".."),
50
+ join(__dirname, "..", "..", ".."),
51
+ process.cwd()
52
+ ];
53
+ const root = candidates.map(protocolRootCandidate).find((candidate) => Boolean(candidate));
54
+ if (!root) {
55
+ throw new Error("Could not locate ODIN Sentinel protocol directory");
56
+ }
57
+ return root;
58
+ }
59
+ function readYaml(path) {
60
+ return requireRecord(YAML.parse(readFileSync(path, "utf8")), path);
61
+ }
62
+ function protocolFingerprint(rootDir) {
63
+ return REQUIRED_PROTOCOL_FILES.map((file) => {
64
+ const stats = statSync(join(rootDir, file));
65
+ return `${file}:${stats.mtimeMs}:${stats.size}`;
66
+ }).join("|");
67
+ }
68
+ function deepFreeze(value) {
69
+ if (!value || typeof value !== "object" || Object.isFrozen(value)) {
70
+ return value;
71
+ }
72
+ for (const nested of Object.values(value)) {
73
+ deepFreeze(nested);
74
+ }
75
+ return Object.freeze(value);
76
+ }
77
+ export function createFileProtocolRepository(rootDir = findRootDir()) {
78
+ const canonicalRootDir = requireProtocolRoot(rootDir, "Protocol root");
79
+ let cache;
80
+ const protocolPath = (...segments) => join(canonicalRootDir, "protocol", ...segments);
81
+ return {
82
+ path: protocolPath,
83
+ load: () => {
84
+ const fingerprint = protocolFingerprint(canonicalRootDir);
85
+ if (cache?.fingerprint === fingerprint) {
86
+ return cache.data;
87
+ }
88
+ const data = deepFreeze({
89
+ protocol: readFileSync(protocolPath("SCP.md"), "utf8"),
90
+ roles: readYaml(protocolPath("roles.yaml")),
91
+ topology: readYaml(protocolPath("topology.yaml")),
92
+ modelProfiles: readYaml(protocolPath("model-profiles.yaml")),
93
+ closeout: readYaml(protocolPath("closeout.yaml")),
94
+ delegation: readYaml(protocolPath("delegation.yaml")),
95
+ bootReceipt: readYaml(protocolPath("receipts", "boot-receipt.yaml")),
96
+ teamManifest: readYaml(protocolPath("receipts", "team-manifest.yaml"))
97
+ });
98
+ cache = { fingerprint, data };
99
+ return data;
100
+ }
101
+ };
102
+ }
103
+ //# sourceMappingURL=repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../../../src/protocol/repository.ts"],"names":[],"mappings":"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"}