Skip to content

Commit 31d52ed

Browse files
Copilotfermga
andcommitted
Implement validation-based THOL window closure per @fermga's bifurcation insight
Co-authored-by: fermga <203334638+fermga@users.noreply.github.com>
1 parent 6978ac4 commit 31d52ed

File tree

1 file changed

+87
-51
lines changed

1 file changed

+87
-51
lines changed

src/tnfr/operators/grammar.py

Lines changed: 87 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -793,31 +793,61 @@ def _consume(self, token: str, index: int) -> None:
793793
if canonical == DISSONANCE:
794794
self._found_dissonance = True
795795

796-
# Track THOL state: Structural time with automatic closure
796+
# Track THOL state: Bifurcation window with automatic validation-based closure
797797
#
798-
# TNFR Structural Time Principle: THOL closure emerges from bifurcation completion,
799-
# not from operator detection. Internal sequences are equivalent to external ones.
798+
# TNFR Bifurcation Window Principle: THOL window closes when internal sequence is valid
799+
# - THOL opens bifurcation window
800+
# - Window accumulates operators
801+
# - When sequence reaches valid end operator, try to validate
802+
# - If valid: close window automatically
803+
# - If not valid: continue accumulating
800804
#
801-
# Implementation for static validation:
802-
# - THOL opens a nested context
803-
# - Operators inside THOL are treated as normal sequence (can include SILENCE, etc.)
804-
# - THOL closes automatically at sequence end or parent THOL closure
805-
# - Nested THOL are supported (operational fractality)
805+
# This allows internal sequences to be identical to external ones:
806+
# they self-close when complete, no explicit delimiter needed.
806807
#
807-
# This allows internal sequences to be identical to external ones, including
808-
# having their own THOL blocks and using any valid end operators.
808+
# Empty window allowed (no bifurcation case: ∂²EPI/∂t² ≤ τ)
809809
if canonical == SELF_ORGANIZATION:
810-
# THOL opening: push to stack and initialize subsequence
810+
# THOL opening: push to stack and initialize bifurcation window
811811
self._thol_stack.append(index)
812812
self._thol_subsequences[index] = []
813813
self._open_thol = True
814814
elif self._open_thol and self._thol_stack:
815815
current_thol = self._thol_stack[-1]
816+
window_content = self._thol_subsequences[current_thol]
816817

817-
# All operators inside THOL are added to subsequence
818-
# No operator-based closure detection - THOL closes structurally
819-
# This allows internal sequences to be identical to external ones
818+
# Check if this is the first operator in window
819+
if len(window_content) == 0:
820+
# First operator after THOL opening
821+
# If it's not a valid start operator, window remains empty (no bifurcation)
822+
# and this operator belongs to external sequence
823+
if canonical not in VALID_START_OPERATORS:
824+
# Empty window - no bifurcation occurred
825+
# Close THOL immediately and process operator in parent context
826+
self._thol_stack.pop()
827+
self._open_thol = bool(self._thol_stack)
828+
# Don't add to window - process normally in parent context
829+
# (will be processed by subsequent validation logic)
830+
return
831+
832+
# Add operator to bifurcation window
820833
self._thol_subsequences[current_thol].append(canonical)
834+
835+
# Check if window is complete (sequence ends with valid end operator)
836+
# Try to close if last operator is a valid sequence end
837+
if canonical in VALID_END_OPERATORS and len(window_content) > 0:
838+
# Attempt to validate window as complete sequence
839+
try:
840+
# Create temporary automaton to test if window is valid
841+
test_automaton = _SequenceAutomaton()
842+
test_automaton.run(self._thol_subsequences[current_thol])
843+
844+
# Validation succeeded - window is complete, close THOL
845+
self._thol_stack.pop()
846+
self._open_thol = bool(self._thol_stack)
847+
848+
except SequenceSyntaxError:
849+
# Window not yet complete/valid - continue accumulating
850+
pass
821851

