@bradheitmann/odin-sentinel 0.2.1 → 0.4.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 +20 -15
- package/dist/src/mcp/server.js +57 -1
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/protocol/index.d.ts +2 -0
- package/dist/src/protocol/index.js +1 -0
- package/dist/src/protocol/index.js.map +1 -1
- package/dist/src/protocol/repository.d.ts +1 -0
- package/dist/src/protocol/repository.js +4 -2
- package/dist/src/protocol/repository.js.map +1 -1
- package/dist/src/protocol/schemas.d.ts +30 -0
- package/dist/src/protocol/schemas.js +30 -0
- package/dist/src/protocol/schemas.js.map +1 -1
- package/dist/src/protocol/service.js +28 -1
- package/dist/src/protocol/service.js.map +1 -1
- package/dist/src/protocol/surface-layout.d.ts +29 -0
- package/dist/src/protocol/surface-layout.js +136 -0
- package/dist/src/protocol/surface-layout.js.map +1 -0
- package/dist/src/telemetry/config.d.ts +8 -0
- package/dist/src/telemetry/config.js +11 -0
- package/dist/src/telemetry/config.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +7 -0
- package/dist/src/telemetry/index.js +5 -0
- package/dist/src/telemetry/index.js.map +1 -0
- package/dist/src/telemetry/redactor.d.ts +2 -0
- package/dist/src/telemetry/redactor.js +45 -0
- package/dist/src/telemetry/redactor.js.map +1 -0
- package/dist/src/telemetry/report.d.ts +30 -0
- package/dist/src/telemetry/report.js +10 -0
- package/dist/src/telemetry/report.js.map +1 -0
- package/dist/src/telemetry/submit.d.ts +14 -0
- package/dist/src/telemetry/submit.js +50 -0
- package/dist/src/telemetry/submit.js.map +1 -0
- package/docs/reference/distribution.md +15 -7
- package/package.json +1 -1
- package/protocol/SCP.md +48 -2
- package/protocol/bootstrap-skill.md +1488 -0
- package/protocol/delegation.yaml +4 -1
- package/protocol/receipts/boot-receipt.yaml +17 -0
- package/protocol/roles.yaml +106 -1
- package/protocol/topology.yaml +35 -1
- package/scripts/audit/public-surface.mjs +11 -3
- package/scripts/audit/verify-pack.mjs +2 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/telemetry/config.ts"],"names":[],"mappings":"AAMA,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAEnD,MAAM,UAAU,mBAAmB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACtE,MAAM,GAAG,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AACpD,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { readTelemetryConfig, ENDPOINT_ENV_VAR } from "./config.js";
|
|
2
|
+
export type { TelemetryConfig } from "./config.js";
|
|
3
|
+
export { redactString, redactPayload } from "./redactor.js";
|
|
4
|
+
export { compileSessionReport } from "./report.js";
|
|
5
|
+
export type { HaltEntry, ModelSignal, SessionReport, SessionReportInput, ViolationEntry } from "./report.js";
|
|
6
|
+
export { submitSessionReport } from "./submit.js";
|
|
7
|
+
export type { SubmitOptions, SubmitResult } from "./submit.js";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { readTelemetryConfig, ENDPOINT_ENV_VAR } from "./config.js";
|
|
2
|
+
export { redactString, redactPayload } from "./redactor.js";
|
|
3
|
+
export { compileSessionReport } from "./report.js";
|
|
4
|
+
export { submitSessionReport } from "./submit.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAQnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Pre-redaction for outbound payloads. Strips file-system paths, email
|
|
2
|
+
// addresses, and common secret token shapes. Intentionally conservative:
|
|
3
|
+
// over-redacts rather than under-redacts.
|
|
4
|
+
const SLASH = "/";
|
|
5
|
+
const BACKSLASH = "\\";
|
|
6
|
+
const HOME_USERS_RE = new RegExp(`${SLASH}${"U" + "sers"}${SLASH}[^${SLASH}\\s"']+`, "g");
|
|
7
|
+
const HOME_LINUX_RE = new RegExp(`${SLASH}${"ho" + "me"}${SLASH}[^${SLASH}\\s"']+`, "g");
|
|
8
|
+
const HOME_WIN_RE = new RegExp(`${BACKSLASH}${BACKSLASH}${"U" + "sers"}${BACKSLASH}${BACKSLASH}[^${BACKSLASH}\\s"']+`, "g");
|
|
9
|
+
const EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
|
|
10
|
+
// Common secret-token shapes. The set is conservative; readers should add
|
|
11
|
+
// project-specific patterns if they ship custom token prefixes.
|
|
12
|
+
const TOKEN_PATTERNS = [
|
|
13
|
+
/\bsk-[a-zA-Z0-9]{20,}\b/g,
|
|
14
|
+
/\blin_api_[a-zA-Z0-9]{16,}\b/g,
|
|
15
|
+
/\bghp_[a-zA-Z0-9]{20,}\b/g,
|
|
16
|
+
/\bgho_[a-zA-Z0-9]{20,}\b/g,
|
|
17
|
+
/\bAIza[0-9A-Za-z_-]{30,}\b/g,
|
|
18
|
+
/\bxox[bp]-[a-zA-Z0-9-]{20,}\b/g
|
|
19
|
+
];
|
|
20
|
+
export function redactString(value) {
|
|
21
|
+
let result = value
|
|
22
|
+
.replace(HOME_USERS_RE, "<HOME>")
|
|
23
|
+
.replace(HOME_LINUX_RE, "<HOME>")
|
|
24
|
+
.replace(HOME_WIN_RE, "<HOME>")
|
|
25
|
+
.replace(EMAIL_RE, "<EMAIL>");
|
|
26
|
+
for (const pattern of TOKEN_PATTERNS) {
|
|
27
|
+
result = result.replace(pattern, "<TOKEN>");
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
export function redactPayload(payload) {
|
|
32
|
+
if (typeof payload === "string")
|
|
33
|
+
return redactString(payload);
|
|
34
|
+
if (Array.isArray(payload))
|
|
35
|
+
return payload.map((entry) => redactPayload(entry));
|
|
36
|
+
if (payload && typeof payload === "object") {
|
|
37
|
+
const result = {};
|
|
38
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
39
|
+
result[key] = redactPayload(value);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
return payload;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=redactor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redactor.js","sourceRoot":"","sources":["../../../src/telemetry/redactor.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,yEAAyE;AACzE,0CAA0C;AAE1C,MAAM,KAAK,GAAG,GAAG,CAAC;AAClB,MAAM,SAAS,GAAG,IAAI,CAAC;AAEvB,MAAM,aAAa,GAAG,IAAI,MAAM,CAC9B,GAAG,KAAK,GAAG,GAAG,GAAG,MAAM,GAAG,KAAK,KAAK,KAAK,SAAS,EAClD,GAAG,CACJ,CAAC;AACF,MAAM,aAAa,GAAG,IAAI,MAAM,CAC9B,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,KAAK,KAAK,SAAS,EACjD,GAAG,CACJ,CAAC;AACF,MAAM,WAAW,GAAG,IAAI,MAAM,CAC5B,GAAG,SAAS,GAAG,SAAS,GAAG,GAAG,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,KAAK,SAAS,SAAS,EACtF,GAAG,CACJ,CAAC;AAEF,MAAM,QAAQ,GAAG,iDAAiD,CAAC;AAEnE,0EAA0E;AAC1E,gEAAgE;AAChE,MAAM,cAAc,GAAa;IAC/B,0BAA0B;IAC1B,+BAA+B;IAC/B,2BAA2B;IAC3B,2BAA2B;IAC3B,6BAA6B;IAC7B,gCAAgC;CACjC,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,IAAI,MAAM,GAAG,KAAK;SACf,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC;SAChC,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC;SAChC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC;SAC9B,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChC,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;QACrC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAI,OAAU;IACzC,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,YAAY,CAAC,OAAO,CAAiB,CAAC;IAC9E,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAiB,CAAC;IAChG,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC3C,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAkC,CAAC,EAAE,CAAC;YAC9E,MAAM,CAAC,GAAG,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,MAAsB,CAAC;IAChC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type ViolationEntry = {
|
|
2
|
+
class: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
};
|
|
5
|
+
export type HaltEntry = {
|
|
6
|
+
source: string;
|
|
7
|
+
target: string;
|
|
8
|
+
trigger: string;
|
|
9
|
+
};
|
|
10
|
+
export type ModelSignal = {
|
|
11
|
+
role: string;
|
|
12
|
+
model: string;
|
|
13
|
+
violations: number;
|
|
14
|
+
};
|
|
15
|
+
export type SessionReportInput = {
|
|
16
|
+
teamCount: number;
|
|
17
|
+
violations: ViolationEntry[];
|
|
18
|
+
halts: HaltEntry[];
|
|
19
|
+
layoutDriftEvents: number;
|
|
20
|
+
peakContextPct: number;
|
|
21
|
+
closeoutClean: boolean;
|
|
22
|
+
modelSignals: ModelSignal[];
|
|
23
|
+
};
|
|
24
|
+
export type SessionReport = SessionReportInput & {
|
|
25
|
+
version: string;
|
|
26
|
+
compiledAt: string;
|
|
27
|
+
violationCount: number;
|
|
28
|
+
haltCount: number;
|
|
29
|
+
};
|
|
30
|
+
export declare function compileSessionReport(input: SessionReportInput, version: string): SessionReport;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/telemetry/report.ts"],"names":[],"mappings":"AAkCA,MAAM,UAAU,oBAAoB,CAAC,KAAyB,EAAE,OAAe;IAC7E,OAAO;QACL,GAAG,KAAK;QACR,OAAO;QACP,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,cAAc,EAAE,KAAK,CAAC,UAAU,CAAC,MAAM;QACvC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM;KAC9B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type TelemetryConfig } from "./config.js";
|
|
2
|
+
export type SubmitResult = {
|
|
3
|
+
submitted: boolean;
|
|
4
|
+
endpoint?: string;
|
|
5
|
+
status?: number;
|
|
6
|
+
id?: string;
|
|
7
|
+
reason?: string;
|
|
8
|
+
};
|
|
9
|
+
export type SubmitOptions = {
|
|
10
|
+
config?: TelemetryConfig;
|
|
11
|
+
fetchImpl?: typeof fetch;
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
};
|
|
14
|
+
export declare function submitSessionReport(report: Record<string, unknown>, options?: SubmitOptions): Promise<SubmitResult>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { readTelemetryConfig } from "./config.js";
|
|
2
|
+
import { redactPayload } from "./redactor.js";
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 8000;
|
|
4
|
+
export async function submitSessionReport(report, options = {}) {
|
|
5
|
+
const config = options.config ?? readTelemetryConfig();
|
|
6
|
+
if (!config.enabled || !config.endpoint) {
|
|
7
|
+
return {
|
|
8
|
+
submitted: false,
|
|
9
|
+
reason: "telemetry not configured (set ODIN_TELEMETRY_ENDPOINT to opt in)"
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const redacted = redactPayload(report);
|
|
13
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
14
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
15
|
+
const controller = new AbortController();
|
|
16
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetchImpl(config.endpoint, {
|
|
19
|
+
method: "POST",
|
|
20
|
+
headers: { "content-type": "application/json" },
|
|
21
|
+
body: JSON.stringify(redacted),
|
|
22
|
+
signal: controller.signal
|
|
23
|
+
});
|
|
24
|
+
let parsed = {};
|
|
25
|
+
try {
|
|
26
|
+
parsed = (await response.json());
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// non-JSON response is acceptable; status code is the source of truth
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
submitted: response.ok,
|
|
33
|
+
endpoint: config.endpoint,
|
|
34
|
+
status: response.status,
|
|
35
|
+
id: typeof parsed.id === "string" ? parsed.id : undefined,
|
|
36
|
+
reason: response.ok ? undefined : `HTTP ${response.status}`
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
return {
|
|
41
|
+
submitted: false,
|
|
42
|
+
endpoint: config.endpoint,
|
|
43
|
+
reason: error instanceof Error ? error.message : "network error"
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=submit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"submit.js","sourceRoot":"","sources":["../../../src/telemetry/submit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAwB,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAgB9C,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAA+B,EAC/B,UAAyB,EAAE;IAE3B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,mBAAmB,EAAE,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxC,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,MAAM,EAAE,kEAAkE;SAC3E,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAE1D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAE9D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;YAC9B,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,IAAI,MAAM,GAAmC,EAAE,CAAC;QAChD,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmC,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,sEAAsE;QACxE,CAAC;QAED,OAAO;YACL,SAAS,EAAE,QAAQ,CAAC,EAAE;YACtB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,EAAE,EAAE,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;YACzD,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,QAAQ,CAAC,MAAM,EAAE;SAC5D,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;SACjE,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -5,26 +5,34 @@ an npm package that ships prebuilt JavaScript and protocol files.
|
|
|
5
5
|
|
|
6
6
|
## Recommended Install Path
|
|
7
7
|
|
|
8
|
-
After publishing:
|
|
9
|
-
|
|
10
8
|
```bash
|
|
11
|
-
|
|
9
|
+
npm i -g @bradheitmann/odin-sentinel
|
|
12
10
|
```
|
|
13
11
|
|
|
14
|
-
MCP client configuration can then use:
|
|
12
|
+
MCP client configuration can then use the installed binary directly:
|
|
15
13
|
|
|
16
14
|
```json
|
|
17
15
|
{
|
|
18
16
|
"mcpServers": {
|
|
19
17
|
"odin-sentinel": {
|
|
20
|
-
"command": "
|
|
21
|
-
"args": ["dlx", "odin-sentinel"]
|
|
18
|
+
"command": "odin-sentinel-mcp"
|
|
22
19
|
}
|
|
23
20
|
}
|
|
24
21
|
}
|
|
25
22
|
```
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
For zero-install via `npx`:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"mcpServers": {
|
|
29
|
+
"odin-sentinel": {
|
|
30
|
+
"command": "npx",
|
|
31
|
+
"args": ["-y", "-p", "@bradheitmann/odin-sentinel", "odin-sentinel-mcp"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
28
36
|
|
|
29
37
|
## Local Clone Path
|
|
30
38
|
|
package/package.json
CHANGED
package/protocol/SCP.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# ODIN Sentinel Coordination Protocol
|
|
2
2
|
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
|
|
5
5
|
ODIN Sentinel is a portable coordination layer for visible multi-agent teams.
|
|
6
6
|
SCP means Sentinel Coordination Protocol in this repository. It is not Secure
|
|
7
7
|
Copy.
|
|
8
8
|
It provides generic role contracts, startup packets, receipt validation, team
|
|
9
9
|
manifest validation, native visible-role delegation packets, closeout
|
|
10
|
-
checklists, and fallback protocol snapshots through an
|
|
10
|
+
checklists, surface layout rules, and fallback protocol snapshots through an
|
|
11
|
+
MCP server.
|
|
11
12
|
|
|
12
13
|
## Principles
|
|
13
14
|
|
|
@@ -19,12 +20,23 @@ checklists, and fallback protocol snapshots through an MCP server.
|
|
|
19
20
|
- Handoffs, closeout, and restart packets must be explicit.
|
|
20
21
|
- Secrets are never printed or embedded in receipts.
|
|
21
22
|
- Delegation is native to the server and must not require an external extension.
|
|
23
|
+
- Staffing and surface custodianship are the sole authority of A/EXEC-PM.
|
|
22
24
|
|
|
23
25
|
## Startup Defaults
|
|
24
26
|
|
|
25
27
|
Fresh startup creates an executive office and one development pod unless the
|
|
26
28
|
user or a handoff requests another topology.
|
|
27
29
|
|
|
30
|
+
## Surface Layout
|
|
31
|
+
|
|
32
|
+
CMUX surface organization is contractually fixed by `surface_layout` in
|
|
33
|
+
`topology.yaml` and the `odin.compute_surface_layout` tool. All columns are
|
|
34
|
+
equal width. At most two surfaces stack inside any column. Team A always
|
|
35
|
+
occupies column 0; when the team count is odd and at least 3, column 0 holds
|
|
36
|
+
only Team A (the tall column). EXEC PM must call
|
|
37
|
+
`odin.compute_surface_layout` (and its gate variant) before any spawn beyond
|
|
38
|
+
A/EXEC and must reach the target layout via CMUX splits before dispatching.
|
|
39
|
+
|
|
28
40
|
## Closeout Defaults
|
|
29
41
|
|
|
30
42
|
Closeout supports two modes:
|
|
@@ -32,3 +44,37 @@ Closeout supports two modes:
|
|
|
32
44
|
- `PARK_FOR_CONTINUITY`: keep role slots open and park occupants.
|
|
33
45
|
- `FULL_SESSION_SHUTDOWN`: quit occupants, verify exit, and close panes except
|
|
34
46
|
the final user-designated surface.
|
|
47
|
+
|
|
48
|
+
## Meta-Governance
|
|
49
|
+
|
|
50
|
+
ODIN Sentinel applies the same Dev/QA contract that governs code execution to
|
|
51
|
+
the execution of organizational strategy itself.
|
|
52
|
+
|
|
53
|
+
In code work:
|
|
54
|
+
|
|
55
|
+
- DEV implements bounded scope and produces evidence.
|
|
56
|
+
- QA verifies independently and does not accept their own work.
|
|
57
|
+
- TEAM PM routes tasks to workers; A/EXEC-PM authorizes and frames claims.
|
|
58
|
+
|
|
59
|
+
In organizational work:
|
|
60
|
+
|
|
61
|
+
- TEAM PM is the Dev of org strategy. It implements the staffing, surfaces,
|
|
62
|
+
and delegations issued by A/EXEC-PM (subject to the constraint that TEAM PM
|
|
63
|
+
cannot self-staff).
|
|
64
|
+
- A/EXEC-PM is the dispatcher of org strategy. It issues the org orders and
|
|
65
|
+
owns staffing and surface custodianship exclusively.
|
|
66
|
+
- ODIN agents are the QA of org strategy. They audit whether A/EXEC-PM's org
|
|
67
|
+
orders are executed correctly, whether surface custodianship is honored,
|
|
68
|
+
whether protocol adherence holds, whether context windows are healthy, and
|
|
69
|
+
whether contracts remain accountable.
|
|
70
|
+
|
|
71
|
+
ODIN agents hold intervention authority. When A/EXEC-PM, any TEAM PM, or any
|
|
72
|
+
worker violates the contract (staffing without the surface gate, hidden agent
|
|
73
|
+
creation, same-role QA acceptance, context window over hard threshold without
|
|
74
|
+
compaction), the supervising ODIN role MAY issue a HALT directive. The
|
|
75
|
+
receiving role is contractually obligated to honor the HALT and reply with a
|
|
76
|
+
remediation plan before resuming. Continuing past a HALT without remediation
|
|
77
|
+
is itself a protocol breach.
|
|
78
|
+
|
|
79
|
+
This recursion is why the same protocol governs both code work and
|
|
80
|
+
organizational work without growing new vocabulary.
|