lex-agentic-social 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +50 -3
- data/lex-agentic-social.gemspec +8 -0
- data/lib/legion/extensions/agentic/social/apprenticeship/runners/cognitive_apprenticeship.rb +11 -11
- data/lib/legion/extensions/agentic/social/conflict/runners/conflict.rb +10 -10
- data/lib/legion/extensions/agentic/social/conscience/runners/conscience.rb +10 -10
- data/lib/legion/extensions/agentic/social/consent/runners/consent.rb +10 -10
- data/lib/legion/extensions/agentic/social/entrainment/runners/cognitive_entrainment.rb +15 -15
- data/lib/legion/extensions/agentic/social/governance/runners/governance.rb +8 -8
- data/lib/legion/extensions/agentic/social/joint_attention/runners/joint_attention.rb +12 -12
- data/lib/legion/extensions/agentic/social/mentalizing/runners/mentalizing.rb +9 -9
- data/lib/legion/extensions/agentic/social/mirror/runners/observe.rb +3 -3
- data/lib/legion/extensions/agentic/social/mirror/runners/resonance.rb +4 -4
- data/lib/legion/extensions/agentic/social/mirror/runners/simulate.rb +5 -5
- data/lib/legion/extensions/agentic/social/mirror_system/runners/mirror.rb +13 -13
- data/lib/legion/extensions/agentic/social/moral_reasoning/runners/moral_reasoning.rb +12 -12
- data/lib/legion/extensions/agentic/social/perspective_shifting/helpers/shifting_engine.rb +4 -0
- data/lib/legion/extensions/agentic/social/perspective_shifting/runners/perspective_shifting.rb +17 -17
- data/lib/legion/extensions/agentic/social/perspective_shifting/version.rb +1 -1
- data/lib/legion/extensions/agentic/social/social/runners/social.rb +11 -11
- data/lib/legion/extensions/agentic/social/social_learning/runners/social_learning.rb +10 -10
- data/lib/legion/extensions/agentic/social/symbiosis/runners/cognitive_symbiosis.rb +6 -6
- data/lib/legion/extensions/agentic/social/theory_of_mind/runners/theory_of_mind.rb +9 -9
- data/lib/legion/extensions/agentic/social/trust/runners/trust.rb +7 -7
- data/lib/legion/extensions/agentic/social/version.rb +1 -1
- data/spec/legion/extensions/agentic/social/perspective_shifting/helpers/shifting_engine_spec.rb +11 -0
- data/spec/spec_helper.rb +22 -29
- metadata +99 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fea8c58125ee47fd7ab9b975a69c4baf42e1724c351c556d2276ea754d98d366
|
|
4
|
+
data.tar.gz: ca7a2dd8d74dd64e94a9e4f0ea52693ca12190f49eeb77baba0643b3e13352a5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e2ad3f1f5a4329f7bd4c4185bb25dd028b17ea93a09a4399f415788b210a311f68b8c82f733762aaf8ef709b5e4eff2f35c366b00a86c91cdc65798160acf4bf
|
|
7
|
+
data.tar.gz: 4582a5327cf187c45e7b03bb7873776d4873a9d4a0b537e2aa09b76c2cef23a79189d3c6f705d11262f5863a2a38ae2fb2d9abdd3d57867f36d8b74d57b0ee8f
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.1.2] - 2026-03-22
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
- Add legion-cache, legion-crypt, legion-data, legion-json, legion-logging, legion-settings, legion-transport as runtime dependencies
|
|
9
|
+
- Replace direct Legion::Logging calls with injected log helper in all runner modules
|
|
10
|
+
- Update spec_helper with real sub-gem helper stubs
|
|
11
|
+
|
|
12
|
+
## [0.1.1] - 2026-03-18
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Enforce PRIORITY_TYPES validation in ShiftingEngine#add_perspective (returns error hash for invalid priorities)
|
|
16
|
+
|
|
5
17
|
## [0.1.0] - 2026-03-18
|
|
6
18
|
|
|
7
19
|
### Added
|
data/README.md
CHANGED
|
@@ -1,13 +1,60 @@
|
|
|
1
1
|
# lex-agentic-social
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Domain consolidation gem for social cognition, governance, and multi-agent interaction. Bundles 17 source extensions into one loadable unit under `Legion::Extensions::Agentic::Social`.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Gem**: `lex-agentic-social`
|
|
8
|
+
**Version**: 0.1.1
|
|
9
|
+
**Namespace**: `Legion::Extensions::Agentic::Social`
|
|
10
|
+
|
|
11
|
+
## Sub-Modules
|
|
12
|
+
|
|
13
|
+
| Sub-Module | Source Gem | Purpose |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| `Social::Social` | `lex-social` | Group membership, multi-dimensional reputation, reciprocity, norm violations |
|
|
16
|
+
| `Social::TheoryOfMind` | `lex-theory-of-mind` | BDI model — belief/desire/intention tracking, false-belief detection |
|
|
17
|
+
| `Social::Mentalizing` | `lex-mentalizing` | Mentalizing network — tracking of mentalizing capacity |
|
|
18
|
+
| `Social::SocialLearning` | `lex-social-learning` | Learning by observation — vicarious reinforcement |
|
|
19
|
+
| `Social::PerspectiveShifting` | `lex-perspective-shifting` | Deliberate perspective adoption |
|
|
20
|
+
| `Social::Trust` | `lex-trust` | Domain-scoped trust scores — asymmetric reinforcement and decay |
|
|
21
|
+
| `Social::Conflict` | `lex-conflict` | Conflict registration, severity-based posture, optional LLM resolution |
|
|
22
|
+
| `Social::Conscience` | `lex-conscience` | Internalized moral compass — guilt/pride signal generation |
|
|
23
|
+
| `Social::Consent` | `lex-consent` | Four-tier consent gradient with earned autonomy, HITL gate |
|
|
24
|
+
| `Social::MoralReasoning` | `lex-moral-reasoning` | Six Haidt foundations, six Kohlberg stages, six ethical frameworks |
|
|
25
|
+
| `Social::Governance` | `lex-governance` | Four-layer governance — council proposals, quorum voting, action validation |
|
|
26
|
+
| `Social::JointAttention` | `lex-joint-attention` | Shared attention between agents — coordinating focus |
|
|
27
|
+
| `Social::Mirror` | `lex-mirror` | Mirror neuron analog — action observation and imitation |
|
|
28
|
+
| `Social::MirrorSystem` | `lex-mirror` | Extended mirror system |
|
|
29
|
+
| `Social::Entrainment` | `lex-cognitive-entrainment` | Rhythmic synchronization between agents |
|
|
30
|
+
| `Social::Symbiosis` | `lex-cognitive-symbiosis` | Mutually beneficial cognitive partnerships |
|
|
31
|
+
| `Social::Apprenticeship` | `lex-cognitive-apprenticeship` | Expert-novice learning relationships |
|
|
32
|
+
|
|
33
|
+
## Actors
|
|
34
|
+
|
|
35
|
+
- `Social::Conflict::Actors::StaleCheck` — runs every 3600s, checks for stale conflicts
|
|
36
|
+
- `Social::Consent::Actors::TierEvaluation` — runs every 3600s, evaluates and applies consent tiers
|
|
37
|
+
- `Social::Governance::Actors::ShadowAiScan` — interval actor, scans for shadow AI activity
|
|
38
|
+
- `Social::Governance::Actors::VoteTimeout` — runs every 300s, times out expired proposals
|
|
39
|
+
- `Social::JointAttention::Actors::Decay` — interval actor, decays joint attention focus
|
|
40
|
+
- `Social::Mentalizing::Actors::Decay` — interval actor, decays mentalizing model confidence
|
|
41
|
+
- `Social::MirrorSystem::Actors::Decay` — interval actor, decays mirror system activation
|
|
42
|
+
- `Social::Trust::Actors::Decay` — runs every 300s, decays all trust scores
|
|
8
43
|
|
|
9
44
|
## Installation
|
|
10
45
|
|
|
11
46
|
```ruby
|
|
12
47
|
gem 'lex-agentic-social'
|
|
13
48
|
```
|
|
49
|
+
|
|
50
|
+
## Development
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
bundle install
|
|
54
|
+
bundle exec rspec # 1646 examples, 0 failures
|
|
55
|
+
bundle exec rubocop # 0 offenses
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## License
|
|
59
|
+
|
|
60
|
+
MIT
|
data/lex-agentic-social.gemspec
CHANGED
|
@@ -24,6 +24,14 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
end
|
|
25
25
|
spec.require_paths = ['lib']
|
|
26
26
|
|
|
27
|
+
spec.add_dependency 'legion-cache', '>= 1.3.11'
|
|
28
|
+
spec.add_dependency 'legion-crypt', '>= 1.4.9'
|
|
29
|
+
spec.add_dependency 'legion-data', '>= 1.4.17'
|
|
30
|
+
spec.add_dependency 'legion-json', '>= 1.2.1'
|
|
31
|
+
spec.add_dependency 'legion-logging', '>= 1.3.2'
|
|
32
|
+
spec.add_dependency 'legion-settings', '>= 1.3.14'
|
|
33
|
+
spec.add_dependency 'legion-transport', '>= 1.3.9'
|
|
34
|
+
|
|
27
35
|
spec.add_development_dependency 'rspec', '~> 3.13'
|
|
28
36
|
spec.add_development_dependency 'rubocop', '~> 1.60'
|
|
29
37
|
spec.add_development_dependency 'rubocop-rspec', '~> 2.26'
|
data/lib/legion/extensions/agentic/social/apprenticeship/runners/cognitive_apprenticeship.rb
CHANGED
|
@@ -21,10 +21,10 @@ module Legion
|
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
if appr
|
|
24
|
-
|
|
24
|
+
log.info "[cognitive_apprenticeship] created id=#{appr.id} skill=#{skill_name} domain=#{domain}"
|
|
25
25
|
{ success: true, apprenticeship: appr.to_h }
|
|
26
26
|
else
|
|
27
|
-
|
|
27
|
+
log.warn '[cognitive_apprenticeship] create failed: capacity reached'
|
|
28
28
|
{ success: false, reason: :capacity_reached }
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -39,8 +39,8 @@ module Legion
|
|
|
39
39
|
)
|
|
40
40
|
|
|
41
41
|
if appr
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
log.debug "[cognitive_apprenticeship] session id=#{apprenticeship_id} method=#{method} " \
|
|
43
|
+
"success=#{success} mastery=#{appr.mastery.round(3)}"
|
|
44
44
|
{ success: true, apprenticeship: appr.to_h }
|
|
45
45
|
else
|
|
46
46
|
{ success: false, reason: :not_found }
|
|
@@ -51,7 +51,7 @@ module Legion
|
|
|
51
51
|
method = engine.recommend_method(apprenticeship_id: apprenticeship_id)
|
|
52
52
|
|
|
53
53
|
if method
|
|
54
|
-
|
|
54
|
+
log.debug "[cognitive_apprenticeship] recommend id=#{apprenticeship_id} method=#{method}"
|
|
55
55
|
{ success: true, apprenticeship_id: apprenticeship_id, recommended_method: method }
|
|
56
56
|
else
|
|
57
57
|
{ success: false, reason: :not_found }
|
|
@@ -60,31 +60,31 @@ module Legion
|
|
|
60
60
|
|
|
61
61
|
def graduated_apprenticeships(**)
|
|
62
62
|
list = engine.graduated_apprenticeships
|
|
63
|
-
|
|
63
|
+
log.debug "[cognitive_apprenticeship] graduated count=#{list.size}"
|
|
64
64
|
{ success: true, apprenticeships: list.map(&:to_h), count: list.size }
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def active_apprenticeships(**)
|
|
68
68
|
list = engine.active_apprenticeships
|
|
69
|
-
|
|
69
|
+
log.debug "[cognitive_apprenticeship] active count=#{list.size}"
|
|
70
70
|
{ success: true, apprenticeships: list.map(&:to_h), count: list.size }
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def mentor_apprenticeships(mentor_id:, **)
|
|
74
74
|
list = engine.by_mentor(mentor_id: mentor_id)
|
|
75
|
-
|
|
75
|
+
log.debug "[cognitive_apprenticeship] mentor=#{mentor_id} count=#{list.size}"
|
|
76
76
|
{ success: true, mentor_id: mentor_id, apprenticeships: list.map(&:to_h), count: list.size }
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def apprentice_apprenticeships(apprentice_id:, **)
|
|
80
80
|
list = engine.by_apprentice(apprentice_id: apprentice_id)
|
|
81
|
-
|
|
81
|
+
log.debug "[cognitive_apprenticeship] apprentice=#{apprentice_id} count=#{list.size}"
|
|
82
82
|
{ success: true, apprentice_id: apprentice_id, apprenticeships: list.map(&:to_h), count: list.size }
|
|
83
83
|
end
|
|
84
84
|
|
|
85
85
|
def domain_apprenticeships(domain:, **)
|
|
86
86
|
list = engine.by_domain(domain: domain)
|
|
87
|
-
|
|
87
|
+
log.debug "[cognitive_apprenticeship] domain=#{domain} count=#{list.size}"
|
|
88
88
|
{ success: true, domain: domain, apprenticeships: list.map(&:to_h), count: list.size }
|
|
89
89
|
end
|
|
90
90
|
|
|
@@ -94,7 +94,7 @@ module Legion
|
|
|
94
94
|
|
|
95
95
|
def cognitive_apprenticeship_stats(**)
|
|
96
96
|
stats = engine.to_h
|
|
97
|
-
|
|
97
|
+
log.debug "[cognitive_apprenticeship] stats=#{stats.inspect}"
|
|
98
98
|
{ success: true }.merge(stats)
|
|
99
99
|
end
|
|
100
100
|
|
|
@@ -15,17 +15,17 @@ module Legion
|
|
|
15
15
|
|
|
16
16
|
id = conflict_log.record(parties: parties, severity: severity, description: description)
|
|
17
17
|
conflict = conflict_log.get(id)
|
|
18
|
-
|
|
18
|
+
log.info "[conflict] registered: id=#{id[0..7]} severity=#{severity} posture=#{conflict[:posture]} parties=#{parties.join(',')}"
|
|
19
19
|
{ conflict_id: id, severity: severity, posture: conflict[:posture] }
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def add_exchange(conflict_id:, speaker:, message:, **)
|
|
23
23
|
result = conflict_log.add_exchange(conflict_id, speaker: speaker, message: message)
|
|
24
24
|
if result
|
|
25
|
-
|
|
25
|
+
log.debug "[conflict] exchange: id=#{conflict_id[0..7]} speaker=#{speaker}"
|
|
26
26
|
{ recorded: true }
|
|
27
27
|
else
|
|
28
|
-
|
|
28
|
+
log.debug "[conflict] exchange failed: id=#{conflict_id[0..7]} not found"
|
|
29
29
|
{ error: :not_found }
|
|
30
30
|
end
|
|
31
31
|
end
|
|
@@ -33,7 +33,7 @@ module Legion
|
|
|
33
33
|
def resolve_conflict(conflict_id:, outcome:, resolution_notes: nil, **)
|
|
34
34
|
conflict = conflict_log.get(conflict_id)
|
|
35
35
|
unless conflict
|
|
36
|
-
|
|
36
|
+
log.debug "[conflict] resolve failed: id=#{conflict_id[0..7]} not found"
|
|
37
37
|
return { error: :not_found }
|
|
38
38
|
end
|
|
39
39
|
|
|
@@ -48,23 +48,23 @@ module Legion
|
|
|
48
48
|
|
|
49
49
|
result = conflict_log.resolve(conflict_id, outcome: outcome, resolution_notes: resolution_notes)
|
|
50
50
|
if result
|
|
51
|
-
|
|
51
|
+
log.info "[conflict] resolved: id=#{conflict_id[0..7]} outcome=#{outcome}"
|
|
52
52
|
{ resolved: true, outcome: outcome }
|
|
53
53
|
else
|
|
54
|
-
|
|
54
|
+
log.debug "[conflict] resolve failed: id=#{conflict_id[0..7]} not found"
|
|
55
55
|
{ error: :not_found }
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
def get_conflict(conflict_id:, **)
|
|
60
60
|
conflict = conflict_log.get(conflict_id)
|
|
61
|
-
|
|
61
|
+
log.debug "[conflict] get: id=#{conflict_id[0..7]} found=#{!conflict.nil?}"
|
|
62
62
|
conflict ? { found: true, conflict: conflict } : { found: false }
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
def active_conflicts(**)
|
|
66
66
|
conflicts = conflict_log.active_conflicts
|
|
67
|
-
|
|
67
|
+
log.debug "[conflict] active: count=#{conflicts.size}"
|
|
68
68
|
{ conflicts: conflicts, count: conflicts.size }
|
|
69
69
|
end
|
|
70
70
|
|
|
@@ -88,13 +88,13 @@ module Legion
|
|
|
88
88
|
conflict_log.add_exchange(c[:conflict_id], speaker: :system, message: message)
|
|
89
89
|
end
|
|
90
90
|
stale_ids = stale.map { |c| c[:conflict_id] }
|
|
91
|
-
|
|
91
|
+
log.debug "[conflict] stale check: active=#{active.size} stale=#{stale.size}"
|
|
92
92
|
{ checked: active.size, stale_count: stale.size, stale_ids: stale_ids }
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
def recommended_posture(severity:, **)
|
|
96
96
|
posture = Helpers::Severity.recommended_posture(severity)
|
|
97
|
-
|
|
97
|
+
log.debug "[conflict] posture: severity=#{severity} posture=#{posture}"
|
|
98
98
|
{ severity: severity, posture: posture }
|
|
99
99
|
end
|
|
100
100
|
|
|
@@ -17,8 +17,8 @@ module Legion
|
|
|
17
17
|
result = moral_store.evaluator.evaluate(action: action, context: context)
|
|
18
18
|
moral_store.record_evaluation(result)
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
log.debug "[conscience] action=#{action} verdict=#{result[:verdict]} " \
|
|
21
|
+
"score=#{result[:weighted_score]} dilemma=#{result[:dilemma]&.dig(:type)}"
|
|
22
22
|
|
|
23
23
|
result
|
|
24
24
|
end
|
|
@@ -28,8 +28,8 @@ module Legion
|
|
|
28
28
|
stats = moral_store.aggregate_stats
|
|
29
29
|
sensitivities = moral_store.foundation_sensitivities
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
log.debug "[conscience] consistency=#{stats[:consistency_score]} " \
|
|
32
|
+
"evaluations=#{stats[:total_evaluations]}"
|
|
33
33
|
|
|
34
34
|
{
|
|
35
35
|
sensitivities: sensitivities,
|
|
@@ -41,7 +41,7 @@ module Legion
|
|
|
41
41
|
# Recent moral evaluation history
|
|
42
42
|
def moral_history(limit: 20, **)
|
|
43
43
|
recent = moral_store.recent_evaluations(limit)
|
|
44
|
-
|
|
44
|
+
log.debug "[conscience] history: #{recent.size} entries"
|
|
45
45
|
|
|
46
46
|
{
|
|
47
47
|
history: recent,
|
|
@@ -57,9 +57,9 @@ module Legion
|
|
|
57
57
|
|
|
58
58
|
moral_store.record_follow_through(effective_verdict, outcome)
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
log.debug "[conscience] follow_through action=#{action} " \
|
|
61
|
+
"verdict=#{effective_verdict} outcome=#{outcome} " \
|
|
62
|
+
"consistency=#{moral_store.consistency_score}"
|
|
63
63
|
|
|
64
64
|
{
|
|
65
65
|
action: action,
|
|
@@ -72,7 +72,7 @@ module Legion
|
|
|
72
72
|
# List unresolved moral dilemmas (cases where foundations strongly disagreed)
|
|
73
73
|
def moral_dilemmas(**)
|
|
74
74
|
open = moral_store.open_dilemmas
|
|
75
|
-
|
|
75
|
+
log.debug "[conscience] dilemmas: #{open.size} open"
|
|
76
76
|
|
|
77
77
|
{
|
|
78
78
|
dilemmas: open,
|
|
@@ -83,7 +83,7 @@ module Legion
|
|
|
83
83
|
# Aggregate moral reasoning stats
|
|
84
84
|
def conscience_stats(**)
|
|
85
85
|
stats = moral_store.aggregate_stats
|
|
86
|
-
|
|
86
|
+
log.debug '[conscience] stats'
|
|
87
87
|
|
|
88
88
|
stats.merge(
|
|
89
89
|
verdict_distribution: verdict_distribution(stats[:verdict_counts]),
|
|
@@ -12,7 +12,7 @@ module Legion
|
|
|
12
12
|
|
|
13
13
|
def check_consent(domain:, _action_type: :general, **)
|
|
14
14
|
tier = consent_map.get_tier(domain)
|
|
15
|
-
|
|
15
|
+
log.debug "[consent] check: domain=#{domain} tier=#{tier} allowed=#{tier == :autonomous}"
|
|
16
16
|
|
|
17
17
|
{
|
|
18
18
|
domain: domain,
|
|
@@ -28,7 +28,7 @@ module Legion
|
|
|
28
28
|
consent_map.record_outcome(domain, success: success)
|
|
29
29
|
rate = consent_map.success_rate(domain)
|
|
30
30
|
total = consent_map.domains[domain][:total_actions]
|
|
31
|
-
|
|
31
|
+
log.info "[consent] action recorded: domain=#{domain} success=#{success} rate=#{rate.round(2)} total=#{total}"
|
|
32
32
|
|
|
33
33
|
{
|
|
34
34
|
domain: domain,
|
|
@@ -52,12 +52,12 @@ module Legion
|
|
|
52
52
|
case recommendation
|
|
53
53
|
when :promote
|
|
54
54
|
result[:proposed_tier] = Helpers::Tiers.promote(current)
|
|
55
|
-
|
|
55
|
+
log.info "[consent] tier change: domain=#{domain} recommend=promote from=#{current} to=#{result[:proposed_tier]}"
|
|
56
56
|
when :demote
|
|
57
57
|
result[:proposed_tier] = Helpers::Tiers.demote(current)
|
|
58
|
-
|
|
58
|
+
log.warn "[consent] tier change: domain=#{domain} recommend=demote from=#{current} to=#{result[:proposed_tier]}"
|
|
59
59
|
else
|
|
60
|
-
|
|
60
|
+
log.debug "[consent] tier eval: domain=#{domain} current=#{current} recommendation=#{recommendation}"
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
result
|
|
@@ -69,7 +69,7 @@ module Legion
|
|
|
69
69
|
old_tier = consent_map.get_tier(domain)
|
|
70
70
|
consent_map.set_tier(domain, new_tier)
|
|
71
71
|
changed = old_tier != new_tier
|
|
72
|
-
|
|
72
|
+
log.info "[consent] tier applied: domain=#{domain} old=#{old_tier} new=#{new_tier} changed=#{changed}"
|
|
73
73
|
{ domain: domain, old_tier: old_tier, new_tier: new_tier, changed: changed }
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -84,8 +84,8 @@ module Legion
|
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
evaluated = consent_map.domain_count
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
log.debug "[consent] tier evaluation sweep: domains=#{evaluated} " \
|
|
88
|
+
"promotions=#{promotions.size} demotions=#{demotions.size}"
|
|
89
89
|
|
|
90
90
|
{ evaluated: evaluated, promotions: promotions, demotions: demotions }
|
|
91
91
|
end
|
|
@@ -200,7 +200,7 @@ module Legion
|
|
|
200
200
|
def consent_status(domain: nil, **)
|
|
201
201
|
if domain
|
|
202
202
|
entry = consent_map.domains[domain]
|
|
203
|
-
|
|
203
|
+
log.debug "[consent] status: domain=#{domain} tier=#{entry[:tier]} total=#{entry[:total_actions]}"
|
|
204
204
|
{
|
|
205
205
|
domain: domain,
|
|
206
206
|
tier: entry[:tier],
|
|
@@ -209,7 +209,7 @@ module Legion
|
|
|
209
209
|
eligible: consent_map.eligible_for_change?(domain)
|
|
210
210
|
}
|
|
211
211
|
else
|
|
212
|
-
|
|
212
|
+
log.debug "[consent] status: domains=#{consent_map.domain_count}"
|
|
213
213
|
{ domains: consent_map.to_h, count: consent_map.domain_count }
|
|
214
214
|
end
|
|
215
215
|
end
|
|
@@ -12,51 +12,51 @@ module Legion
|
|
|
12
12
|
|
|
13
13
|
def create_entrainment_pairing(agent_a:, agent_b:, domain:, **)
|
|
14
14
|
pairing = engine.create_pairing(agent_a: agent_a, agent_b: agent_b, domain: domain)
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
log.debug '[cognitive_entrainment] pairing ' \
|
|
16
|
+
"#{agent_a}<->#{agent_b} domain=#{domain} id=#{pairing.id[0..7]}"
|
|
17
17
|
{ success: true, pairing_id: pairing.id, agent_a: agent_a,
|
|
18
18
|
agent_b: agent_b, domain: domain, synchrony: pairing.synchrony }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def record_entrainment_interaction(pairing_id:, aligned:, **)
|
|
22
22
|
result = engine.record_interaction(pairing_id: pairing_id, aligned: aligned)
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
log.debug '[cognitive_entrainment] interaction ' \
|
|
24
|
+
"id=#{pairing_id[0..7]} aligned=#{aligned}"
|
|
25
25
|
result
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def pairings_for_agent(agent_id:, **)
|
|
29
29
|
pairings = engine.pairings_for(agent_id: agent_id)
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
log.debug '[cognitive_entrainment] pairings_for ' \
|
|
31
|
+
"agent=#{agent_id} count=#{pairings.size}"
|
|
32
32
|
{ success: true, agent_id: agent_id,
|
|
33
33
|
pairings: pairings.map(&:to_h), count: pairings.size }
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def entrained_partners(agent_id:, **)
|
|
37
37
|
partners = engine.entrained_partners(agent_id: agent_id)
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
log.debug '[cognitive_entrainment] entrained_partners ' \
|
|
39
|
+
"agent=#{agent_id} count=#{partners.size}"
|
|
40
40
|
{ success: true, agent_id: agent_id, partners: partners, count: partners.size }
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def strongest_entrainment_pairings(limit: 5, **)
|
|
44
44
|
pairings = engine.strongest_pairings(limit: limit)
|
|
45
|
-
|
|
45
|
+
log.debug "[cognitive_entrainment] strongest count=#{pairings.size}"
|
|
46
46
|
{ success: true, pairings: pairings.map(&:to_h), count: pairings.size }
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def domain_entrainment(domain:, **)
|
|
50
50
|
pairings = engine.by_domain(domain: domain)
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
log.debug "[cognitive_entrainment] domain=#{domain} " \
|
|
52
|
+
"count=#{pairings.size}"
|
|
53
53
|
{ success: true, domain: domain,
|
|
54
54
|
pairings: pairings.map(&:to_h), count: pairings.size }
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def overall_entrainment_level(**)
|
|
58
58
|
sync = engine.overall_entrainment
|
|
59
|
-
|
|
59
|
+
log.debug "[cognitive_entrainment] overall_sync=#{sync.round(3)}"
|
|
60
60
|
{ success: true, overall_synchrony: sync,
|
|
61
61
|
entrained_count: engine.entrained_pairings.size }
|
|
62
62
|
end
|
|
@@ -64,14 +64,14 @@ module Legion
|
|
|
64
64
|
def update_cognitive_entrainment(**)
|
|
65
65
|
engine.drift_all
|
|
66
66
|
pruned = engine.prune_independent
|
|
67
|
-
|
|
67
|
+
log.debug "[cognitive_entrainment] drift+prune pruned=#{pruned}"
|
|
68
68
|
{ success: true, pruned: pruned }
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def cognitive_entrainment_stats(**)
|
|
72
72
|
stats = engine.to_h
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
log.debug '[cognitive_entrainment] stats ' \
|
|
74
|
+
"total=#{stats[:total_pairings]}"
|
|
75
75
|
{ success: true }.merge(stats)
|
|
76
76
|
end
|
|
77
77
|
|
|
@@ -16,7 +16,7 @@ module Legion
|
|
|
16
16
|
size = council_size || Helpers::Layers::MIN_COUNCIL_SIZE
|
|
17
17
|
id = proposal_store.create(category: category, description: description,
|
|
18
18
|
proposer: proposer, council_size: size)
|
|
19
|
-
|
|
19
|
+
log.info "[governance] proposal created: id=#{id[0..7]} category=#{category} proposer=#{proposer} council=#{size}"
|
|
20
20
|
{ proposal_id: id, category: category, status: :open }
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -24,26 +24,26 @@ module Legion
|
|
|
24
24
|
result = proposal_store.vote(proposal_id, voter: voter, approve: approve)
|
|
25
25
|
case result
|
|
26
26
|
when nil
|
|
27
|
-
|
|
27
|
+
log.debug "[governance] vote failed: proposal=#{proposal_id[0..7]} not found or closed"
|
|
28
28
|
{ error: :not_found_or_closed }
|
|
29
29
|
when :already_voted
|
|
30
|
-
|
|
30
|
+
log.debug "[governance] vote failed: proposal=#{proposal_id[0..7]} voter=#{voter} already voted"
|
|
31
31
|
{ error: :already_voted }
|
|
32
32
|
else
|
|
33
|
-
|
|
33
|
+
log.info "[governance] vote: proposal=#{proposal_id[0..7]} voter=#{voter} approve=#{approve} resolution=#{result}"
|
|
34
34
|
{ voted: true, resolution: result }
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def get_proposal(proposal_id:, **)
|
|
39
39
|
prop = proposal_store.get(proposal_id)
|
|
40
|
-
|
|
40
|
+
log.debug "[governance] get: proposal=#{proposal_id[0..7]} found=#{!prop.nil?}"
|
|
41
41
|
prop ? { found: true, proposal: prop } : { found: false }
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def open_proposals(**)
|
|
45
45
|
props = proposal_store.open_proposals
|
|
46
|
-
|
|
46
|
+
log.debug "[governance] open proposals: count=#{props.size}"
|
|
47
47
|
{ proposals: props, count: props.size }
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -52,7 +52,7 @@ module Legion
|
|
|
52
52
|
timed = open.select { |p| Time.now.utc - p[:created_at] > Helpers::Layers::VOTE_TIMEOUT }
|
|
53
53
|
timed.each { |p| proposal_store.resolve_timed_out(p[:proposal_id]) }
|
|
54
54
|
timed_ids = timed.map { |p| p[:proposal_id] }
|
|
55
|
-
|
|
55
|
+
log.debug "[governance] vote timeout sweep: open=#{open.size} timed_out=#{timed.size}"
|
|
56
56
|
{ checked: open.size, timed_out: timed.size, timed_out_ids: timed_ids }
|
|
57
57
|
end
|
|
58
58
|
|
|
@@ -69,7 +69,7 @@ module Legion
|
|
|
69
69
|
when :transparency
|
|
70
70
|
{ allowed: true, layer: layer, reason: :logged, audit_required: true }
|
|
71
71
|
end
|
|
72
|
-
|
|
72
|
+
log.debug "[governance] validate: layer=#{layer} allowed=#{result[:allowed]} reason=#{result[:reason]}"
|
|
73
73
|
result
|
|
74
74
|
end
|
|
75
75
|
|
|
@@ -12,65 +12,65 @@ module Legion
|
|
|
12
12
|
|
|
13
13
|
def create_attention_target(name:, domain:, creator:, priority: 0.5, **)
|
|
14
14
|
target = joint_focus_manager.create_target(name: name, domain: domain, priority: priority, creator: creator)
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
log.debug "[joint_attention] create_target: name=#{name} domain=#{domain} priority=#{priority} " \
|
|
16
|
+
"creator=#{creator} id=#{target.id}"
|
|
17
17
|
{ success: true, target: target.to_h }
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def join_attention(target_id:, agent_id:, gaze: nil, **)
|
|
21
21
|
result = joint_focus_manager.join_target(target_id: target_id, agent_id: agent_id, gaze: gaze)
|
|
22
|
-
|
|
22
|
+
log.debug "[joint_attention] join: target_id=#{target_id} agent_id=#{agent_id} gaze=#{gaze} result=#{result}"
|
|
23
23
|
{ success: %i[joined already_attending].include?(result), result: result, target_id: target_id, agent_id: agent_id }
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def leave_attention(target_id:, agent_id:, **)
|
|
27
27
|
result = joint_focus_manager.leave_target(target_id: target_id, agent_id: agent_id)
|
|
28
|
-
|
|
28
|
+
log.debug "[joint_attention] leave: target_id=#{target_id} agent_id=#{agent_id} result=#{result}"
|
|
29
29
|
{ success: result == :removed, result: result, target_id: target_id, agent_id: agent_id }
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def direct_attention(from_agent:, to_agent:, target_id:, **)
|
|
33
33
|
result = joint_focus_manager.direct_attention(from_agent: from_agent, to_agent: to_agent, target_id: target_id)
|
|
34
|
-
|
|
34
|
+
log.debug "[joint_attention] direct: from=#{from_agent} to=#{to_agent} target_id=#{target_id} result=#{result}"
|
|
35
35
|
{ success: %i[directed already_attending].include?(result), result: result, target_id: target_id,
|
|
36
36
|
from_agent: from_agent, to_agent: to_agent }
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def establish_mutual_awareness(target_id:, agent_a:, agent_b:, **)
|
|
40
40
|
result = joint_focus_manager.establish_shared(target_id: target_id, agent_a: agent_a, agent_b: agent_b)
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
log.debug "[joint_attention] mutual_awareness: target_id=#{target_id} " \
|
|
42
|
+
"agent_a=#{agent_a} agent_b=#{agent_b} result=#{result}"
|
|
43
43
|
{ success: result == :established, result: result, target_id: target_id, agent_a: agent_a, agent_b: agent_b }
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def update_gaze(target_id:, agent_id:, gaze:, **)
|
|
47
47
|
result = joint_focus_manager.update_gaze(target_id: target_id, agent_id: agent_id, gaze: gaze)
|
|
48
|
-
|
|
48
|
+
log.debug "[joint_attention] update_gaze: target_id=#{target_id} agent_id=#{agent_id} gaze=#{gaze} result=#{result}"
|
|
49
49
|
{ success: result == :updated, result: result, target_id: target_id, agent_id: agent_id, gaze: gaze }
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def shared_focus(agent_a:, agent_b:, **)
|
|
53
53
|
targets = joint_focus_manager.shared_targets(agent_a: agent_a, agent_b: agent_b)
|
|
54
|
-
|
|
54
|
+
log.debug "[joint_attention] shared_focus: agent_a=#{agent_a} agent_b=#{agent_b} count=#{targets.size}"
|
|
55
55
|
{ success: true, agent_a: agent_a, agent_b: agent_b, shared_targets: targets.map(&:to_h), count: targets.size }
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def attention_targets_for(agent_id:, **)
|
|
59
59
|
targets = joint_focus_manager.targets_for_agent(agent_id: agent_id)
|
|
60
|
-
|
|
60
|
+
log.debug "[joint_attention] targets_for: agent_id=#{agent_id} count=#{targets.size}"
|
|
61
61
|
{ success: true, agent_id: agent_id, targets: targets.map(&:to_h), count: targets.size }
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def update_joint_attention(**)
|
|
65
65
|
joint_focus_manager.decay_all
|
|
66
66
|
stats = joint_focus_manager.to_h
|
|
67
|
-
|
|
67
|
+
log.debug "[joint_attention] decay_tick: targets=#{stats[:target_count]} agents=#{stats[:agent_count]}"
|
|
68
68
|
{ success: true, targets: stats[:target_count], agents: stats[:agent_count], history: stats[:history_size] }
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def joint_attention_stats(**)
|
|
72
72
|
stats = joint_focus_manager.to_h
|
|
73
|
-
|
|
73
|
+
log.debug "[joint_attention] stats: targets=#{stats[:target_count]} agents=#{stats[:agent_count]}"
|
|
74
74
|
{ success: true, stats: stats }
|
|
75
75
|
end
|
|
76
76
|
|