822852
# Validate sequential compatibility if not first token
823853
# Only validate if both prev and current are known operators
@@ -1031,48 +1061,52 @@ def _validate_thol_subsequence(
10311061
end_index: int,
10321062
end_token: str
10331063
) -> None:
1034-
"""Validate recursively the subsequence within THOL block.
1064+
"""Validate bifurcation window content within THOL block.
1065+
1066+
TNFR Bifurcation Window Principle: THOL requires explicit window that
1067+
contains bifurcation sequences. Window must be verified before proceeding.
10351068
1036-
TNFR Physical Principle: THOL (self-organization) always applies as operator,
1037-
but only generates sub-EPIs (and thus subsequence) if ∂²EPI/∂t² > τ.
1069+
Empty window is valid (THOL applied without bifurcation: ∂²EPI/∂t² ≤ τ).
1070+
Non-empty window must contain grammatically coherent sequence(s).
10381071
1039-
Empty THOL is physically valid - represents THOL application without bifurcation.
1040-
Non-empty subsequence represents sub-EPIs and must respect grammar rules (C1-C4).
1072+
Window semantics (from @fermga's structural time insight):
1073+
- Window opened by THOL, closed by CONTRACTION
1074+
- Content represents bifurcation space
1075+
- If bifurcation occurs: sequences written in window
1076+
- If no bifurcation: window remains empty
1077+
- Only after window validation, sequence proceeds to next operator
10411078
10421079
Parameters
10431080
----------
10441081
subsequence : list[str]
1045-
Operators within THOL block (between opening and closure)
1082+
Operators within THOL bifurcation window
10461083
start_index : int
10471084
Index of THOL opening in parent sequence
10481085
end_index : int
1049-
Index of THOL closure in parent sequence
1086+
Index of window closure in parent sequence
10501087
end_token : str
1051-
Token used for closure (for error messages)
1088+
Token used for closure (CONTRACTION)
10521089
10531090
Raises
10541091
------
10551092
SequenceSyntaxError
1056-
If subsequence is invalid (when non-empty)
1093+
If window content is invalid (when non-empty)
10571094
10581095
Notes
10591096
-----
10601097
From TNFR Manual §3.2.2 (Ontología fractal resonante):
10611098
"Los NFRs pueden anidarse jerárquicamente: un nodo puede contener
10621099
nodos internos coherentes, dando lugar a una estructura fractal."
10631100
1064-
From operator implementation: THOL bifurcates only if d2_epi > tau.
1065-
This means THOL can appear without generating sub-EPIs (empty subsequence).
1066-
1067-
When bifurcation occurs (non-empty subsequence), structures must be
1068-
coherent at all scales - operational fractality is maintained.
1101+
Bifurcation window enables operational fractality while maintaining
1102+
explicit structural boundaries.
10691103
"""
1070-
# Empty THOL is valid: THOL applied but no bifurcation occurred
1104+
# Empty window is valid: THOL applied without bifurcation
10711105
if not subsequence:
10721106
return
10731107

1074-
# Recursive grammar validation for non-empty subsequences
1075-
# Create new automaton to validate subsequence independently
1108+
# Recursive grammar validation for non-empty bifurcation window
1109+
# Create new automaton to validate window content independently
10761110
try:
10771111
nested_automaton = _SequenceAutomaton()
10781112
nested_automaton.run(subsequence)
@@ -1258,30 +1292,32 @@ def _finalize(self, names: Sequence[str]) -> None:
12581292
message=f"C3: missing stabilizer ({operator_display_name(COHERENCE)} or {operator_display_name(SELF_ORGANIZATION)}) - integral divergence (BOUNDEDNESS constraint)",
12591293
)
12601294

1261-
# Self-organization block closure (structural time)
1262-
# THOL closes automatically at sequence end - validates all captured subsequences
1295+
# Self-organization bifurcation window closure
1296+
# Empty window is valid (no bifurcation: ∂²EPI/∂t² ≤ τ)
1297+
# Non-empty window must contain valid sequence (bifurcation occurred)
12631298
if self._open_thol:
1264-
# Close all open THOL blocks from innermost to outermost
1299+
# Close all open THOL windows with their current content
12651300
while self._thol_stack:
12661301
thol_start = self._thol_stack.pop()
1267-
thol_subseq = self._thol_subsequences[thol_start]
1302+
window_content = self._thol_subsequences[thol_start]
1303+
1304+
# Empty window is valid (THOL without bifurcation)
1305+
if len(window_content) == 0:
1306+
continue # Valid empty window
12681307

1269-
# Validate subsequence (allows empty THOL - no bifurcation case)
1270-
if len(thol_subseq) > 0:
1271-
try:
1272-
self._validate_thol_subsequence(
1273-
thol_subseq,
1274-
thol_start,
1275-
len(names) - 1,
1276-
names[-1] if names else ""
1277-
)
1278-
except SequenceSyntaxError as e:
1279-
# Re-raise with THOL context
1280-
raise SequenceSyntaxError(
1281-
index=e.index,
1282-
token=e.token,
1283-
message=f"Invalid THOL subsequence (opened at position {thol_start}): {e.message}"
1284-
) from e
1308+
# Non-empty window: validate as complete sequence
1309+
# If window was not auto-closed during parsing, check if valid at sequence end
1310+
try:
1311+
nested_automaton = _SequenceAutomaton()
1312+
nested_automaton.run(window_content)
1313+
# Valid - window is complete
1314+
except SequenceSyntaxError as e:
1315+
# Invalid/incomplete window
1316+
raise SequenceSyntaxError(
1317+
index=len(names) - 1,
1318+
token=names[-1] if names else "",
1319+
message=f"Invalid {operator_display_name(SELF_ORGANIZATION)} bifurcation window (opened at position {thol_start}): {e.message}"
1320+
) from e
12851321

12861322
self._open_thol = False
12871323

0 commit comments

Comments
 (0)