Edoxen is a set of information models used for representing resolution and decision information. They are designed to provide a structured way to model formal resolutions, including their metadata, actions, considerations, and approvals.
The edoxen gem provides a Ruby library for working with these models,
allowing users to create, manipulate, and serialize resolution data in a
structured format. It is built on top of the lutaml-model serialization
framework, which provides a flexible and extensible way to define data models
and serialize them to YAML or JSON formats.
This library is particularly useful for standards organizations, committees, and governance bodies that need to maintain structured records of their decision-making processes.
"Edoxen" is how all resolutions of Ancient Athens started.
"It was the opinion of… (the people and city that…)"
The word "edoxen" originates from the Ancient Greek word edokeō (ἔδοξεν), meaning "it was the opinion of" or "it seemed good to". This term was used in the context of formal resolutions and decisions made by the Athenian assembly, reflecting the collective will and judgment of the citizens.
-
Classes for modeling resolutions, actions, considerations, and approvals
-
Support for resolution collections with rich metadata
-
Structured date handling with semantic meaning (meeting, decision, effective dates)
-
YAML and JSON serialization with round-trip compatibility
-
Structured identifiers and meeting information
-
Resolution relationships and dependencies
-
Integration with the
lutaml-modelserialization framework -
Comprehensive YAML schema for validation
-
Command-line interface for validation and processing
-
Real-world compatibility with real-world resolutions (e.g., ISO/TCs, CIPM)
Add this line to your application’s Gemfile:
gem 'edoxen'And then execute:
$ bundle installOr install it yourself as:
$ gem install edoxenThe edoxen command provides utilities for working with resolution data files.
Get help on available commands:
$ edoxen help
Commands:
edoxen help [COMMAND] # Describe available commands or one specific command
edoxen normalize YAML_FILE_PATTERN # Normalize YAML files using Edoxen schema
edoxen validate YAML_FILE_PATTERN # Validate YAML files against Edoxen schemaValidate resolution data files against the Edoxen schema:
# Validate a single file
$ edoxen validate resolutions.yaml
# Validate multiple files
$ edoxen validate file1.yaml file2.yaml file3.yaml
# Validate files using patterns
$ edoxen validate "*.yaml"
$ edoxen validate "resolutions/*.yml"
# Example output
🔍 Validating 3 file(s)...
resolutions.yaml... ✅ VALID
file1.yaml... ✅ VALID
file2.yaml... ❌ INVALID
- Line 15: Invalid action type 'invalid_type'
📊 Validation Summary:
Valid files: 2
Invalid files: 1
Success rate: 66.7%Get detailed help for the validate command:
$ edoxen help validate
Usage:
edoxen validate YAML_FILE_PATTERN
Description:
Validate YAML files against the Edoxen schema. Supports file patterns and multiple files.
Examples:
edoxen validate resolutions.yaml
edoxen validate *.yaml
edoxen validate "data/*.yml"Normalize YAML files to ensure they conform to the Edoxen schema format.
This command loads the YAML files, parses them through the Edoxen models, and outputs clean, properly formatted YAML.
# Normalize files to a specific output directory
$ edoxen normalize resolutions.yaml --output /path/to/output
# Normalize multiple files
$ edoxen normalize "*.yaml" --output normalized/
# Normalize files in place (overwrites original files)
$ edoxen normalize resolutions.yaml --inplace
# Example output
🔄 Normalizing 2 file(s)...
resolutions.yaml... ✅ NORMALIZED → /path/to/output/resolutions.yaml
meeting-notes.yaml... ✅ NORMALIZED → /path/to/output/meeting-notes.yaml
📊 Normalization Summary:
Successful: 2
Failed: 0
Success rate: 100.0%
Output directory: /path/to/outputGet detailed help for the normalize command:
$ edoxen help normalize
Usage:
edoxen normalize YAML_FILE_PATTERN
Options:
[--output=OUTPUT] # Output directory for normalized files
[--inplace], [--no-inplace], [--skip-inplace] # Modify files in place (no backup)
Description:
Normalize YAML files using Edoxen schema. This ensures consistent formatting
and structure according to the Edoxen data models.
Examples:
edoxen normalize resolutions.yaml --output clean/
edoxen normalize "*.yaml" --inplace
edoxen normalize "data/*.yml" --output normalized/# Validate all YAML files in a directory
$ edoxen validate "resolutions/*.yaml"
# Validate specific meeting files
$ edoxen validate "plenary-*.yaml" "ballots-*.yaml"# Normalize legacy files to new schema format
$ edoxen normalize "legacy/*.yaml" --output clean/
# Update files in place after backup
$ cp -r data/ data-backup/
$ edoxen normalize "data/*.yaml" --inplacemetadata:
title: "Resolutions of the 42nd plenary meeting of ISO/TC 154"
dates:
- kind: meeting
start: 2024-01-15
end: 2024-01-17
source: "ISO/TC 154 Secretariat"
urls:
- href: "https://example.com/meeting"
title: "Meeting Information"
resolutions:
- identifier: "2024-01"
title: "Adoption of new standard"
category: "Technical resolutions"
dates:
- kind: decision
start: 2024-01-16
subject: "ISO/TC 154"
considerations:
- type: "having"
message: "reviewed the technical specifications"
actions:
- type: "resolves"
dates:
- kind: effective
start: 2024-01-16
message: "to adopt ISO 12345 as a new standard"
approvals:
- type: "affirmative"
degree: "unanimous"
message: "UNANIMOUS"require 'edoxen'
# Parse from YAML string
yaml_content = File.read('resolutions.yaml')
resolution_set = Edoxen::ResolutionSet.from_yaml(yaml_content)
# Access metadata
puts "Title: #{resolution_set.metadata.title}"
puts "Meeting dates: #{resolution_set.metadata.dates.first.start} to #{resolution_set.metadata.dates.first.end}"
puts "Source: #{resolution_set.metadata.source}"
# Access resolutions
resolution_set.resolutions.each do |resolution|
puts "Resolution: #{resolution.identifier} - #{resolution.title}"
puts "Category: #{resolution.category}"
puts "Subject: #{resolution.subject}"
# Access structured dates
resolution.dates.each do |date|
puts " #{date.kind.capitalize} date: #{date.start}"
end
# Access considerations
resolution.considerations.each do |consideration|
puts " Consideration (#{consideration.type}): #{consideration.message}"
end
# Access actions
resolution.actions.each do |action|
puts " Action (#{action.type}): #{action.message}"
action.dates.each do |date|
puts " #{date.kind.capitalize} date: #{date.start}"
end
end
# Access approvals
resolution.approvals.each do |approval|
puts " Approval: #{approval.type} (#{approval.degree})"
end
endrequire 'edoxen'
# Create structured dates
meeting_date = Edoxen::ResolutionDate.new(
kind: "meeting",
start: Date.new(2024, 1, 15),
end: Date.new(2024, 1, 17)
)
decision_date = Edoxen::ResolutionDate.new(
kind: "decision",
start: Date.new(2024, 1, 16)
)
effective_date = Edoxen::ResolutionDate.new(
kind: "effective",
start: Date.new(2024, 1, 16)
)
# Create metadata
metadata = Edoxen::Metadata.new(
title: "Resolutions of the 42nd plenary meeting of ISO/TC 154",
dates: [meeting_date],
source: "ISO/TC 154 Secretariat",
urls: [
Edoxen::Url.new(
href: "https://example.com/meeting",
title: "Meeting Information"
)
]
)
# Create a resolution
resolution = Edoxen::Resolution.new(
identifier: "2024-01",
title: "Adoption of new standard",
category: "Technical resolutions",
subject: "ISO/TC 154",
dates: [decision_date]
)
# Add considerations
consideration = Edoxen::Consideration.new(
type: "having",
message: "reviewed the technical specifications"
)
resolution.considerations = [consideration]
# Add actions
action = Edoxen::Action.new(
type: "resolves",
dates: [effective_date],
message: "to adopt ISO 12345 as a new standard"
)
resolution.actions = [action]
# Add approvals
approval = Edoxen::Approval.new(
type: "affirmative",
degree: "unanimous",
message: "UNANIMOUS"
)
resolution.approvals = [approval]
# Create resolution set
resolution_set = Edoxen::ResolutionSet.new(
metadata: metadata,
resolutions: [resolution]
)The Edoxen gem provides the following models:
┌─────────────────────────┐
│ ResolutionSet │
│ │
│ ◊metadata │
│ ◊resolutions │
└───────────┬─────────────┘
│ 1..*
┌───────────────┴────────────────┐
┌───────────▼─────────────┐ ┌────────────▼───────────┐
│ Resolution │ │ Metadata │
│ │ │ │
│ •identifier │ │ •title │
│ •title │ │ ◊dates │
│ •category │ │ •source │
│ •subject │ │ ◊urls │
│ ◊dates │ └────────────────────────┘
│ ◊considerations │
│ ◊actions │
│ ◊approvals │
└────────────┬────────────┘
├────────────────────┬────────────────────┐
│ 1..* │ 1..* │ 1..*
┌────────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐
│ Consideration │ │ Action │ │ Approval │
│ │ │ │ │ │
│ •type │ │ •type │ │ •type │
│ •message │ │ •message │ │ •degree │
│ •date_effective │ │ •subject │ │ •message │
└─────────────────┘ └─────────────────┘ └─────────────────┘The main container for resolution collections with metadata.
metadata-
A
Metadataobject containing collection information resolutions-
A collection of
Resolutionobjects
Contains metadata about the resolution collection.
title-
The collection title as a string
dates-
A collection of
ResolutionDateobjects for meeting dates source-
The source organization as a string
urls-
A collection of
Urlobjects for reference links
Represents structured date information with semantic meaning.
kind-
The type of date as a string
start-
The start date as a Date object
end-
The end date as a Date object (optional, for date ranges)
Represents a URL reference with optional title.
href-
The URL as a string
title-
The link title as a string (optional)
Represents a single formal resolution.
identifier-
The resolution identifier as a string
title-
The resolution title as a string
category-
The resolution category as a string (optional)
subject-
The subject body as a string (optional)
dates-
A collection of
ResolutionDateobjects considerations-
A collection of
Considerationobjects actions-
A collection of
Actionobjects approvals-
A collection of
Approvalobjects
Represents actions taken within a resolution.
type-
The action type(s). Can be a string or array of strings
dates-
A collection of
ResolutionDateobjects message-
The action description as a string
subject-
The action subject as a string (optional)
Represents considerations that lead to a resolution.
type-
The consideration type as a string
message-
The consideration description as a string
date_effective-
The effective date as a Date object (optional)
Copyright Ribose.
The gem is available as open source under the terms of the 2-Clause BSD License.