@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
@@ -0,0 +1,64 @@
1
+ import { z } from "zod";
2
+ export declare const startupPacketInputShape: {
3
+ readonly role: z.ZodOptional<z.ZodString>;
4
+ readonly pods: z.ZodOptional<z.ZodNumber>;
5
+ readonly repoPath: z.ZodOptional<z.ZodString>;
6
+ readonly handoffPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
7
+ readonly userInstruction: z.ZodOptional<z.ZodString>;
8
+ };
9
+ export declare const startupPacketInputSchema: z.ZodObject<{
10
+ role: z.ZodOptional<z.ZodString>;
11
+ pods: z.ZodOptional<z.ZodNumber>;
12
+ repoPath: z.ZodOptional<z.ZodString>;
13
+ handoffPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
14
+ userInstruction: z.ZodOptional<z.ZodString>;
15
+ }, z.core.$strip>;
16
+ export type StartupPacketInput = z.infer<typeof startupPacketInputSchema>;
17
+ export declare const delegationPacketInputShape: {
18
+ readonly sourceRole: z.ZodString;
19
+ readonly targetRoleSlot: z.ZodString;
20
+ readonly task: z.ZodString;
21
+ readonly scope: z.ZodOptional<z.ZodString>;
22
+ readonly mayImplement: z.ZodOptional<z.ZodBoolean>;
23
+ readonly mayQaAccept: z.ZodOptional<z.ZodBoolean>;
24
+ readonly writeScope: z.ZodOptional<z.ZodArray<z.ZodString>>;
25
+ readonly readScope: z.ZodOptional<z.ZodArray<z.ZodString>>;
26
+ readonly prohibitedPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
27
+ readonly reportBack: z.ZodOptional<z.ZodString>;
28
+ };
29
+ export declare const delegationPacketInputSchema: z.ZodObject<{
30
+ sourceRole: z.ZodString;
31
+ targetRoleSlot: z.ZodString;
32
+ task: z.ZodString;
33
+ scope: z.ZodOptional<z.ZodString>;
34
+ mayImplement: z.ZodOptional<z.ZodBoolean>;
35
+ mayQaAccept: z.ZodOptional<z.ZodBoolean>;
36
+ writeScope: z.ZodOptional<z.ZodArray<z.ZodString>>;
37
+ readScope: z.ZodOptional<z.ZodArray<z.ZodString>>;
38
+ prohibitedPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
39
+ reportBack: z.ZodOptional<z.ZodString>;
40
+ }, z.core.$strip>;
41
+ export type DelegationPacketInput = z.infer<typeof delegationPacketInputSchema>;
42
+ export declare const recordInputShape: {
43
+ readonly packet: z.ZodRecord<z.ZodString, z.ZodUnknown>;
44
+ };
45
+ export declare const roleProfileInputShape: {
46
+ readonly role: z.ZodString;
47
+ };
48
+ export declare const bootReceiptInputShape: {
49
+ readonly receipt: z.ZodRecord<z.ZodString, z.ZodUnknown>;
50
+ };
51
+ export declare const teamManifestInputShape: {
52
+ readonly manifest: z.ZodRecord<z.ZodString, z.ZodUnknown>;
53
+ };
54
+ export declare const closeoutModeSchema: z.ZodEnum<{
55
+ PARK_FOR_CONTINUITY: "PARK_FOR_CONTINUITY";
56
+ FULL_SESSION_SHUTDOWN: "FULL_SESSION_SHUTDOWN";
57
+ }>;
58
+ export type CloseoutMode = z.infer<typeof closeoutModeSchema>;
59
+ export declare const closeoutChecklistInputShape: {
60
+ readonly mode: z.ZodEnum<{
61
+ PARK_FOR_CONTINUITY: "PARK_FOR_CONTINUITY";
62
+ FULL_SESSION_SHUTDOWN: "FULL_SESSION_SHUTDOWN";
63
+ }>;
64
+ };
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ export const startupPacketInputShape = {
3
+ role: z.string().optional(),
4
+ pods: z.number().int().min(0).max(25).optional(),
5
+ repoPath: z.string().optional(),
6
+ handoffPaths: z.array(z.string()).optional(),
7
+ userInstruction: z.string().optional()
8
+ };
9
+ export const startupPacketInputSchema = z.object(startupPacketInputShape);
10
+ export const delegationPacketInputShape = {
11
+ sourceRole: z.string(),
12
+ targetRoleSlot: z.string(),
13
+ task: z.string(),
14
+ scope: z.string().optional(),
15
+ mayImplement: z.boolean().optional(),
16
+ mayQaAccept: z.boolean().optional(),
17
+ writeScope: z.array(z.string()).optional(),
18
+ readScope: z.array(z.string()).optional(),
19
+ prohibitedPaths: z.array(z.string()).optional(),
20
+ reportBack: z.string().optional()
21
+ };
22
+ export const delegationPacketInputSchema = z.object(delegationPacketInputShape);
23
+ export const recordInputShape = {
24
+ packet: z.record(z.string(), z.unknown())
25
+ };
26
+ export const roleProfileInputShape = {
27
+ role: z.string()
28
+ };
29
+ export const bootReceiptInputShape = {
30
+ receipt: z.record(z.string(), z.unknown())
31
+ };
32
+ export const teamManifestInputShape = {
33
+ manifest: z.record(z.string(), z.unknown())
34
+ };
35
+ export const closeoutModeSchema = z.enum(["PARK_FOR_CONTINUITY", "FULL_SESSION_SHUTDOWN"]);
36
+ export const closeoutChecklistInputShape = {
37
+ mode: closeoutModeSchema
38
+ };
39
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/protocol/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;IAChD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC5C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC;AAEX,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;AAG1E,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACpC,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACnC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACzC,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC/C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACzB,CAAC;AAEX,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;AAGhF,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;CACjC,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;CACR,CAAC;AAEX,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;CAClC,CAAC;AAEX,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;CACnC,CAAC;AAEX,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,qBAAqB,EAAE,uBAAuB,CAAC,CAAC,CAAC;AAG3F,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,IAAI,EAAE,kBAAkB;CAChB,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { type ProtocolData, type ProtocolRepository } from "./repository.js";
2
+ import type { CloseoutMode, DelegationPacketInput, StartupPacketInput } from "./schemas.js";
3
+ import { type ValidationResult } from "./validators.js";
4
+ import { VERSION } from "./version.js";
5
+ export type { ProtocolData, ValidationResult };
6
+ export type { CloseoutMode, DelegationPacketInput, StartupPacketInput };
7
+ export { VERSION };
8
+ export type StartupPacket = {
9
+ version: string;
10
+ role: string;
11
+ pods: number;
12
+ resourcesToRead: string[];
13
+ requiredActions: string[];
14
+ defaultTopology: unknown;
15
+ modelProfile: unknown;
16
+ bootReceiptRequiredFields: unknown;
17
+ startupPrompt: string;
18
+ };
19
+ export type RuntimeNotice = {
20
+ inferenceProvider: "none";
21
+ hostedService: false;
22
+ telemetry: false;
23
+ networkCalls: false;
24
+ maintainerPaysForUserInference: false;
25
+ userPaysForHarnessInference: true;
26
+ externalOrchestrationBundled: false;
27
+ notes: string[];
28
+ };
29
+ export declare function protocolPath(...segments: string[]): string;
30
+ export declare function loadProtocolData(repository?: ProtocolRepository): ProtocolData;
31
+ export declare function getRoleProfile(role: string, repository?: ProtocolRepository): unknown;
32
+ export declare function getStartupPacket(input?: StartupPacketInput, repository?: ProtocolRepository): StartupPacket;
33
+ export declare function getDelegationPacket(input: DelegationPacketInput): Record<string, unknown>;
34
+ export declare function validateDelegationPacket(packet: Record<string, unknown>, repository?: ProtocolRepository): ValidationResult;
35
+ export declare function validateBootReceipt(receipt: Record<string, unknown>, repository?: ProtocolRepository): ValidationResult;
36
+ export declare function validateTeamManifest(manifest: Record<string, unknown>, repository?: ProtocolRepository): ValidationResult;
37
+ export declare function getCloseoutChecklist(mode: CloseoutMode, repository?: ProtocolRepository): unknown;
38
+ export declare function getRuntimeNotice(): RuntimeNotice;
39
+ export declare function exportProtocolSnapshot(repository?: ProtocolRepository): Record<string, string>;
40
+ export declare function createProtocolService(repository?: ProtocolRepository): {
41
+ protocolPath: (...segments: string[]) => string;
42
+ loadProtocolData: () => ProtocolData;
43
+ getRoleProfile: (role: string) => unknown;
44
+ getStartupPacket: (input?: StartupPacketInput) => StartupPacket;
45
+ getDelegationPacket: typeof getDelegationPacket;
46
+ validateDelegationPacket: (packet: Record<string, unknown>) => ValidationResult;
47
+ validateBootReceipt: (receipt: Record<string, unknown>) => ValidationResult;
48
+ validateTeamManifest: (manifest: Record<string, unknown>) => ValidationResult;
49
+ getCloseoutChecklist: (mode: CloseoutMode) => unknown;
50
+ getRuntimeNotice: typeof getRuntimeNotice;
51
+ exportProtocolSnapshot: () => Record<string, string>;
52
+ };
@@ -0,0 +1,322 @@
1
+ import YAML from "yaml";
2
+ import { createFileProtocolRepository } from "./repository.js";
3
+ import { asRecord, buildValidationResult, isVisibleRoleSlot, requireRecord, requireStringArray, validateFieldTypes, validateNonEmptyArrays, validateRequiredFields } from "./validators.js";
4
+ import { VERSION } from "./version.js";
5
+ const DEFAULT_ROLE_SLOT = "A/EXEC-PM";
6
+ const DEFAULT_HANDOFF_PATHS = [
7
+ "docs/handoffs/",
8
+ ".odin/handoffs/",
9
+ ".odin/audit/"
10
+ ];
11
+ export { VERSION };
12
+ let defaultRepository;
13
+ function getDefaultRepository() {
14
+ defaultRepository ??= createFileProtocolRepository();
15
+ return defaultRepository;
16
+ }
17
+ export function protocolPath(...segments) {
18
+ return getDefaultRepository().path(...segments);
19
+ }
20
+ function normalizeRoleName(role) {
21
+ const visibleSlot = role.includes("/") ? role.split("/").at(-1) ?? role : role;
22
+ const normalized = visibleSlot.toUpperCase().replace(/[\s-]+/g, "_");
23
+ if (normalized === "ODIN")
24
+ return "TEAM_ODIN";
25
+ if (/^DEV_\d+$/.test(normalized))
26
+ return "DEV_WORKER";
27
+ if (/^QA_\d+$/.test(normalized))
28
+ return "QA_WORKER";
29
+ if (/^SHADOW_\d+$/.test(normalized))
30
+ return "SHADOW_REVIEWER";
31
+ return normalized;
32
+ }
33
+ function modelProfileKeys(role) {
34
+ const normalized = normalizeRoleName(role);
35
+ const executiveSlot = normalized.startsWith("EXEC_") ? `A/${normalized.replaceAll("_", "-")}` : undefined;
36
+ return [role, executiveSlot, normalized].filter((key) => Boolean(key));
37
+ }
38
+ function safeErrorText(value) {
39
+ const sanitized = value.replace(/[\u0000-\u001F\u007F]/g, " ").replace(/\s+/g, " ").trim();
40
+ if (sanitized.length === 0)
41
+ return "<empty>";
42
+ return sanitized.length > 120 ? `${sanitized.slice(0, 117)}...` : sanitized;
43
+ }
44
+ function normalizePodCount(pods) {
45
+ const value = pods ?? 1;
46
+ if (!Number.isInteger(value) || value < 0 || value > 25) {
47
+ throw new Error(`Invalid development pod count: ${value}`);
48
+ }
49
+ return value;
50
+ }
51
+ export function loadProtocolData(repository = getDefaultRepository()) {
52
+ return repository.load();
53
+ }
54
+ export function getRoleProfile(role, repository = getDefaultRepository()) {
55
+ const data = loadProtocolData(repository);
56
+ const roles = requireRecord(data.roles.roles, "roles.roles");
57
+ const normalized = normalizeRoleName(role);
58
+ const roleProfile = roles?.[normalized];
59
+ if (!roleProfile) {
60
+ throw new Error(`Unknown ODIN/SCP role: ${safeErrorText(role)}`);
61
+ }
62
+ return roleProfile;
63
+ }
64
+ export function getStartupPacket(input = {}, repository = getDefaultRepository()) {
65
+ const data = loadProtocolData(repository);
66
+ const role = input.role ?? DEFAULT_ROLE_SLOT;
67
+ getRoleProfile(role, repository);
68
+ const pods = normalizePodCount(input.pods);
69
+ const resourcesToRead = [
70
+ "odin://protocol/main",
71
+ "odin://protocol/roles",
72
+ "odin://protocol/topology",
73
+ "odin://protocol/model-profiles",
74
+ "odin://protocol/closeout",
75
+ "odin://protocol/delegation",
76
+ "odin://protocol/receipts/boot",
77
+ "odin://protocol/receipts/team-manifest",
78
+ ...(input.handoffPaths ?? DEFAULT_HANDOFF_PATHS)
79
+ ];
80
+ const requiredActions = [
81
+ "emit SCP_BOOT_RECEIPT or SCP_MIN_BOOT_RECEIPT before broad dispatch",
82
+ "use visible role slots only; do not create hidden subagents",
83
+ `bootstrap executive office plus ${pods} development pod${pods === 1 ? "" : "s"}`,
84
+ "state SESSION_OBJECTIVES before product dispatch",
85
+ "refresh repo status, upstream parity, worktrees, stashes, and topology before lifecycle claims"
86
+ ];
87
+ const modelProfiles = requireRecord(data.modelProfiles.profiles, "model-profiles.profiles");
88
+ const roleModelProfile = modelProfileKeys(role)
89
+ .map((key) => modelProfiles[key])
90
+ .find((profile) => profile !== undefined) ?? modelProfiles[DEFAULT_ROLE_SLOT];
91
+ if (!roleModelProfile) {
92
+ throw new Error(`No model profile found for role: ${safeErrorText(role)}`);
93
+ }
94
+ return {
95
+ version: VERSION,
96
+ role,
97
+ pods,
98
+ resourcesToRead,
99
+ requiredActions,
100
+ defaultTopology: data.topology.default_topology,
101
+ modelProfile: roleModelProfile,
102
+ bootReceiptRequiredFields: data.bootReceipt.required_fields,
103
+ startupPrompt: [
104
+ "Use ODIN Sentinel coordination.",
105
+ "",
106
+ `You are ${role}.`,
107
+ "Load startup requirements from the odin-sentinel MCP resources and tools. Do not assume external local extensions exist.",
108
+ input.repoPath ? `Repository: ${input.repoPath}` : "Repository: discover from current working directory.",
109
+ `Bootstrap executive office plus ${pods} development pod${pods === 1 ? "" : "s"} unless handoff or user instruction overrides this.`,
110
+ input.userInstruction ? `User instruction: ${input.userInstruction}` : "Ask for objectives if no handoff supplies them."
111
+ ].join("\n")
112
+ };
113
+ }
114
+ export function getDelegationPacket(input) {
115
+ return {
116
+ receipt_type: "SCP-DELEGATE",
117
+ source_role: input.sourceRole,
118
+ target_role_slot: input.targetRoleSlot,
119
+ task: input.task,
120
+ scope: input.scope ?? "bounded task scope; caller must specify exact files or artifacts before mutation",
121
+ authority: {
122
+ may_implement: input.mayImplement ?? false,
123
+ may_qa_accept: input.mayQaAccept ?? false,
124
+ write_scope: input.writeScope ?? [],
125
+ read_scope: input.readScope ?? [],
126
+ prohibited_paths: input.prohibitedPaths ?? []
127
+ },
128
+ visibility: {
129
+ requires_visible_role_slot: true,
130
+ hidden_agents_allowed: false,
131
+ delivery_proof_required: true
132
+ },
133
+ report_back: input.reportBack ?? "Return status, evidence path, blockers, touched files, and next requested action.",
134
+ required_delivery_states: ["DELIVERED_ACKED", "DELIVERED_NO_ACK", "INPUT_BAR_ONLY", "PANE_BLOCKED_ON_PERMISSION", "PANE_STILL_THINKING"]
135
+ };
136
+ }
137
+ export function validateDelegationPacket(packet, repository = getDefaultRepository()) {
138
+ const data = loadProtocolData(repository);
139
+ const contract = requireRecord(data.delegation.delegation_contract, "delegation.delegation_contract");
140
+ const required = requireStringArray(contract.required_fields, "delegation.delegation_contract.required_fields");
141
+ const authorityRequired = requireStringArray(contract.authority_fields, "delegation.delegation_contract.authority_fields");
142
+ const visibilityRequired = requireStringArray(contract.visibility_fields, "delegation.delegation_contract.visibility_fields");
143
+ const receiptTypes = requireStringArray(contract.receipt_types, "delegation.delegation_contract.receipt_types");
144
+ const authority = asRecord(packet.authority);
145
+ const visibility = asRecord(packet.visibility);
146
+ const missing = [
147
+ ...validateRequiredFields(packet, required),
148
+ ...validateRequiredFields(authority, authorityRequired).map((field) => `authority.${field}`),
149
+ ...validateRequiredFields(visibility, visibilityRequired).map((field) => `visibility.${field}`)
150
+ ];
151
+ const invalid = [
152
+ ...validateFieldTypes(packet, {
153
+ receipt_type: "string",
154
+ source_role: "string",
155
+ target_role_slot: "string",
156
+ task: "string",
157
+ scope: "string",
158
+ authority: "object",
159
+ report_back: "string",
160
+ visibility: "object"
161
+ }),
162
+ ...validateFieldTypes(authority, {
163
+ may_implement: "boolean",
164
+ may_qa_accept: "boolean",
165
+ write_scope: "string_array",
166
+ read_scope: "string_array",
167
+ prohibited_paths: "string_array"
168
+ }).map((field) => `authority.${field}`),
169
+ ...validateFieldTypes(visibility, {
170
+ requires_visible_role_slot: "boolean",
171
+ hidden_agents_allowed: "boolean",
172
+ delivery_proof_required: "boolean"
173
+ }).map((field) => `visibility.${field}`)
174
+ ];
175
+ const warnings = [];
176
+ if (typeof packet.receipt_type === "string" && !receiptTypes.includes(packet.receipt_type)) {
177
+ invalid.push("receipt_type");
178
+ }
179
+ if (typeof packet.target_role_slot === "string" && !isVisibleRoleSlot(packet.target_role_slot)) {
180
+ invalid.push("target_role_slot");
181
+ }
182
+ if (visibility?.hidden_agents_allowed === true) {
183
+ invalid.push("visibility.hidden_agents_allowed");
184
+ warnings.push("delegation permits hidden agents; ODIN requires visible role slots");
185
+ }
186
+ if (visibility?.requires_visible_role_slot === false) {
187
+ invalid.push("visibility.requires_visible_role_slot");
188
+ warnings.push("delegation does not require a visible role slot");
189
+ }
190
+ if (visibility?.delivery_proof_required === false) {
191
+ invalid.push("visibility.delivery_proof_required");
192
+ warnings.push("delegation does not require delivery proof");
193
+ }
194
+ if (authority?.may_implement === true && authority?.may_qa_accept === true) {
195
+ invalid.push("authority.may_qa_accept");
196
+ warnings.push("same delegation grants implementation and QA acceptance authority");
197
+ }
198
+ return buildValidationResult(missing, invalid, warnings);
199
+ }
200
+ export function validateBootReceipt(receipt, repository = getDefaultRepository()) {
201
+ const data = loadProtocolData(repository);
202
+ const required = requireStringArray(data.bootReceipt.required_fields, "boot-receipt.required_fields");
203
+ const missing = validateRequiredFields(receipt, required);
204
+ const invalid = validateFieldTypes(receipt, {
205
+ role: "string",
206
+ authority_layer: "string",
207
+ team: "string",
208
+ terminal_locator: "string",
209
+ branch: "string",
210
+ cwd: "string",
211
+ model_harness: "string",
212
+ permission_mode: "string",
213
+ may_implement: "boolean",
214
+ may_qa_accept: "boolean",
215
+ reports_to: "string",
216
+ write_scope: "string_array",
217
+ evidence_path: "string",
218
+ current_task: "string"
219
+ });
220
+ const warnings = [];
221
+ if (receipt.may_implement === true && receipt.may_qa_accept === true) {
222
+ invalid.push("may_qa_accept");
223
+ warnings.push("same receipt grants both implementation and QA acceptance authority");
224
+ }
225
+ if (typeof receipt.model_harness === "string" && /token|key|secret/i.test(receipt.model_harness)) {
226
+ warnings.push("model_harness appears to contain secret-like wording");
227
+ }
228
+ return buildValidationResult(missing, invalid, warnings);
229
+ }
230
+ export function validateTeamManifest(manifest, repository = getDefaultRepository()) {
231
+ const data = loadProtocolData(repository);
232
+ const required = requireStringArray(data.teamManifest.required_fields, "team-manifest.required_fields");
233
+ const missing = validateRequiredFields(manifest, required);
234
+ const invalid = validateFieldTypes(manifest, {
235
+ session_id: "string",
236
+ topology: "object",
237
+ executive_office: "string_array",
238
+ development_pods: "string_array",
239
+ odin_mesh: "object",
240
+ model_profile: "object",
241
+ handoff_sources: "string_array",
242
+ startup_objectives: "string_array"
243
+ });
244
+ const warnings = [];
245
+ invalid.push(...validateNonEmptyArrays(manifest, [
246
+ "executive_office",
247
+ "development_pods",
248
+ "handoff_sources",
249
+ "startup_objectives"
250
+ ]));
251
+ if (Array.isArray(manifest.executive_office)) {
252
+ for (const [index, slot] of manifest.executive_office.entries()) {
253
+ if (typeof slot !== "string" || !isVisibleRoleSlot(slot)) {
254
+ invalid.push(`executive_office.${index}`);
255
+ }
256
+ }
257
+ }
258
+ return buildValidationResult(missing, invalid, warnings);
259
+ }
260
+ export function getCloseoutChecklist(mode, repository = getDefaultRepository()) {
261
+ const data = loadProtocolData(repository);
262
+ const modes = requireRecord(data.closeout.modes, "closeout.modes");
263
+ const checklist = modes[mode];
264
+ if (!checklist) {
265
+ throw new Error(`Unknown closeout mode: ${safeErrorText(mode)}`);
266
+ }
267
+ return checklist;
268
+ }
269
+ export function getRuntimeNotice() {
270
+ return {
271
+ inferenceProvider: "none",
272
+ hostedService: false,
273
+ telemetry: false,
274
+ networkCalls: false,
275
+ maintainerPaysForUserInference: false,
276
+ userPaysForHarnessInference: true,
277
+ externalOrchestrationBundled: false,
278
+ notes: [
279
+ "ODIN Sentinel is a local stdio MCP server.",
280
+ "It serves protocol resources and validation tools; it does not proxy model calls.",
281
+ "Model and harness profiles are capability preferences, not hosted inference.",
282
+ "ODIN Sentinel is standalone and does not require any external orchestration repo."
283
+ ]
284
+ };
285
+ }
286
+ export function exportProtocolSnapshot(repository = getDefaultRepository()) {
287
+ const data = loadProtocolData(repository);
288
+ return {
289
+ "ODIN-SNAPSHOT.md": [
290
+ "# ODIN Sentinel Protocol Snapshot",
291
+ "",
292
+ `Version: ${VERSION}`,
293
+ "",
294
+ "Prefer the MCP server as the source of truth. This snapshot is a fallback export.",
295
+ "",
296
+ data.protocol
297
+ ].join("\n"),
298
+ "protocol/roles.yaml": YAML.stringify(data.roles),
299
+ "protocol/topology.yaml": YAML.stringify(data.topology),
300
+ "protocol/model-profiles.yaml": YAML.stringify(data.modelProfiles),
301
+ "protocol/closeout.yaml": YAML.stringify(data.closeout),
302
+ "protocol/delegation.yaml": YAML.stringify(data.delegation),
303
+ "protocol/receipts/boot-receipt.yaml": YAML.stringify(data.bootReceipt),
304
+ "protocol/receipts/team-manifest.yaml": YAML.stringify(data.teamManifest)
305
+ };
306
+ }
307
+ export function createProtocolService(repository = createFileProtocolRepository()) {
308
+ return {
309
+ protocolPath: (...segments) => repository.path(...segments),
310
+ loadProtocolData: () => loadProtocolData(repository),
311
+ getRoleProfile: (role) => getRoleProfile(role, repository),
312
+ getStartupPacket: (input = {}) => getStartupPacket(input, repository),
313
+ getDelegationPacket,
314
+ validateDelegationPacket: (packet) => validateDelegationPacket(packet, repository),
315
+ validateBootReceipt: (receipt) => validateBootReceipt(receipt, repository),
316
+ validateTeamManifest: (manifest) => validateTeamManifest(manifest, repository),
317
+ getCloseoutChecklist: (mode) => getCloseoutChecklist(mode, repository),
318
+ getRuntimeNotice,
319
+ exportProtocolSnapshot: () => exportProtocolSnapshot(repository)
320
+ };
321
+ }
322
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/protocol/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export type ValidationResult = {
2
+ valid: boolean;
3
+ missing: string[];
4
+ invalid: string[];
5
+ warnings: string[];
6
+ };
7
+ type FieldKind = "string" | "boolean" | "string_array" | "object";
8
+ export declare function asRecord(value: unknown): Record<string, unknown>;
9
+ export declare function requireRecord(value: unknown, label: string): Record<string, unknown>;
10
+ export declare function requireStringArray(value: unknown, label: string): string[];
11
+ export declare function buildValidationResult(missing: string[], invalid: string[], warnings?: string[]): ValidationResult;
12
+ export declare function validateRequiredFields(value: Record<string, unknown>, requiredFields: string[]): string[];
13
+ export declare function validateFieldTypes(value: Record<string, unknown>, expected: Record<string, FieldKind>): string[];
14
+ export declare function validateNonEmptyArrays(value: Record<string, unknown>, fields: string[]): string[];
15
+ export declare function isVisibleRoleSlot(value: string): boolean;
16
+ export {};
@@ -0,0 +1,56 @@
1
+ export function asRecord(value) {
2
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
3
+ }
4
+ export function requireRecord(value, label) {
5
+ if (value && typeof value === "object" && !Array.isArray(value)) {
6
+ return value;
7
+ }
8
+ throw new Error(`Invalid protocol data: ${label} must be an object`);
9
+ }
10
+ export function requireStringArray(value, label) {
11
+ if (Array.isArray(value) && value.every((item) => typeof item === "string" && item.trim() !== "")) {
12
+ return value;
13
+ }
14
+ throw new Error(`Invalid protocol data: ${label} must be a string array`);
15
+ }
16
+ export function buildValidationResult(missing, invalid, warnings = []) {
17
+ return {
18
+ valid: missing.length === 0 && invalid.length === 0,
19
+ missing,
20
+ invalid,
21
+ warnings
22
+ };
23
+ }
24
+ export function validateRequiredFields(value, requiredFields) {
25
+ return requiredFields.filter((field) => {
26
+ const current = value[field];
27
+ if (current === undefined || current === null)
28
+ return true;
29
+ if (typeof current === "string" && current.trim() === "")
30
+ return true;
31
+ return false;
32
+ });
33
+ }
34
+ export function validateFieldTypes(value, expected) {
35
+ return Object.entries(expected)
36
+ .filter(([field, kind]) => {
37
+ if (!(field in value) || value[field] === undefined || value[field] === null)
38
+ return false;
39
+ const current = value[field];
40
+ if (kind === "string")
41
+ return typeof current !== "string" || current.trim() === "";
42
+ if (kind === "boolean")
43
+ return typeof current !== "boolean";
44
+ if (kind === "string_array")
45
+ return !Array.isArray(current) || current.some((item) => typeof item !== "string" || item.trim() === "");
46
+ return typeof current !== "object" || Array.isArray(current);
47
+ })
48
+ .map(([field]) => field);
49
+ }
50
+ export function validateNonEmptyArrays(value, fields) {
51
+ return fields.filter((field) => Array.isArray(value[field]) && value[field].length === 0);
52
+ }
53
+ export function isVisibleRoleSlot(value) {
54
+ return /^[A-Z0-9][A-Z0-9_-]*\/[A-Z0-9][A-Z0-9_-]*(?:-\d+)?$/.test(value);
55
+ }
56
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../../src/protocol/validators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const VERSION: string;
@@ -0,0 +1,26 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ function packageJsonCandidates() {
6
+ return [
7
+ join(__dirname, "..", "..", "package.json"),
8
+ join(__dirname, "..", "..", "..", "package.json")
9
+ ];
10
+ }
11
+ function readPackageVersion() {
12
+ for (const path of packageJsonCandidates()) {
13
+ if (!existsSync(path))
14
+ continue;
15
+ const metadata = JSON.parse(readFileSync(path, "utf8"));
16
+ if (typeof metadata.name === "string" &&
17
+ /(^|\/)odin-sentinel$/.test(metadata.name) &&
18
+ typeof metadata.version === "string" &&
19
+ metadata.version.trim() !== "") {
20
+ return metadata.version;
21
+ }
22
+ }
23
+ throw new Error("Could not locate odin-sentinel package version");
24
+ }
25
+ export const VERSION = readPackageVersion();
26
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/protocol/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAOzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,SAAS,qBAAqB;IAC5B,OAAO;QACL,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;QAC3C,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC;KAClD,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB;IACzB,KAAK,MAAM,IAAI,IAAI,qBAAqB,EAAE,EAAE,CAAC;QAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,SAAS;QAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAoB,CAAC;QAC3E,IACE,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ;YACjC,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAC1C,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ;YACpC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAC9B,CAAC;YACD,OAAO,QAAQ,CAAC,OAAO,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC"}