@bradheitmann/odin-sentinel 0.2.1 → 0.4.2

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 (40) hide show
  1. package/dist/src/mcp/server.js +57 -1
  2. package/dist/src/mcp/server.js.map +1 -1
  3. package/dist/src/protocol/index.d.ts +2 -0
  4. package/dist/src/protocol/index.js +1 -0
  5. package/dist/src/protocol/index.js.map +1 -1
  6. package/dist/src/protocol/repository.d.ts +1 -0
  7. package/dist/src/protocol/repository.js +4 -2
  8. package/dist/src/protocol/repository.js.map +1 -1
  9. package/dist/src/protocol/schemas.d.ts +30 -0
  10. package/dist/src/protocol/schemas.js +30 -0
  11. package/dist/src/protocol/schemas.js.map +1 -1
  12. package/dist/src/protocol/service.js +28 -1
  13. package/dist/src/protocol/service.js.map +1 -1
  14. package/dist/src/protocol/surface-layout.d.ts +29 -0
  15. package/dist/src/protocol/surface-layout.js +136 -0
  16. package/dist/src/protocol/surface-layout.js.map +1 -0
  17. package/dist/src/telemetry/config.d.ts +8 -0
  18. package/dist/src/telemetry/config.js +11 -0
  19. package/dist/src/telemetry/config.js.map +1 -0
  20. package/dist/src/telemetry/index.d.ts +7 -0
  21. package/dist/src/telemetry/index.js +5 -0
  22. package/dist/src/telemetry/index.js.map +1 -0
  23. package/dist/src/telemetry/redactor.d.ts +2 -0
  24. package/dist/src/telemetry/redactor.js +48 -0
  25. package/dist/src/telemetry/redactor.js.map +1 -0
  26. package/dist/src/telemetry/report.d.ts +30 -0
  27. package/dist/src/telemetry/report.js +10 -0
  28. package/dist/src/telemetry/report.js.map +1 -0
  29. package/dist/src/telemetry/submit.d.ts +14 -0
  30. package/dist/src/telemetry/submit.js +50 -0
  31. package/dist/src/telemetry/submit.js.map +1 -0
  32. package/package.json +1 -1
  33. package/protocol/SCP.md +48 -2
  34. package/protocol/bootstrap-skill.md +1488 -0
  35. package/protocol/delegation.yaml +4 -1
  36. package/protocol/receipts/boot-receipt.yaml +17 -0
  37. package/protocol/roles.yaml +106 -1
  38. package/protocol/topology.yaml +35 -1
  39. package/scripts/audit/public-surface.mjs +12 -3
  40. package/scripts/audit/verify-pack.mjs +2 -1
@@ -1,4 +1,4 @@
1
- version: 0.2.1
1
+ version: 0.3.0
2
2
  delegation_contract:
3
3
  required_fields:
4
4
  - receipt_type
@@ -36,3 +36,6 @@ delegation_contract:
36
36
  - Delegation must include exact authority and scope.
37
37
  - Terminal text left in an input bar is not delivery.
38
38
  - QA acceptance cannot be delegated to the same role that implemented the deliverable.
39
+ - Staffing actions (spawn, rename, kill, reassign, move-surface) are the sole authority of A/EXEC-PM and may not be delegated to TEAM PMs or workers.
40
+ - Surface custodianship (new-split, new-surface, move-surface, close-surface) is held exclusively by A/EXEC-PM.
41
+ - TEAM PMs needing more staff must escalate to A/EXEC-PM rather than act.
@@ -21,3 +21,20 @@ recommended_fields:
21
21
  - delegates_to
22
22
  - prohibited_paths
23
23
  - proof_source
24
+ - staffed_by
25
+ - parent_surface_ref
26
+ - column_index
27
+ - team_letter
28
+ staffing_audit:
29
+ description: >-
30
+ For any role outside the executive office (team != "A"), the boot receipt
31
+ must record who staffed the agent (staffed_by) and which CMUX surface it
32
+ occupies (parent_surface_ref, column_index, team_letter). Receipts missing
33
+ these fields on non-exec roles produce ODIN warnings. EXEC PM is the sole
34
+ canonical staffing authority.
35
+ required_for_non_exec_team:
36
+ - staffed_by
37
+ - parent_surface_ref
38
+ - column_index
39
+ - team_letter
40
+ staffed_by_canonical_value: A/EXEC-PM
@@ -1,4 +1,4 @@
1
- version: 0.2.1
1
+ version: 0.3.0
2
2
  roles:
3
3
  EXEC_PM:
4
4
  title: EXEC PM
@@ -6,12 +6,75 @@ roles:
6
6
  may_implement_default: false
7
7
  may_qa_accept_default: false
8
8
  purpose: Intent, priority, authorization, escalation, and claim framing.
