@@ -793,35 +793,45 @@ def _consume(self, token: str, index: int) -> None:
793793 if canonical == DISSONANCE :
794794 self ._found_dissonance = True
795795
796- # Track THOL state with recursive support
796+ # Track THOL state: Use balanced nesting to allow SILENCE/CONTRACTION inside THOL
797+ # TNFR Physical Principle: THOL applies as operator, bifurcates if d2_epi > tau
798+ # Empty THOL valid (no bifurcation), non-empty must be grammatically coherent
799+ # Closure: First SILENCE/CONTRACTION at nesting depth 0 closes THOL
797800 if canonical == SELF_ORGANIZATION :
798801 # THOL opening: push to stack and initialize subsequence
799802 self ._thol_stack .append (index )
800803 self ._thol_subsequences [index ] = []
801804 self ._open_thol = True
802- elif self ._open_thol and canonical in SELF_ORGANIZATION_CLOSURES :
803- # THOL closure: validate subsequence recursively
804- if not self ._thol_stack :
805- raise SequenceSyntaxError (
806- index = index ,
807- token = token ,
808- message = f"{ operator_display_name (canonical )} closure without corresponding { operator_display_name (SELF_ORGANIZATION )} opening"
809- )
810-
811- thol_start = self ._thol_stack .pop ()
812- thol_subseq = self ._thol_subsequences [thol_start ]
805+ elif self ._open_thol and self ._thol_stack :
806+ current_thol = self ._thol_stack [- 1 ]
813807
814- # Validate THOL subsequence recursively
815- self ._validate_thol_subsequence (thol_subseq , thol_start , index , token )
808+ # Check if this operator closes THOL BEFORE adding to subsequence
809+ # This allows SILENCE/CONTRACTION inside THOL as sequence operators
810+ if canonical in SELF_ORGANIZATION_CLOSURES :
811+ # Count nested THOL blocks to determine nesting depth
812+ subseq = self ._thol_subsequences [current_thol ]
813+ nested_thol_count = 0
814+ for op in subseq :
815+ if op == SELF_ORGANIZATION :
816+ nested_thol_count += 1
817+ elif op in SELF_ORGANIZATION_CLOSURES :
818+ nested_thol_count -= 1
819+
820+ # Close THOL if we're at depth 0 (no unclosed nested THOL)
821+ if nested_thol_count == 0 :
822+ thol_start = self ._thol_stack .pop ()
823+ final_subseq = self ._thol_subsequences [thol_start ]
824+
825+ # Validate THOL subsequence
826+ # Empty THOL valid (no bifurcation), non-empty must be coherent
827+ self ._validate_thol_subsequence (final_subseq , thol_start , index , token )
828+
829+ # Update _open_thol based on stack state (supports nested THOL)
830+ self ._open_thol = bool (self ._thol_stack )
831+ return # Don't add closure operator to subsequence
816832
817- # Update _open_thol based on stack state (supports nested THOL)
818- self ._open_thol = bool (self ._thol_stack )
819- elif self ._open_thol and self ._thol_stack :
820- # Track operators within THOL block (excluding nested THOL openings)
821- # Nested THOL openings are handled separately, closures are part of inner subsequence
822- if canonical != SELF_ORGANIZATION :
823- current_thol = self ._thol_stack [- 1 ]
824- self ._thol_subsequences [current_thol ].append (canonical )
833+ # Add operator to current THOL subsequence
834+ self ._thol_subsequences [current_thol ].append (canonical )
825835
826836 # Validate sequential compatibility if not first token
827837 # Only validate if both prev and current are known operators
@@ -1037,10 +1047,11 @@ def _validate_thol_subsequence(
10371047 ) -> None :
10381048 """Validate recursively the subsequence within THOL block.
10391049
1040- TNFR Fractal Principle: THOL (self-organization) is a fractal operator
1041- that encapsulates autonomous reorganization. The subsequence must:
1042- 1. Be non-empty (THOL without content is meaningless)
1043- 2. Respect all grammar rules R1-R6 (recursive coherence)
1050+ TNFR Physical Principle: THOL (self-organization) always applies as operator,
1051+ but only generates sub-EPIs (and thus subsequence) if ∂²EPI/∂t² > τ.
1052+
1053+ Empty THOL is physically valid - represents THOL application without bifurcation.
1054+ Non-empty subsequence represents sub-EPIs and must respect grammar rules (C1-C4).
10441055
10451056 Parameters
10461057 ----------
@@ -1056,33 +1067,25 @@ def _validate_thol_subsequence(
10561067 Raises
10571068 ------
10581069 SequenceSyntaxError
1059- If subsequence is empty or invalid
1070+ If subsequence is invalid (when non-empty)
10601071
10611072 Notes
10621073 -----
10631074 From TNFR Manual §3.2.2 (Ontología fractal resonante):
10641075 "Los NFRs pueden anidarse jerárquicamente: un nodo puede contener
10651076 nodos internos coherentes, dando lugar a una estructura fractal."
10661077
1067- This validation ensures THOL maintains operational fractality:
1068- structures are coherent at all scales .
1078+ From operator implementation: THOL bifurcates only if d2_epi > tau.
1079+ This means THOL can appear without generating sub-EPIs (empty subsequence) .
10691080
1070- Autonomy is implicit: if the subsequence passes all grammar rules,
1071- it is by definition autonomous (can function independently) .
1081+ When bifurcation occurs (non-empty subsequence), structures must be
1082+ coherent at all scales - operational fractality is maintained .
10721083 """
1073- # Validation 1: Non-empty subsequence
1084+ # Empty THOL is valid: THOL applied but no bifurcation occurred
10741085 if not subsequence :
1075- raise SequenceSyntaxError (
1076- index = end_index ,
1077- token = end_token ,
1078- message = (
1079- f"{ operator_display_name (SELF_ORGANIZATION )} block is empty "
1080- f"(opened at position { start_index } ). Subsequence must contain "
1081- f"at least one operator for autonomous reorganization."
1082- )
1083- )
1086+ return
10841087
1085- # Validation 2: Recursive grammar validation
1088+ # Recursive grammar validation for non-empty subsequences
10861089 # Create new automaton to validate subsequence independently
10871090 try :
10881091 nested_automaton = _SequenceAutomaton ()
0 commit comments