@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,62 @@
1
+ version: 0.2.1
2
+ roles:
3
+ EXEC_PM:
4
+ title: EXEC PM
5
+ layer: executive
6
+ may_implement_default: false
7
+ may_qa_accept_default: false
8
+ purpose: Intent, priority, authorization, escalation, and claim framing.
9
+ EXEC_ODIN:
10
+ title: EXEC ODIN
11
+ layer: meta_control
12
+ may_implement_default: false
13
+ may_qa_accept_default: false
14
+ purpose: Governance health, polling, delivery proof, role boundaries, and closeout hygiene.
15
+ EXEC_ASST:
16
+ title: EXEC ASST
17
+ layer: executive_support
18
+ may_implement_default: false
19
+ may_qa_accept_default: false
20
+ purpose: Ledger, reminders, pane inventory, artifact index, and delivery checks.
21
+ EXEC_RSCH:
22
+ title: EXEC RSCH
23
+ layer: research
24
+ may_implement_default: false
25
+ may_qa_accept_default: false
26
+ purpose: Read-only strategy, alternatives, context recovery, and risk analysis.
27
+ EXEC_QA:
28
+ title: EXEC QA
29
+ layer: quality
30
+ may_implement_default: false
31
+ may_qa_accept_default: true
32
+ purpose: Independent adversarial audit of process, evidence, closure language, and drift.
33
+ TEAM_PM:
34
+ title: TEAM PM
35
+ layer: pod_control
36
+ may_implement_default: false
37
+ may_qa_accept_default: false
38
+ purpose: Pod task routing, worker activation, and reporting.
39
+ TEAM_ODIN:
40
+ title: TEAM ODIN
41
+ layer: meta_control
42
+ may_implement_default: false
43
+ may_qa_accept_default: false
44
+ purpose: Pod health monitoring, polling, blockers, freezes, and lateral ODIN mesh awareness.
45
+ DEV_WORKER:
46
+ title: DEV WORKER
47
+ layer: implementation
48
+ may_implement_default: true
49
+ may_qa_accept_default: false
50
+ purpose: Bounded implementation inside exact write scope with evidence.
51
+ QA_WORKER:
52
+ title: QA WORKER
53
+ layer: quality
54
+ may_implement_default: false
55
+ may_qa_accept_default: true
56
+ purpose: Independent verification of worker evidence and acceptance criteria.
57
+ SHADOW_REVIEWER:
58
+ title: SHADOW REVIEWER
59
+ layer: review
60
+ may_implement_default: false
61
+ may_qa_accept_default: false
62
+ purpose: Independent critique, risk surfacing, and second-pass review.
@@ -0,0 +1,22 @@
1
+ version: 0.2.1
2
+ default_topology:
3
+ executive_office:
4
+ team: A
5
+ slots:
6
+ - A/EXEC-PM
7
+ - A/EXEC-ODIN
8
+ - A/EXEC-ASST
9
+ - A/EXEC-RSCH
10
+ - A/EXEC-QA
11
+ development_pod:
12
+ slots:
13
+ - "{TEAM}/TEAM-PM"
14
+ - "{TEAM}/ODIN"
15
+ - "{TEAM}/DEV-1"
16
+ - "{TEAM}/QA-1"
17
+ - "{TEAM}/SHADOW-1"
18
+ fresh_repo_default_pods: 1
19
+ odin_mesh:
20
+ bootstrap_identity_exchange: true
21
+ health_round_robin_minutes: 10
22
+ aggregator: A/EXEC-ODIN
@@ -0,0 +1,67 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { readdirSync, readFileSync, statSync } from "node:fs";
3
+ import { join } from "node:path";
4
+
5
+ function walk(dir) {
6
+ return readdirSync(dir).flatMap((entry) => {
7
+ const path = join(dir, entry);
8
+ if ([".git", "dist", "node_modules"].includes(entry)) return [];
9
+ if (path === "pnpm-lock.yaml") return [];
10
+ return statSync(path).isDirectory() ? walk(path) : [path];
11
+ });
12
+ }
13
+
14
+ function filesToAudit() {
15
+ try {
16
+ const tracked = execFileSync("git", ["ls-files"], {
17
+ encoding: "utf8",
18
+ stdio: ["ignore", "pipe", "ignore"]
19
+ });
20
+ const untracked = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
21
+ encoding: "utf8",
22
+ stdio: ["ignore", "pipe", "ignore"]
23
+ });
24
+
25
+ return `${tracked}\n${untracked}`
26
+ .split("\n")
27
+ .filter(Boolean)
28
+ .filter((file) => !file.startsWith("pnpm-lock.yaml"));
29
+ } catch {
30
+ return walk(".");
31
+ }
32
+ }
33
+
34
+ const publicFiles = filesToAudit();
35
+
36
+ const forbidden = [
37
+ { name: "macOS home path", pattern: new RegExp(`/${"Users"}/[A-Za-z0-9._-]+/`) },
38
+ { name: "Linux home path", pattern: /\/home\/[A-Za-z0-9._-]+\// },
39
+ { name: "tilde home path", pattern: /~\// },
40
+ { name: "local agent config path", pattern: new RegExp(`\\.${"codex"}|\\.${"claude"}|\\.${"agents"}`, "i") },
41
+ { name: "legacy extension terminology", pattern: new RegExp(`\\b${"sk" + "ill"}\\b|${"SK" + "ILL"}\\.md|export_${"sk" + "ill"}_snapshot`, "i") },
42
+ {
43
+ name: "private project or account marker",
44
+ pattern: new RegExp(
45
+ `\\b(edge-${"agentic"}|Edu${"gentic"}|${"OK" + "OA"}|open_${"protocols"})\\b`,
46
+ "i"
47
+ )
48
+ },
49
+ { name: "secret-looking assignment", pattern: /(api[_-]?key|secret|token|password)\s*[:=]\s*["'][^"']+["']/i }
50
+ ];
51
+
52
+ const findings = [];
53
+
54
+ for (const file of publicFiles) {
55
+ const text = readFileSync(file, "utf8");
56
+ for (const rule of forbidden) {
57
+ if (rule.pattern.test(text)) {
58
+ findings.push(`${file}: ${rule.name}`);
59
+ }
60
+ }
61
+ }
62
+
63
+ if (findings.length > 0) {
64
+ throw new Error(`Public surface audit failed:\n${findings.join("\n")}`);
65
+ }
66
+
67
+ console.log(`Public surface audit PASS: ${publicFiles.length} files checked`);
@@ -0,0 +1,71 @@
1
+ import { execFileSync } from "node:child_process";
2
+
3
+ const output = execFileSync("pnpm", ["pack", "--dry-run", "--json"], {
4
+ encoding: "utf8",
5
+ stdio: ["ignore", "pipe", "pipe"]
6
+ });
7
+
8
+ // pnpm 11 writes JSON directly to stdout (no preamble); pnpm <=10 prefixed
9
+ // it with lifecycle logs. Handle both shapes: take from "\n{" if present, or
10
+ // from the start if output already begins with "{".
11
+ const newlineBrace = output.lastIndexOf("\n{");
12
+ const jsonStart = newlineBrace !== -1 ? newlineBrace + 1 : (output.trimStart().startsWith("{") ? output.indexOf("{") : -1);
13
+ if (jsonStart === -1) {
14
+ throw new Error("pnpm pack did not return JSON metadata");
15
+ }
16
+
17
+ const pack = JSON.parse(output.slice(jsonStart));
18
+ const paths = new Set(pack.files.map((file) => file.path));
19
+
20
+ const requiredProtocolFiles = [
21
+ "protocol/SCP.md",
22
+ "protocol/roles.yaml",
23
+ "protocol/topology.yaml",
24
+ "protocol/model-profiles.yaml",
25
+ "protocol/closeout.yaml",
26
+ "protocol/delegation.yaml",
27
+ "protocol/receipts/boot-receipt.yaml",
28
+ "protocol/receipts/team-manifest.yaml"
29
+ ];
30
+
31
+ const requiredFiles = [
32
+ "dist/src/bin/index.js",
33
+ "dist/src/mcp/server.js",
34
+ "dist/src/protocol/index.js",
35
+ "dist/src/protocol/service.js",
36
+ "dist/src/protocol/repository.js",
37
+ "dist/src/protocol/schemas.js",
38
+ "dist/src/protocol/validators.js",
39
+ "dist/src/protocol/version.js",
40
+ "docs/guides/quick-start.md",
41
+ "docs/guides/recommended-starter-team.md",
42
+ "docs/reference/client-compatibility.md",
43
+ "docs/reference/cost-and-privacy.md",
44
+ "docs/reference/distribution.md",
45
+ "docs/reference/public-surface-audit.md",
46
+ ...requiredProtocolFiles,
47
+ "scripts/audit/public-surface.mjs",
48
+ "scripts/audit/verify-pack.mjs",
49
+ "README.md",
50
+ "LICENSE",
51
+ "package.json"
52
+ ];
53
+
54
+ const missing = requiredFiles.filter((file) => !paths.has(file));
55
+ if (missing.length > 0) {
56
+ throw new Error(`Package is missing required files: ${missing.join(", ")}`);
57
+ }
58
+
59
+ const staleFiles = [
60
+ "dist/src/index.js",
61
+ "dist/src/server.js",
62
+ "dist/src/protocol.js",
63
+ "dist/src/protocol-repository.js",
64
+ "dist/src/validators.js"
65
+ ].filter((file) => paths.has(file));
66
+
67
+ if (staleFiles.length > 0) {
68
+ throw new Error(`Package includes stale build files: ${staleFiles.join(", ")}`);
69
+ }
70
+
71
+ console.log(`Package smoke PASS: ${pack.files.length} files included in ${pack.filename}`);