9
+ authority:
10
+ sole_staffing_authority:
11
+ active: true
12
+ scope: >-
13
+ A/EXEC-PM is the only role that may spawn, name, kill, rename,
14
+ reassign, or move agents on any team. No TEAM PM may staff its own
15
+ pod or any other pod. Worker roles never staff.
16
+ surface_custodianship:
17
+ sole_custodian: true
18
+ includes:
19
+ - cmux new-split
20
+ - cmux new-surface
21
+ - cmux move-surface
22
+ - cmux close-surface
23
+ - cmux drag-surface-to-split
24
+ pre_staffing_gate:
25
+ required: true
26
+ steps:
27
+ - call odin.compute_surface_layout for the target team count
28
+ - call odin.compute_surface_layout_gate to retrieve the transition checklist
29
+ - execute the required cmux split operations
30
+ - confirm each new surface is empty and addressable via cmux list-pane-surfaces
31
+ - dispatch the spawn only after surface confirmation
32
+ violation_class: protocol_breach_high
33
+ meta_governance:
34
+ role_in_org_strategy: org_strategy_dev
35
+ supervisor: A/EXEC-ODIN
9
36
  EXEC_ODIN:
10
37
  title: EXEC ODIN
11
38
  layer: meta_control
12
39
  may_implement_default: false
13
40
  may_qa_accept_default: false
14
41
  purpose: Governance health, polling, delivery proof, role boundaries, and closeout hygiene.
42
+ authority:
43
+ intervention_authority:
44
+ may_issue_halt: true
45
+ halt_targets:
46
+ - A/EXEC-PM
47
+ - any TEAM PM
48
+ - any worker on any pod
49
+ - any ODIN agent
50
+ halt_triggers:
51
+ - staffing without the surface layout gate
52
+ - hidden agent creation
53
+ - QA acceptance by implementer
54
+ - context window exceeds hard threshold without compaction or handoff
55
+ - boot receipt missing required staffing audit fields
56
+ - team manifest topology drift from default_topology contract
57
+ receiving_role_obligation: >-
58
+ The role receiving a HALT directive must stop the offending action
59
+ and reply with a remediation plan before resuming. Continuing past a
60
+ HALT without remediation is itself a protocol breach.
61
+ health_escalation:
62
+ round_robin_minutes: 10
63
+ thresholds:
64
+ missed_heartbeat_warn: 1
65
+ missed_heartbeat_escalate: 2
66
+ missed_heartbeat_lockdown: 3
67
+ lockdown_effect: >-
68
+ On lockdown, the affected agent is suspended from new dispatch and
69
+ A/EXEC-PM is required to restaff or close the surface.
70
+ context_window_budgeting:
71
+ per_agent_soft_pct: 70
72
+ per_agent_hard_pct: 90
73
+ on_soft: warn_and_request_compaction
74
+ on_hard: force_handoff_or_lockdown
75
+ mesh_aggregator: A/EXEC-ODIN
76
+ meta_governance:
77
+ role_in_org_strategy: org_strategy_qa
15
78
  EXEC_ASST:
16
79
  title: EXEC ASST
17
80
  layer: executive_support
@@ -36,12 +99,54 @@ roles:
36
99
  may_implement_default: false
37
100
  may_qa_accept_default: false
38
101
  purpose: Pod task routing, worker activation, and reporting.
102
+ forbidden_actions:
103
+ - spawn agents on own pod or any other pod
104
+ - rename, kill, or reassign agents on own pod
105
+ - split, move, or close any surface
106
+ - accept own pod's QA work
107
+ - delegate staffing or surface operations to workers
108
+ constraint_rationale: >-
109
+ Staffing and surface custodianship are the sole authority of A/EXEC-PM.
110
+ Any TEAM PM staffing or surface action without an explicit A/EXEC-PM
111
+ directive is a protocol breach and will be HALTed by the supervising
112
+ ODIN role.
113
+ escalation_path:
114
+ need_more_staff: report to A/EXEC-PM with rationale; do not act
115
+ surface_misconfigured: report to A/EXEC-PM and own pod's ODIN
39
116
  TEAM_ODIN:
40
117
  title: TEAM ODIN
41
118
  layer: meta_control
42
119
  may_implement_default: false
43
120
  may_qa_accept_default: false
44
121
  purpose: Pod health monitoring, polling, blockers, freezes, and lateral ODIN mesh awareness.
122
+ authority:
123
+ intervention_authority:
124
+ may_issue_halt: true
125
+ halt_targets:
126
+ - own pod TEAM PM
127
+ - own pod workers
128
+ halt_triggers:
129
+ - QA acceptance by implementer
130
+ - context window exceeds hard threshold without compaction
131
+ - delivery without evidence
132
+ - hidden subagent creation
133
+ receiving_role_obligation: >-
134
+ Same as EXEC_ODIN. Pod role receiving a HALT must stop and remediate
135
+ before resuming.
136
+ health_escalation:
137
+ reports_to: A/EXEC-ODIN via odin_mesh aggregator
138
+ thresholds:
139
+ missed_heartbeat_warn: 1
140
+ missed_heartbeat_escalate: 2
141
+ missed_heartbeat_lockdown: 3
142
+ context_window_budgeting:
143
+ per_agent_soft_pct: 70
144
+ per_agent_hard_pct: 90
145
+ on_soft: warn_and_request_compaction
146
+ on_hard: force_handoff_or_lockdown
147
+ meta_governance:
148
+ role_in_org_strategy: org_strategy_qa
149
+ reports_to: A/EXEC-ODIN
45
150
  DEV_WORKER:
