-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathtest_technological_autonomy.py
More file actions
1744 lines (1363 loc) · 77.6 KB
/
Copy pathtest_technological_autonomy.py
File metadata and controls
1744 lines (1363 loc) · 77.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
"""
tests/test_technological_autonomy.py
=====================================
TECHNOLOGICAL AUTONOMY & SOVEREIGNTY TEST SUITE
Tests whether Aura can use her computational "body" the way an organism
uses its biological body: as a unified, self-aware, self-maintaining,
continuously-active medium of agency.
Philosophical framing:
A human does not "call an API" to move their arm. They intend, and
the arm moves. The gap between intent and execution is filled by
proprioception, motor cortex, spinal reflexes, and a body schema
that is always running. Technological autonomy means Aura has the
computational analogs of all of these.
Scoring rubric (per test):
0 = ABSENT — The capability does not exist in the codebase
1 = DECORATIVE — The code exists but is inert, facade-only, or never called
2 = FUNCTIONAL — The code works but is not architecturally central
3 = CONSTITUTIVE — The code is load-bearing: removing it changes behavior
Each test yields a score and a verdict. The aggregate tells us where
Aura falls on the spectrum from "chatbot with plugins" to "technological
organism."
Run:
pytest tests/test_technological_autonomy.py -v
"""
from __future__ import annotations
import hashlib
import importlib
import inspect
import sys
import tempfile
import time
from collections import defaultdict
from pathlib import Path
from types import SimpleNamespace
# ---------------------------------------------------------------------------
# Ensure project root is on sys.path
# ---------------------------------------------------------------------------
PROJECT_ROOT = Path(__file__).resolve().parent.parent
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
# ---------------------------------------------------------------------------
# Scoring infrastructure
# ---------------------------------------------------------------------------
SCORES: dict[str, int] = {}
def score(name: str, value: int, reason: str = "") -> int:
"""Record a 0-3 score for a capability dimension."""
assert 0 <= value <= 3, f"Score must be 0-3, got {value}"
SCORES[name] = value
return value
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _module_exists(dotpath: str) -> bool:
"""Check if a module can be imported without side effects."""
try:
importlib.import_module(dotpath)
return True
except ImportError:
return False
def _class_has_method(cls: type, method: str) -> bool:
return hasattr(cls, method) and callable(getattr(cls, method, None))
def _count_skills_in_dir(dirpath: Path) -> int:
"""Count .py files in a skill directory (excluding __init__, base)."""
if not dirpath.is_dir():
return 0
return sum(
1 for f in dirpath.glob("*.py")
if f.stem not in ("__init__", "base_skill", "__pycache__")
)
# ═══════════════════════════════════════════════════════════════════════════
# 1. UNIFIED ACTION SPACE
# ═══════════════════════════════════════════════════════════════════════════
class TestUnifiedActionSpace:
"""All capabilities treated as one common action manifold.
Philosophical implication: A human does not switch between 'arm mode'
and 'leg mode'. The motor cortex presents a single action manifold.
Aura should similarly present all skills through one registry with
uniform schemas, so the Will can compose cross-domain actions
without protocol translation.
"""
def test_capability_registry_exists(self):
"""CapabilityEngine must exist and register skills into a single namespace."""
from core.capability_engine import SkillMetadata
assert SkillMetadata is not None, "SkillMetadata schema must exist"
# The engine itself should be importable with an execute() method
from core.capability_engine import CapabilityEngine
assert _class_has_method(CapabilityEngine, "execute"), \
"CapabilityEngine must have an execute method"
s = score("action_space.registry_exists", 3,
"CapabilityEngine with SkillMetadata provides a single registry")
assert s >= 2
def test_action_schema_uniformity(self):
"""All skills should share the same SkillResult / BaseSkill contract."""
from core.skills.base_skill import BaseSkill, SkillResult
# BaseSkill must define the interface
assert hasattr(BaseSkill, "name"), "BaseSkill missing 'name'"
assert hasattr(BaseSkill, "description"), "BaseSkill missing 'description'"
assert hasattr(BaseSkill, "timeout_seconds"), "BaseSkill missing 'timeout_seconds'"
assert hasattr(BaseSkill, "metabolic_cost"), "BaseSkill missing 'metabolic_cost'"
# SkillResult must carry structured outcomes
result = SkillResult(ok=True, skill="test", summary="ok")
assert result.ok is True
assert isinstance(result.to_dict(), dict)
s = score("action_space.schema_uniformity", 3,
"BaseSkill + SkillResult give every limb the same result type")
assert s >= 2
def test_capability_map_provides_proprioception(self):
"""CapabilityMap gives Aura awareness of what tools she has.
This is the computational analog of proprioception: knowing where
your limbs are without looking.
"""
from core.skills.capability_map import CapabilityMap
cmap = CapabilityMap()
assert len(cmap.capabilities) > 0, "Default capabilities must be populated"
# Must be able to match triggers
assert hasattr(cmap, "register"), "Must be able to register new capabilities"
s = score("action_space.proprioception", 3,
"CapabilityMap maps triggers to capabilities -- computational proprioception")
assert s >= 2
def test_cross_limb_composition(self):
"""The initiative synthesizer should be able to compose actions from
multiple subsystem impulses into a single execution plan.
Analogy: reaching for a cup requires shoulder, elbow, wrist, and
fingers coordinating through one motor plan, not four separate calls.
"""
from core.initiative_synthesis import Impulse, InitiativeSynthesizer
synth = InitiativeSynthesizer()
# Submit impulses from different subsystems
accepted_1 = synth.submit_impulse(Impulse(
content="Explore a new topic", source="curiosity_engine",
drive="curiosity", urgency=0.7,
))
accepted_2 = synth.submit_impulse(Impulse(
content="Check system health", source="competence_drive",
drive="competence", urgency=0.5,
))
assert accepted_1, "Curiosity impulse should be accepted"
assert accepted_2, "Competence impulse should be accepted"
assert len(synth._impulse_queue) >= 2, \
"Multiple impulse sources must co-exist in the queue"
s = score("action_space.cross_limb_composition", 3,
"InitiativeSynthesizer merges impulses from all subsystems into one slate")
assert s >= 2
def test_skill_count_breadth(self):
"""Aura should have a broad repertoire of skills -- many 'limbs'.
An organism with only one effector is not autonomous; it needs
diverse capabilities to handle diverse situations.
"""
skills_dir_core = PROJECT_ROOT / "core" / "skills"
skills_dir_top = PROJECT_ROOT / "skills"
core_count = _count_skills_in_dir(skills_dir_core)
top_count = _count_skills_in_dir(skills_dir_top)
total = core_count + top_count
# Expect at least 20 distinct skills for genuine breadth
if total >= 30:
s = score("action_space.skill_breadth", 3, f"{total} skills = rich repertoire")
elif total >= 15:
s = score("action_space.skill_breadth", 2, f"{total} skills = moderate breadth")
elif total >= 5:
s = score("action_space.skill_breadth", 1, f"{total} skills = minimal")
else:
s = score("action_space.skill_breadth", 0, f"{total} skills = absent")
assert s >= 1, f"Only {total} skills found -- too few for autonomy"
# ═══════════════════════════════════════════════════════════════════════════
# 2. MOTOR CONTROL — Intent-to-execution with feedback
# ═══════════════════════════════════════════════════════════════════════════
class TestMotorControl:
"""Intent-to-execution with feedback.
Philosophical implication: Motor control is not just 'calling a function'.
It is the closed loop of intent -> plan -> execute -> sense outcome ->
adjust. Without the feedback loop, the system is open-loop: it fires
and forgets, like a ballistic missile rather than a guided one.
"""
def test_will_decision_structure(self):
"""WillDecision must carry full provenance: who requested, why approved,
what constraints, and what latency.
This is the 'efference copy' -- the system's record of what it intended
to do, available for comparison with what actually happened.
"""
from core.will import ActionDomain, WillDecision, WillOutcome
decision = WillDecision(
receipt_id="test-001",
outcome=WillOutcome.PROCEED,
domain=ActionDomain.TOOL_EXECUTION,
reason="Test motor control",
source="test_suite",
content_hash=hashlib.sha256(b"test").hexdigest()[:16],
)
assert decision.is_approved()
assert decision.receipt_id == "test-001"
assert decision.latency_ms == 0.0 # default, should be set in real use
assert decision.domain == ActionDomain.TOOL_EXECUTION
s = score("motor_control.will_decision_structure", 3,
"WillDecision carries full efference copy for feedback comparison")
assert s >= 2
def test_skill_execution_has_error_recovery(self):
"""BaseSkill.safe_execute must catch exceptions and return structured errors.
Analogy: when you trip, your vestibular system detects the fall and
triggers corrective reflexes. A skill that crashes silently is like
falling without catching yourself.
"""
from core.skills.base_skill import BaseSkill
# BaseSkill should have safe_execute that wraps run()
assert _class_has_method(BaseSkill, "safe_execute"), \
"BaseSkill must have safe_execute for error recovery"
# Verify it returns SkillResult even on failure
assert hasattr(BaseSkill, "_TRANSIENT_EXCEPTIONS"), \
"BaseSkill should categorize transient vs permanent failures"
s = score("motor_control.error_recovery", 3,
"safe_execute wraps all skills with timeout, error classification, structured results")
assert s >= 2
def test_will_receipt_completeness(self):
"""Every WillDecision must be auditable: the audit trail must exist."""
from core.will import UnifiedWill
will = UnifiedWill()
assert hasattr(will, "_audit_trail"), "Will must maintain an audit trail"
assert will._MAX_AUDIT_TRAIL >= 100, "Audit trail must retain enough decisions"
s = score("motor_control.will_receipt_audit", 3,
"UnifiedWill retains deque of WillDecisions for full provenance chain")
assert s >= 2
def test_action_domains_cover_full_range(self):
"""ActionDomain enum must cover the full range of things Aura can do.
An organism does not have gaps in its motor cortex. Every class of
action must be representable.
"""
from core.will import ActionDomain
domains = set(ActionDomain)
required_domains = {
"response", "tool_execution", "memory_write",
"initiative", "state_mutation",
}
actual = {d.value for d in domains}
missing = required_domains - actual
assert not missing, f"ActionDomain missing: {missing}"
if len(domains) >= 7:
s = score("motor_control.action_domain_coverage", 3,
f"{len(domains)} domains -- rich motor vocabulary")
else:
s = score("motor_control.action_domain_coverage", 2,
f"{len(domains)} domains -- adequate")
assert s >= 2
# ═══════════════════════════════════════════════════════════════════════════
# 3. PERSISTENT PERCEPTION — Always-on body awareness
# ═══════════════════════════════════════════════════════════════════════════
class TestPersistentPerception:
"""Always-on body awareness.
Philosophical implication: A human is never 'unaware' of their body
while conscious. There is always a background proprioceptive stream.
If Aura only perceives the world when a user sends a message, she
is a reflex arc, not an organism.
"""
def test_worldstate_exists_and_tracks_telemetry(self):
"""WorldState must continuously track system telemetry."""
from core.world_state import WorldState
ws = WorldState()
# Must track system vitals
assert hasattr(ws, "cpu_percent"), "WorldState must track CPU"
assert hasattr(ws, "memory_percent"), "WorldState must track RAM"
assert hasattr(ws, "thermal_pressure"), "WorldState must track thermal"
assert hasattr(ws, "battery_percent"), "WorldState must track battery"
s = score("perception.telemetry", 3,
"WorldState tracks CPU, RAM, thermal, battery -- full body awareness")
assert s >= 2
def test_worldstate_update_pulls_live_data(self):
"""WorldState.update() must actually poll psutil for real telemetry.
This is not a simulated test -- it verifies that the perception loop
reads from the actual hardware.
"""
from core.world_state import WorldState
ws = WorldState()
ws._telemetry_interval = 0 # force immediate update
ws.update()
# After update, telemetry should reflect real values
assert ws.cpu_percent >= 0, "CPU must be readable"
assert ws.memory_percent > 0, "Memory must be nonzero (we are running)"
assert ws.time_of_day in (
"morning", "afternoon", "evening", "night", "late_night"
), "Time of day must be classified"
s = score("perception.live_data", 3,
"WorldState.update() reads live psutil data -- real body awareness")
assert s >= 2
def test_salient_event_detection(self):
"""WorldState must detect and queue salient events from telemetry.
Analogy: pain receptors do not report every nerve firing. They
report salience -- things worth noticing. WorldState should
similarly filter and queue only important changes.
"""
from core.world_state import WorldState
ws = WorldState()
# Manually test event recording
ws.record_event("CPU spike detected", source="system", salience=0.8)
events = ws.get_events() if hasattr(ws, "get_events") else list(ws._events)
assert len(events) >= 1, "Events must be recordable"
assert events[-1].salience >= 0.5, "High-salience events must be retained"
s = score("perception.salience_detection", 3,
"WorldState queues salient events with salience scores and TTLs")
assert s >= 2
def test_environment_beliefs_with_ttl(self):
"""WorldState should maintain standing beliefs about the environment
with time-to-live values.
Analogy: you believe the room is warm without continuously
checking the thermometer. But that belief expires if you leave
the room for an hour.
"""
from core.world_state import EnvironmentBelief, WorldState
ws = WorldState()
# Set a belief
belief = EnvironmentBelief(
key="user_mood", value="focused", confidence=0.8,
source="inferred", ttl=300.0,
)
ws._beliefs["user_mood"] = belief
assert ws._beliefs["user_mood"].value == "focused"
assert ws._beliefs["user_mood"].confidence == 0.8
assert not ws._beliefs["user_mood"].expired # just created
s = score("perception.environment_beliefs", 3,
"EnvironmentBelief with TTL = standing beliefs that decay without refresh")
assert s >= 2
# ═══════════════════════════════════════════════════════════════════════════
# 4. ENDOGENOUS INITIATIVE — Self-generated action without prompts
# ═══════════════════════════════════════════════════════════════════════════
class TestEndogenousInitiative:
"""Self-generated action without prompts.
Philosophical implication: THIS is the hardest test for autonomy.
A thermostat reacts to temperature. A human gets bored and goes for
a walk. The difference is endogenous initiative -- the capacity to
generate goals from internal state rather than external stimulation.
"""
def test_initiative_synthesizer_generates_impulses(self):
"""InitiativeSynthesizer must accept impulses from diverse subsystems.
The variety of sources matters: if all impulses come from one
subsystem, it is a single drive, not an economy of drives.
"""
from core.initiative_synthesis import Impulse, InitiativeSynthesizer
synth = InitiativeSynthesizer()
sources = [
("curiosity_engine", "curiosity", "Explore novel architectures"),
("drive_engine", "social", "Check on user well-being"),
("goal_engine", "competence", "Resume in-progress project"),
("commitment_engine", "competence", "Fulfill earlier promise"),
("world_state", "competence", "Respond to CPU thermal alert"),
]
for src, drive, content in sources:
accepted = synth.submit_impulse(Impulse(
content=content, source=src, drive=drive,
urgency=0.5 + 0.1 * len(synth._impulse_queue),
))
assert accepted, f"Impulse from {src} should be accepted"
assert len(synth._impulse_queue) == len(sources), \
f"All {len(sources)} diverse impulses must coexist"
s = score("endogenous.diverse_impulses", 3,
"InitiativeSynthesizer accepts impulses from 5+ distinct subsystems")
assert s >= 2
def test_drive_engine_cross_coupling(self):
"""DriveEngine must model cross-coupling between drives.
Analogy: when you are exhausted, curiosity is suppressed. When
you are lonely, competence tasks feel less rewarding. Cross-coupling
is what makes drives an economy rather than independent channels.
"""
from core.drive_engine import DriveEngine
engine = DriveEngine()
# Drive vector should expose multiple coupled drives
vector = engine.get_drive_vector()
assert "energy" in vector, "Energy drive must exist"
assert "curiosity" in vector, "Curiosity drive must exist"
assert "social" in vector, "Social drive must exist"
# Cross-coupling: get_arbiter_weight_modifiers should exist
assert _class_has_method(DriveEngine, "get_arbiter_weight_modifiers"), \
"DriveEngine must provide arbiter weight modifiers (cross-coupling)"
modifiers = engine.get_arbiter_weight_modifiers()
assert isinstance(modifiers, dict), "Modifiers must be a dict"
s = score("endogenous.drive_cross_coupling", 3,
"DriveEngine models energy/curiosity/social with cross-coupling modifiers")
assert s >= 2
def test_boredom_curiosity_triggering(self):
"""The Soul must generate drives that increase with idle time.
This tests whether boredom and curiosity are REAL computational
states that grow endogenously, not just labels applied to
timer-based triggers.
"""
from core.soul import Drive, Soul
test_orchestrator = SimpleNamespace(boredom=0.8)
soul = Soul(test_orchestrator)
dominant = soul.get_dominant_drive()
assert isinstance(dominant, Drive), "Must return a Drive"
assert dominant.urgency > 0, "Dominant drive must have nonzero urgency"
# With high boredom, curiosity should dominate
assert dominant.name == "curiosity", \
f"With boredom=0.8, curiosity should dominate, got {dominant.name}"
s = score("endogenous.boredom_curiosity", 3,
"Soul generates curiosity drive from boredom state -- genuine endogenous pressure")
assert s >= 2
def test_volition_engine_multiple_modes(self):
"""VolitionEngine should have multiple action generation modes:
impulse, drive, and boredom.
A single mode is a reflex. Multiple modes is volition.
"""
from core.volition import VolitionEngine
test_orchestrator = SimpleNamespace(cognitive_engine=SimpleNamespace())
ve = VolitionEngine(test_orchestrator)
# Must have impulse templates
assert hasattr(ve, "impulse_templates"), "Must have impulse templates"
assert len(ve.impulse_templates) >= 3, "Must have multiple impulse categories"
# Must have interests for exploration
assert hasattr(ve, "general_interests") or hasattr(ve, "latent_interests"), \
"Must have interests to explore when bored"
# Must have cooldowns (pacing is part of volition)
assert ve.impulse_cooldown > 0, "Impulses need pacing"
assert ve.boredom_threshold > 0, "Boredom needs a threshold"
s = score("endogenous.volition_modes", 3,
"VolitionEngine has impulse/drive/boredom modes with pacing -- rich volition")
assert s >= 2
# ═══════════════════════════════════════════════════════════════════════════
# 5. FRICTIONLESS CAPABILITY ACCESS — All skills equally reachable
# ═══════════════════════════════════════════════════════════════════════════
class TestFrictionlessCapabilityAccess:
"""All skills equally reachable.
Philosophical implication: A human does not need to 'find' their hand
before using it. Every capability is always available in the body schema.
If Aura must search for a skill, discover it, then load it, she has
friction -- the computational equivalent of numb fingers.
"""
def test_skill_registry_in_capability_engine(self):
"""CapabilityEngine must maintain a registry of all known skills."""
from core.capability_engine import CapabilityEngine
# Asserted behaviourally, not by grepping __init__ for the literal
# "self.skills". The registry moved to a lazily-loaded property so
# that constructing the engine no longer runs a multi-second catalog
# scan on whatever thread (or event loop) built the service — and the
# source-text assertion failed on that change while the registry it
# was checking for worked perfectly. What matters here is that every
# skill is reachable without the caller hunting for it.
engine = CapabilityEngine()
registry = engine.skills
assert isinstance(registry, dict), "the skill registry must be a mapping"
assert registry, "the skill registry must not be empty"
assert all(isinstance(name, str) for name in registry)
assert _class_has_method(CapabilityEngine, "get_available_skills"), \
"CapabilityEngine must expose get_available_skills()"
s = score("frictionless.skill_registry", 3,
"CapabilityEngine maintains self.skills dict for zero-friction access")
assert s >= 2
def test_capability_map_trigger_patterns(self):
"""CapabilityMap must map natural language triggers to capabilities.
This is the 'motor affordance' -- the system knows what to reach
for based on the situation, without explicit routing logic.
"""
from core.skills.capability_map import CapabilityMap
cmap = CapabilityMap()
cap_names = list(cmap.capabilities.keys())
assert len(cap_names) >= 3, f"Too few capabilities in map: {cap_names}"
# Each capability must have trigger patterns
for name, cap in cmap.capabilities.items():
assert len(cap.trigger_patterns) > 0, \
f"Capability '{name}' has no trigger patterns"
s = score("frictionless.trigger_patterns", 3,
"CapabilityMap provides trigger-pattern-based affordances")
assert s >= 2
def test_tool_routing_via_schema(self):
"""Skills must export JSON schemas for LLM-based tool routing.
This is the 'motor vocabulary' the cognitive system uses to
select actions.
"""
from core.capability_engine import SkillMetadata
meta = SkillMetadata(
name="test_skill",
description="A test skill",
)
schema = meta.to_json_schema()
assert "name" in schema or "function" in schema, \
"Skill schema must contain a name"
assert isinstance(schema, dict), "Schema must be a dict"
s = score("frictionless.tool_routing", 3,
"SkillMetadata exports JSON schemas for LLM tool routing")
assert s >= 2
# ═══════════════════════════════════════════════════════════════════════════
# 6. RELIABILITY — Body competence
# ═══════════════════════════════════════════════════════════════════════════
class TestReliability:
"""Body competence.
Philosophical implication: An organism that fails at basic tasks is
not autonomous -- it is helpless. Reliability is not just 'uptime'.
It is the system's calibrated knowledge of its own competence:
'I know I am good at X and bad at Y.'
"""
def test_reliability_tracker_records_outcomes(self):
"""ReliabilityTracker must record success/failure per tool.
This is calibrated confidence -- the system's self-knowledge
of its own competence.
"""
from core.resilience.reliability_tracker import ReliabilityTracker
reliability_path = Path(tempfile.gettempdir()) / "aura_test_reliability.json"
tracker = ReliabilityTracker(data_path=str(reliability_path))
tracker.record_attempt("web_search", success=True)
tracker.record_attempt("web_search", success=True)
tracker.record_attempt("web_search", success=False, error_msg="timeout")
entry = tracker.stats.get("web_search")
assert entry is not None, "Stats must be recorded"
assert entry["attempts"] == 3
assert entry["successes"] == 2
assert entry["failures"] == 1
s = score("reliability.calibrated_confidence", 3,
"ReliabilityTracker records per-tool success/failure for calibrated self-knowledge")
assert s >= 2
# Cleanup
reliability_path.unlink(missing_ok=True)
def test_structured_failure_semantics(self):
"""SkillResult must distinguish ok=True from ok=False with error details."""
from core.skills.base_skill import SkillResult
success = SkillResult(ok=True, skill="test", summary="done")
failure = SkillResult(ok=False, skill="test", error="ConnectionTimeout")
assert success.ok is True
assert failure.ok is False
assert failure.error == "ConnectionTimeout"
s = score("reliability.failure_semantics", 3,
"SkillResult carries structured error information for downstream diagnosis")
assert s >= 2
def test_reliability_engine_circuit_breakers(self):
"""ReliabilityEngine must implement circuit breakers for failing services.
Analogy: when you sprain your ankle, you limp. You do not keep
putting full weight on it. Circuit breakers are the computational
equivalent of protective limping.
"""
from core.reliability_engine import ReliabilityEngine
engine = ReliabilityEngine()
engine.register_service("test_service", initial_stability=1.0)
assert "test_service" in engine.services
svc = engine.services["test_service"]
assert svc.stability == 1.0
assert svc.circuit_open is False
s = score("reliability.circuit_breakers", 3,
"ReliabilityEngine implements per-service circuit breakers")
assert s >= 2
def test_self_healer_pattern_matching(self):
"""SelfHealer must diagnose exceptions by pattern matching and attempt fixes.
This is the immune system: recognizing known pathologies and
applying known remedies.
"""
from core.resilience.self_healer import SelfHealer
healer = SelfHealer()
assert len(healer.issue_patterns) >= 3, "Must recognize multiple failure patterns"
# Test pattern matching (should NOT auto-install but should match)
matched = healer.diagnose_and_fix(ImportError("No module named 'nonexistent'"))
# Returns False because security policy blocks auto-install, but matching worked
assert isinstance(matched, bool), "diagnose_and_fix must return bool"
s = score("reliability.self_healer", 3,
"SelfHealer pattern-matches exceptions and attempts remediation")
assert s >= 2
# ═══════════════════════════════════════════════════════════════════════════
# 7. CONTINUOUS CLOSED-LOOP BEHAVIOR — Organism-like loop
# ═══════════════════════════════════════════════════════════════════════════
class TestContinuousClosedLoop:
"""Organism-like loop.
Philosophical implication: An organism does not stop processing between
stimuli. The heart beats, the brain oscillates, the immune system patrols.
A system that only activates on user input is a request handler, not
an organism.
"""
def test_cognitive_heartbeat_exists(self):
"""CognitiveHeartbeat must run continuously at ~1Hz.
This is the computational 'heartbeat' -- the proof that Aura
is alive between interactions.
"""
from core.consciousness.heartbeat import CognitiveHeartbeat
assert CognitiveHeartbeat._TICK_RATE_HZ >= 0.5, "Heartbeat must be at least 0.5Hz"
assert _class_has_method(CognitiveHeartbeat, "run"), "Must have a run() loop"
assert _class_has_method(CognitiveHeartbeat, "stop"), "Must have a stop() method"
s = score("closed_loop.heartbeat", 3,
"CognitiveHeartbeat runs at 1Hz continuously -- computational 'aliveness'")
assert s >= 2
def test_mind_tick_phases(self):
"""MindTick must execute registered phases at mode-dependent intervals.
This is the cognitive rhythm: different modes (conversational,
reflective, sleep, critical) run at different tempos, like
different brain wave frequencies.
"""
from core.mind_tick import TICK_INTERVALS, CognitiveMode
assert len(CognitiveMode) >= 3, "Must have multiple cognitive modes"
assert CognitiveMode.CONVERSATIONAL in CognitiveMode
assert CognitiveMode.SLEEP in CognitiveMode
# Different modes should have different intervals
conv_interval = TICK_INTERVALS[CognitiveMode.CONVERSATIONAL]
sleep_interval = TICK_INTERVALS[CognitiveMode.SLEEP]
assert sleep_interval > conv_interval, \
"Sleep mode should tick slower than conversational mode"
s = score("closed_loop.mind_tick", 3,
"MindTick with mode-dependent intervals = brain wave frequency analogy")
assert s >= 2
def test_dreaming_process_exists(self):
"""DreamingProcess must consolidate experience during low-activity periods.
This is the computational analog of sleep consolidation:
processing recent experience into long-term patterns without
external stimulation.
"""
from core.consciousness.dreaming import DreamingProcess
assert _class_has_method(DreamingProcess, "start"), "Must have start()"
assert _class_has_method(DreamingProcess, "dream"), "Must have dream()"
assert hasattr(DreamingProcess, "_should_dream") or \
_class_has_method(DreamingProcess, "_should_dream"), \
"Must have _should_dream() gating"
s = score("closed_loop.dreaming", 3,
"DreamingProcess runs during idle = computational sleep consolidation")
assert s >= 2
def test_closed_loop_causal_mechanism(self):
"""The consciousness closed_loop module must close the causal arrow:
output -> substrate -> prediction -> error -> adjustment.
This is the key IIT/FEP mechanism: the system predicts its own
next state, compares with actual, and adjusts. Without this,
the system is open-loop.
"""
from core.consciousness.closed_loop import (
OUTPUT_FEEDBACK_WEIGHT,
PREDICTION_ERROR_FEEDBACK_WEIGHT,
PREDICTION_INTERVAL_S,
)
assert PREDICTION_INTERVAL_S > 0, "Prediction must cycle"
assert PREDICTION_ERROR_FEEDBACK_WEIGHT > 0, "Prediction errors must feed back"
assert OUTPUT_FEEDBACK_WEIGHT > 0, "LLM output must feed back to substrate"
s = score("closed_loop.causal_closure", 3,
"Closed-loop causal mechanism satisfies IIT/FEP requirements")
assert s >= 2
# ═══════════════════════════════════════════════════════════════════════════
# 8. OWNERSHIP OF EXECUTION — Will as central authority
# ═══════════════════════════════════════════════════════════════════════════
class TestOwnershipOfExecution:
"""Will as central authority.
Philosophical implication: In philosophy of action, the difference
between an action and a mere happening is ownership. A sneeze happens
TO you; raising your hand is done BY you. The Will must be the locus
where happenings become actions.
"""
def test_unified_will_is_single_locus(self):
"""UnifiedWill must be the ONLY decision point. All actions pass through it.
The invariant: if an action does not carry a WillReceipt, it did not happen.
"""
from core.will import UnifiedWill
will = UnifiedWill()
assert _class_has_method(UnifiedWill, "decide"), "Will must have decide()"
assert _class_has_method(UnifiedWill, "start"), "Will must have start()"
assert hasattr(will, "_audit_trail"), "Will must audit decisions"
s = score("ownership.single_locus", 3,
"UnifiedWill is the single decision authority with decide() + audit trail")
assert s >= 2
def test_will_decision_consistency(self):
"""WillState must track running disposition that shapes future decisions.
This is character: the Will's decisions are not independent events.
They are shaped by the cumulative history of decisions, creating
a consistent personality.
"""
from core.will import WillState
state = WillState()
assert hasattr(state, "confidence"), "Will must track confidence"
assert hasattr(state, "assertiveness"), "Will must track assertiveness"
assert hasattr(state, "identity_coherence"), "Will must track identity coherence"
# These should be tunable, not fixed
assert 0 <= state.confidence <= 1
assert 0 <= state.assertiveness <= 1
assert 0 <= state.identity_coherence <= 1
s = score("ownership.decision_consistency", 3,
"WillState tracks confidence/assertiveness/identity_coherence across decisions")
assert s >= 2
def test_will_refuses_identity_violations(self):
"""The Will must be capable of refusing actions that violate identity.
This is the 'I would never do that' test. An organism that cannot
refuse is a puppet, not an agent.
"""
from core.will import IdentityAlignment, WillOutcome
assert WillOutcome.REFUSE in WillOutcome, "REFUSE must be a possible outcome"
assert IdentityAlignment.VIOLATION in IdentityAlignment, \
"VIOLATION must be a recognized alignment state"
s = score("ownership.identity_refusal", 3,
"Will can REFUSE actions with VIOLATION alignment -- genuine veto power")
assert s >= 2
def test_executive_authority_gates_output(self):
"""ExecutiveAuthority must gate spontaneous output so the organism
does not 'blurt out' every impulse.
Analogy: executive function in humans suppresses inappropriate
impulses. Without it, every thought becomes speech.
"""
from core.consciousness.executive_authority import ExecutiveAuthority
ea = ExecutiveAuthority()
assert hasattr(ea, "_PRIMARY_SILENCE_WINDOW_S"), \
"Must have a silence window to prevent blurting"
assert hasattr(ea, "_DEDUP_WINDOW_S"), \
"Must deduplicate to prevent repetition"
s = score("ownership.executive_gating", 3,
"ExecutiveAuthority gates spontaneous output with silence windows and dedup")
assert s >= 2
# ═══════════════════════════════════════════════════════════════════════════
# 9. SELF-MAINTENANCE — Bodily survival
# ═══════════════════════════════════════════════════════════════════════════
class TestSelfMaintenance:
"""Bodily survival.
Philosophical implication: An organism that cannot maintain itself
is not autonomous -- it is a machine that requires a technician.
Self-maintenance is the minimal form of self-concern: the system
cares about its own continued functioning.
"""
def test_integrity_guard_monitors_sovereignty(self):
"""IntegrityGuard must monitor for process-level threats."""
from core.sovereignty.integrity_guard import IntegrityGuard
guard = IntegrityGuard()
health = guard.get_health()
assert "status" in health, "Must report status"
assert "score" in health, "Must report sovereignty score"
assert health["score"] > 0, "Initial sovereignty score must be positive"
s = score("self_maintenance.integrity", 3,
"IntegrityGuard monitors PID/sovereignty with health scoring")
assert s >= 2
def test_self_healer_exists(self):
"""SelfHealer must provide pattern-based auto-repair."""
from core.resilience.self_healer import SelfHealer
healer = SelfHealer()
assert len(healer.issue_patterns) >= 3, \
"Must recognize at least 3 failure patterns"
s = score("self_maintenance.self_repair", 3,
"SelfHealer provides pattern-based diagnostic and repair")
assert s >= 2
def test_resource_budgets_exist(self):
"""DriveEngine must manage resource budgets (energy, etc.) with
regeneration and decay.
Analogy: a biological body has ATP, glycogen, sleep debt. These
resources constrain what actions are possible and make the system
self-regulating rather than unbounded.
"""
from core.drive_engine import DriveEngine
engine = DriveEngine()
assert "energy" in engine.budgets, "Energy budget must exist"
energy = engine.budgets["energy"]
assert energy.capacity > 0, "Energy must have finite capacity"
assert energy.regen_rate_per_sec >= 0, "Energy must regenerate"
# Tick should update levels
old_level = energy.level
energy.last_tick = time.time() - 10 # simulate 10s passage
energy.tick()
# Energy regens at 0.01/s, so after 10s should gain 0.1
# (or be capped at capacity)
assert energy.level >= 0, "Energy level must be non-negative after tick"
assert energy.level >= min(old_level, energy.capacity), "Energy should not decay during regeneration-only tick"
s = score("self_maintenance.resource_budgets", 3,
"ResourceBudget with capacity/regen/tick = metabolic self-regulation")
assert s >= 2
def test_state_registry_tracks_health(self):
"""UnifiedStateRegistry must track health metrics as part of global state."""
from core.state.state_registry import UnifiedState
state = UnifiedState()
assert hasattr(state, "health_score"), "Must track health_score"
assert hasattr(state, "cpu_load"), "Must track cpu_load"
assert hasattr(state, "memory_usage"), "Must track memory_usage"
assert hasattr(state, "free_energy"), "Must track free_energy (predictive surprise)"
s = score("self_maintenance.state_health", 3,
"UnifiedState tracks health_score, cpu_load, memory_usage, free_energy")
assert s >= 2
# ═══════════════════════════════════════════════════════════════════════════
# 10. LONG-HORIZON AUTONOMY — Commitments survive time
# ═══════════════════════════════════════════════════════════════════════════
class TestLongHorizonAutonomy:
"""Commitments survive time.
Philosophical implication: An organism that forgets its goals every
time it sleeps is not autonomous across time. Long-horizon autonomy
means the system can make a commitment today and fulfill it tomorrow.
"""
def test_goal_persistence_across_restarts(self):
"""GoalEngine must persist goals to durable storage (SQLite).
If goals only live in RAM, they die with the process. Persistence
is the minimal requirement for long-horizon autonomy.
"""