@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
package/protocol/delegation.yaml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
version: 0.
|
|
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
|
package/protocol/roles.yaml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
version: 0.
|
|
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
|
package/protocol/topology.yaml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
version: 0.
|
|
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,19 @@ function filesToAudit() {
|
|
|
33
33
|
|
|
34
34
|
const publicFiles = filesToAudit();
|
|
35
35
|
|
|
36
|
+
// The bundled bootstrap protocol document references agent harness config
|
|
37
|
+
// directories and tilde home paths as part of its install guidance. The
|
|
38
|
+
// path-style rules below skip these files; the rest of the rules still apply.
|
|
39
|
+
const BUNDLED_DOC = new Set([
|
|
40
|
+
"protocol/bootstrap-" + "sk" + "ill.md",
|
|
41
|
+
"plugins/sentinel-coordination-protocol/" + "sk" + "ills/sentinel-coordination-protocol/SK" + "ILL.md"
|
|
42
|
+
]);
|
|
43
|
+
|
|
36
44
|
const forbidden = [
|
|
37
45
|
{ name: "macOS home path", pattern: new RegExp(`/${"Users"}/[A-Za-z0-9._-]+/`) },
|
|
38
46
|
{ 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") },
|
|
47
|
+
{ name: "tilde home path", pattern: /~\//, exemptFiles: BUNDLED_DOC },
|
|
48
|
+
{ name: "local agent config path", pattern: new RegExp(`\\.${"codex"}|\\.${"claude"}|\\.${"agents"}`, "i"), exemptFiles: BUNDLED_DOC },
|
|
42
49
|
{
|
|
43
50
|
name: "private project or account marker",
|
|
44
51
|
pattern: new RegExp(
|
|
@@ -54,6 +61,7 @@ const findings = [];
|
|
|
54
61
|
for (const file of publicFiles) {
|
|
55
62
|
const text = readFileSync(file, "utf8");
|
|
56
63
|
for (const rule of forbidden) {
|
|
64
|
+
if (rule.exemptFiles?.has(file)) continue;
|
|
57
65
|
if (rule.pattern.test(text)) {
|
|
58
66
|
findings.push(`${file}: ${rule.name}`);
|
|
59
67
|
}
|
|
@@ -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 = [
|