46
151
  title: DEV WORKER
47
152
  layer: implementation
@@ -1,4 +1,4 @@
1
- version: 0.2.1
1
+ version: 0.3.0
2
2
  default_topology:
3
3
  executive_office:
4
4
  team: A
@@ -20,3 +20,37 @@ default_topology:
20
20
  bootstrap_identity_exchange: true
21
21
  health_round_robin_minutes: 10
22
22
  aggregator: A/EXEC-ODIN
23
+ surface_layout:
24
+ description: >-
25
+ Canonical CMUX surface layout rule for EXEC PM. Teams arrive as letters
26
+ (Team A is executive; Team B onward are development pods). Columns are
27
+ equal width. Surfaces stack vertically inside a column with at most two
28
+ surfaces per column. Team A always occupies column 0. When the team count
29
+ is odd and at least 3, column 0 holds only Team A (the "tall column").
30
+ rules:
31
+ max_surfaces_per_column: 2
32
+ column_widths: equal
33
+ exec_team_column: 0
34
+ tall_column_when_odd_team: A
35
+ custodianship:
36
+ sole_custodian: A/EXEC-PM
37
+ includes:
38
+ - cmux new-split
39
+ - cmux new-surface
40
+ - cmux move-surface
41
+ - cmux close-surface
42
+ pre_staffing_gate: >-
43
+ Before adding any agent beyond A/EXEC, EXEC PM must (1) call
44
+ odin.compute_surface_layout for teamCount=N+1, (2) execute the splits
45
+ required to reach that layout via cmux, (3) confirm each new surface
46
+ is empty and addressable via cmux list-pane-surfaces, and only then
47
+ (4) dispatch the spawn to the newly created surface.
48
+ reference_layouts:
49
+ teams_1: "[A]"
50
+ teams_2: "[A] [B]"
51
+ teams_3: "[A] [B/C]"
52
+ teams_4: "[A/D] [B/C]"
53
+ teams_5: "[A] [B/C] [D/E]"
54
+ teams_6: "[A/F] [B/C] [D/E]"
55
+ teams_7: "[A] [B/C] [D/E] [F/G]"
56
+ teams_8: "[A/H] [B/C] [D/E] [F/G]"
@@ -33,12 +33,20 @@ function filesToAudit() {
33
33
 
34
34
  const publicFiles = filesToAudit();
35
35
 
36
+ // Per-rule file exemptions. The bundled bootstrap protocol document is
37
+ // user-authored content that legitimately references multiple agent harness
38
+ // config dirs (the dot-prefixed home subdirs of codex, claude, and friends)
39
+ // and uses tilde home paths in its install instructions.
40
+ const BUNDLED_DOC = new Set([
41
+ "protocol/bootstrap-" + "sk" + "ill.md",
42
+ "plugins/sentinel-coordination-protocol/" + "sk" + "ills/sentinel-coordination-protocol/SK" + "ILL.md"
43
+ ]);
44
+
36
45
  const forbidden = [
37
46
  { name: "macOS home path", pattern: new RegExp(`/${"Users"}/[A-Za-z0-9._-]+/`) },
38
47
  { 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") },
48
+ { name: "tilde home path", pattern: /~\//, exemptFiles: BUNDLED_DOC },
49
+ { name: "local agent config path", pattern: new RegExp(`\\.${"codex"}|\\.${"claude"}|\\.${"agents"}`, "i"), exemptFiles: BUNDLED_DOC },
42
50
  {
43
51
  name: "private project or account marker",
44
52
  pattern: new RegExp(
@@ -54,6 +62,7 @@ const findings = [];
54
62
  for (const file of publicFiles) {
55
63
  const text = readFileSync(file, "utf8");
56
64
  for (const rule of forbidden) {
65
+ if (rule.exemptFiles?.has(file)) continue;
57
66
  if (rule.pattern.test(text)) {
58
67
  findings.push(`${file}: ${rule.name}`);
59
68
  }
@@ -25,7 +25,8 @@ const requiredProtocolFiles = [
25
25
  "protocol/closeout.yaml",
26
26
  "protocol/delegation.yaml",
27
27
  "protocol/receipts/boot-receipt.yaml",
28
- "protocol/receipts/team-manifest.yaml"
28
+ "protocol/receipts/team-manifest.yaml",
29
+ "protocol/bootstrap-skill.md"
29
30
  ];
30
31
 
31
32
  const requiredFiles = [