tgi-foundation 0.2.0.dev0__py3-none-any.whl

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.
Files changed (252) hide show
  1. tgi/__init__.py +7 -0
  2. tgi/__main__.py +194 -0
  3. tgi/acquisition_history.py +45 -0
  4. tgi/acquisition_history_check.py +51 -0
  5. tgi/acquisition_monitor.py +66 -0
  6. tgi/acquisition_monitor_check.py +78 -0
  7. tgi/acquisition_projection.py +70 -0
  8. tgi/acquisition_projection_check.py +93 -0
  9. tgi/acquisition_role_cells.py +53 -0
  10. tgi/acquisition_role_constraints.py +13 -0
  11. tgi/acquisition_role_constraints_check.py +66 -0
  12. tgi/acquisition_snapshot.py +35 -0
  13. tgi/acquisition_stream.py +21 -0
  14. tgi/acquisition_witness.py +117 -0
  15. tgi/actuation_goal_frontier.py +117 -0
  16. tgi/actuation_goal_frontier_check.py +147 -0
  17. tgi/actuation_goal_workflow.py +159 -0
  18. tgi/actuation_sequence_feedback.py +41 -0
  19. tgi/actuation_sequence_feedback_check.py +43 -0
  20. tgi/ask_certificate.py +74 -0
  21. tgi/bands.py +59 -0
  22. tgi/capacity_graph.py +70 -0
  23. tgi/closed_actuation_goal_frontier.py +13 -0
  24. tgi/closed_actuation_goal_frontier_check.py +19 -0
  25. tgi/closed_actuation_goal_workflow.py +159 -0
  26. tgi/closure.py +202 -0
  27. tgi/compact_acquisition_map.py +68 -0
  28. tgi/compact_acquisition_map_check.py +91 -0
  29. tgi/compact_complete_role_core.py +36 -0
  30. tgi/compact_complete_role_core_check.py +62 -0
  31. tgi/compact_measured_path.py +84 -0
  32. tgi/compact_role_observation.py +13 -0
  33. tgi/compact_role_observation_check.py +66 -0
  34. tgi/compatible_joins.py +33 -0
  35. tgi/complete_role_core.py +53 -0
  36. tgi/complete_role_core_check.py +54 -0
  37. tgi/context_family_selection.py +45 -0
  38. tgi/context_family_selection_check.py +32 -0
  39. tgi/context_family_separation.py +43 -0
  40. tgi/context_family_separation_check.py +47 -0
  41. tgi/contextual_isometry.py +62 -0
  42. tgi/contextual_isometry_check.py +54 -0
  43. tgi/continuation_checkpoint.py +75 -0
  44. tgi/continuation_cycle.py +102 -0
  45. tgi/continuation_goal_frontier.py +13 -0
  46. tgi/continuation_goal_frontier_check.py +19 -0
  47. tgi/continuation_goal_workflow.py +159 -0
  48. tgi/continuation_learning.py +36 -0
  49. tgi/continuation_learning_check.py +53 -0
  50. tgi/correspondence.py +76 -0
  51. tgi/cross_action_correspondence.py +182 -0
  52. tgi/cross_action_correspondence_check.py +92 -0
  53. tgi/cross_view_identity_map.py +41 -0
  54. tgi/cross_view_identity_map_check.py +48 -0
  55. tgi/derivation.py +74 -0
  56. tgi/empirical_transport.py +74 -0
  57. tgi/empirical_transport_check.py +78 -0
  58. tgi/events.py +36 -0
  59. tgi/evidence_response.py +24 -0
  60. tgi/evidence_response_check.py +33 -0
  61. tgi/exact_field.py +101 -0
  62. tgi/experience.py +68 -0
  63. tgi/experience_cli.py +44 -0
  64. tgi/feedback_update.py +32 -0
  65. tgi/feedback_update_check.py +38 -0
  66. tgi/formation.py +74 -0
  67. tgi/frame_cli.py +26 -0
  68. tgi/frame_engine.py +214 -0
  69. tgi/functional_capacity.py +74 -0
  70. tgi/functional_capacity_check.py +110 -0
  71. tgi/functional_transition.py +40 -0
  72. tgi/functional_transition_check.py +58 -0
  73. tgi/geometry.py +143 -0
  74. tgi/grounding.py +285 -0
  75. tgi/guarded_word_closure.py +148 -0
  76. tgi/guarded_word_closure_check.py +171 -0
  77. tgi/guarded_word_goal_frontier.py +13 -0
  78. tgi/guarded_word_goal_frontier_check.py +19 -0
  79. tgi/guarded_word_goal_workflow.py +160 -0
  80. tgi/identity.py +32 -0
  81. tgi/incidence.py +155 -0
  82. tgi/incremental.py +134 -0
  83. tgi/intervention_composition.py +63 -0
  84. tgi/intervention_composition_check.py +84 -0
  85. tgi/intervention_continuity.py +43 -0
  86. tgi/intervention_continuity_check.py +56 -0
  87. tgi/intervention_correspondence.py +156 -0
  88. tgi/intervention_correspondence_check.py +80 -0
  89. tgi/intervention_edit_contrast.py +27 -0
  90. tgi/intervention_edit_contrast_check.py +41 -0
  91. tgi/intervention_experiment.py +62 -0
  92. tgi/intervention_experiment_check.py +78 -0
  93. tgi/intervention_resolution.py +45 -0
  94. tgi/intervention_resolution_check.py +70 -0
  95. tgi/intervention_roles.py +83 -0
  96. tgi/intervention_roles_check.py +91 -0
  97. tgi/intervention_scope.py +34 -0
  98. tgi/intervention_sequence_experiment.py +71 -0
  99. tgi/intervention_sequence_experiment_check.py +97 -0
  100. tgi/interventions.py +240 -0
  101. tgi/joint_correspondence.py +73 -0
  102. tgi/joint_frontier_acquisition.py +114 -0
  103. tgi/joint_frontier_acquisition_check.py +116 -0
  104. tgi/joint_goal_observation.py +49 -0
  105. tgi/joint_goal_observation_check.py +55 -0
  106. tgi/joint_goal_traversal.py +101 -0
  107. tgi/joint_goal_traversal_check.py +114 -0
  108. tgi/joint_observed_laws.py +40 -0
  109. tgi/joint_observed_laws_check.py +63 -0
  110. tgi/joint_temporal_candidates.py +40 -0
  111. tgi/joint_temporal_candidates_check.py +68 -0
  112. tgi/lineage_knowledge.py +29 -0
  113. tgi/lineage_knowledge_check.py +41 -0
  114. tgi/lineage_state.py +39 -0
  115. tgi/lineage_state_check.py +47 -0
  116. tgi/local_acquisition_ownership.py +65 -0
  117. tgi/local_acquisition_runtime.py +119 -0
  118. tgi/local_acquisition_selection.py +41 -0
  119. tgi/local_acquisition_transition.py +50 -0
  120. tgi/local_acquisition_transition_check.py +80 -0
  121. tgi/local_edit_transport_classes.py +220 -0
  122. tgi/local_edit_transport_classes_check.py +128 -0
  123. tgi/local_evidence_persistence.py +67 -0
  124. tgi/measured_actuation_transition.py +56 -0
  125. tgi/measured_actuation_transition_check.py +81 -0
  126. tgi/measured_capacity.py +61 -0
  127. tgi/measured_context.py +52 -0
  128. tgi/measured_context_check.py +65 -0
  129. tgi/measured_context_laws.py +75 -0
  130. tgi/measured_context_laws_check.py +91 -0
  131. tgi/measured_context_layout.py +49 -0
  132. tgi/measured_occurrence_path.py +70 -0
  133. tgi/momentum.py +43 -0
  134. tgi/observation_context_laws.py +32 -0
  135. tgi/observation_context_laws_check.py +40 -0
  136. tgi/observation_epochs.py +35 -0
  137. tgi/observation_epochs_check.py +51 -0
  138. tgi/observation_point.py +92 -0
  139. tgi/observation_projection.py +45 -0
  140. tgi/observation_projection_check.py +48 -0
  141. tgi/observed_actuation_cycle.py +114 -0
  142. tgi/observed_actuation_discovery.py +41 -0
  143. tgi/observed_actuation_discovery_check.py +54 -0
  144. tgi/observed_actuation_learning.py +71 -0
  145. tgi/observed_actuation_learning_check.py +73 -0
  146. tgi/observed_actuation_runtime.py +114 -0
  147. tgi/observed_context_actions.py +66 -0
  148. tgi/observed_context_actions_check.py +81 -0
  149. tgi/observed_joint_state.py +52 -0
  150. tgi/observed_joint_state_check.py +55 -0
  151. tgi/observed_refinement.py +43 -0
  152. tgi/observed_response.py +20 -0
  153. tgi/observed_response_check.py +27 -0
  154. tgi/observed_role_core.py +41 -0
  155. tgi/observed_role_core_check.py +54 -0
  156. tgi/occurrence_route.py +56 -0
  157. tgi/operator_windows.py +84 -0
  158. tgi/operator_windows_check.py +111 -0
  159. tgi/organization.py +484 -0
  160. tgi/organization_check.py +143 -0
  161. tgi/organization_cli.py +77 -0
  162. tgi/organization_inventory_check.py +82 -0
  163. tgi/organization_snapshot.py +50 -0
  164. tgi/path_isometry.py +82 -0
  165. tgi/path_temporal_feasibility.py +69 -0
  166. tgi/phase_evidence.py +100 -0
  167. tgi/port_distinction_exploration.py +37 -0
  168. tgi/port_distinction_exploration_check.py +40 -0
  169. tgi/proofcheck.py +117 -0
  170. tgi/provenance.py +19 -0
  171. tgi/recent_observation.py +145 -0
  172. tgi/relational.py +222 -0
  173. tgi/resonance.py +114 -0
  174. tgi/response_eligibility.py +46 -0
  175. tgi/response_eligibility_check.py +55 -0
  176. tgi/response_interval_order.py +59 -0
  177. tgi/response_interval_order_check.py +92 -0
  178. tgi/response_readout.py +53 -0
  179. tgi/response_readout_check.py +73 -0
  180. tgi/role_bundle.py +31 -0
  181. tgi/role_bundle_check.py +20 -0
  182. tgi/role_candidates.py +47 -0
  183. tgi/role_candidates_check.py +57 -0
  184. tgi/role_eligibility.py +34 -0
  185. tgi/role_eligibility_check.py +46 -0
  186. tgi/role_feedback.py +15 -0
  187. tgi/role_feedback_check.py +23 -0
  188. tgi/role_history.py +37 -0
  189. tgi/role_history_check.py +51 -0
  190. tgi/role_projection.py +16 -0
  191. tgi/role_projection_check.py +85 -0
  192. tgi/role_proposal.py +39 -0
  193. tgi/role_proposal_check.py +51 -0
  194. tgi/role_readout.py +31 -0
  195. tgi/role_readout_check.py +51 -0
  196. tgi/role_response.py +34 -0
  197. tgi/role_response_check.py +40 -0
  198. tgi/role_work.py +54 -0
  199. tgi/scoped_sequence_experiment.py +20 -0
  200. tgi/scoped_sequence_experiment_check.py +33 -0
  201. tgi/separation.py +74 -0
  202. tgi/separation_check.py +87 -0
  203. tgi/sequence_prefix_feedback.py +57 -0
  204. tgi/sequence_prefix_feedback_check.py +79 -0
  205. tgi/source_intervals.py +85 -0
  206. tgi/source_intervals_check.py +97 -0
  207. tgi/spatial.py +109 -0
  208. tgi/spatial_action_observation.py +88 -0
  209. tgi/spatial_action_relation.py +53 -0
  210. tgi/spatial_action_relation_check.py +45 -0
  211. tgi/spatial_action_relation_cycle.py +84 -0
  212. tgi/spatial_action_relation_migration.py +41 -0
  213. tgi/spatial_action_relation_migration_bundle.py +60 -0
  214. tgi/spatial_contextual_action_cycle.py +130 -0
  215. tgi/spatial_contextual_action_local.py +79 -0
  216. tgi/spatial_contextual_action_phase.py +81 -0
  217. tgi/spatial_contextual_action_phase_check.py +81 -0
  218. tgi/spatial_direct_action_cycle.py +98 -0
  219. tgi/spatial_direct_action_relation.py +60 -0
  220. tgi/spatial_direct_action_relation_check.py +67 -0
  221. tgi/spatial_local_action_cycle.py +62 -0
  222. tgi/spatial_local_action_relation.py +66 -0
  223. tgi/spatial_temporal_action_cycle.py +116 -0
  224. tgi/spatial_temporal_action_local.py +77 -0
  225. tgi/spatial_temporal_action_phase.py +89 -0
  226. tgi/spatial_temporal_action_phase_check.py +94 -0
  227. tgi/structural_append_closure.py +99 -0
  228. tgi/structural_append_closure_check.py +106 -0
  229. tgi/structural_continuation_closure.py +93 -0
  230. tgi/structural_continuation_closure_check.py +108 -0
  231. tgi/temporal_candidate_spectrum.py +57 -0
  232. tgi/temporal_candidate_spectrum_check.py +94 -0
  233. tgi/temporal_correspondence.py +41 -0
  234. tgi/temporal_correspondence_check.py +56 -0
  235. tgi/temporal_projection.py +41 -0
  236. tgi/temporal_projection_check.py +56 -0
  237. tgi/transport.py +294 -0
  238. tgi/transport_cli.py +27 -0
  239. tgi/unlabeled_port_classes.py +199 -0
  240. tgi/unlabeled_port_classes_check.py +113 -0
  241. tgi/unobserved_action_selection.py +47 -0
  242. tgi/unobserved_action_selection_check.py +40 -0
  243. tgi/verification.py +98 -0
  244. tgi/witness_function.py +62 -0
  245. tgi/witness_probe.py +50 -0
  246. tgi/witness_probe_feedback.py +106 -0
  247. tgi/witness_response.py +67 -0
  248. tgi_foundation-0.2.0.dev0.dist-info/METADATA +30 -0
  249. tgi_foundation-0.2.0.dev0.dist-info/RECORD +252 -0
  250. tgi_foundation-0.2.0.dev0.dist-info/WHEEL +5 -0
  251. tgi_foundation-0.2.0.dev0.dist-info/licenses/LICENSE +3 -0
  252. tgi_foundation-0.2.0.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,53 @@
1
+ """Native visible intervention-role partitions; no world-object labels."""
2
+ from copy import deepcopy
3
+ from tgi.identity import decode,encode
4
+ from tgi.organization import OMEGA_CRIT
5
+ from tgi.acquisition_snapshot import acquisition_snapshot as snapshot
6
+ from tgi.acquisition_witness import certify_raw_acquisition_witness as certify_acquisition_witness
7
+ from tgi.compact_measured_path import _decimal_count
8
+ from tgi.role_work import RoleSearchBudget
9
+
10
+
11
+ def _cells(acquisition,groups,measurements):
12
+ view=snapshot(acquisition);witness=certify_acquisition_witness(view,measurements)
13
+ if not isinstance(groups,list) or not groups:raise ValueError('Groups required')
14
+ lookup={(r['source'],r['frame']):r for r in measurements}
15
+ if len(lookup)!=len(measurements):raise ValueError('One full-frame measurement required')
16
+ expected={(s,i) for s,(frames,_) in view.episodes.items() for i in range(len(frames))}
17
+ if set(lookup)!=expected:raise ValueError('Complete measurement coverage required')
18
+ for (s,i),r in lookup.items():
19
+ if r['start']!=0 or r['stop']!=len(view.episodes[s][0][i]):raise ValueError('Whole-frame measurements required')
20
+ ports=[];used=set();records=[];diversity={};windows=[]
21
+ for group in groups:
22
+ if not isinstance(group,list) or not group:raise ValueError('Nonempty view group required')
23
+ cells={};actions=set();action_bounds=set();context_windows={};before_values={}
24
+ for spec in group:
25
+ if not isinstance(spec,dict) or set(spec)!={'port','source'}:raise ValueError('Invalid view layout')
26
+ port=spec['port'];source=spec['source']
27
+ encode(port)
28
+ if not isinstance(port,str) or not port or port in cells or source in used or source not in view.episodes:raise ValueError('Duplicate or missing view source')
29
+ frames=view.episodes[source][0]
30
+ if len(frames)!=3:raise ValueError('Exactly before/action/after frames required')
31
+ used.add(source);actions.add(decode(frames[1]))
32
+ if port not in ports:ports.append(port);diversity[port]=set()
33
+ before,action,after=(lookup[source,i] for i in range(3))
34
+ action_bounds.add((action['clock'],action['lower'],action['upper']))
35
+ context_windows[port]=(before['clock'],before['lower'],after['upper'])
36
+ before_values[port]=frames[0]
37
+ certain=len({before['clock'],action['clock'],after['clock']})==1 and before['upper']<=action['lower'] and action['upper']<=after['lower']
38
+ value=int(frames[0]!=frames[2]) if certain else None
39
+ cells[port]=value
40
+
41
+ if len(actions)!=1 or len(action_bounds)!=1:raise ValueError('One consistent measured action per group required')
42
+ windows.append(next(iter(action_bounds)))
43
+ records.append({'action':next(iter(actions)),'cells':cells,'windows':context_windows,'before':before_values})
44
+ if used!=set(view.episodes):raise ValueError('Complete source coverage required')
45
+ for index,r in enumerate(records):
46
+ for port,value in list(r['cells'].items()):
47
+ clock,lower,upper=r['windows'][port]
48
+ if any(other_clock!=clock or not (other_upper<lower or other_lower>upper) for j,(other_clock,other_lower,other_upper) in enumerate(windows) if j!=index):value=None
49
+ r['cells'][port]=value
50
+ if value==1:diversity[port].add(r['before'][port])
51
+ rows=[{'action':r['action'],'cells':[r['cells'].get(p) for p in ports]} for r in records]
52
+ return witness,ports,rows,[len(diversity[p]) for p in ports]
53
+
@@ -0,0 +1,13 @@
1
+ """Exact full original binary role domain without enumerating its completions."""
2
+ from copy import deepcopy
3
+ from tgi.acquisition_snapshot import acquisition_snapshot as snapshot
4
+ from tgi.acquisition_role_cells import _cells
5
+ from tgi.role_work import RoleSearchBudget
6
+
7
+
8
+ def certify_compact_role_constraints(model,groups,measurements,*,max_search_steps=None):
9
+ budget=RoleSearchBudget(max_search_steps)
10
+ with budget.scope():
11
+ budget.consume();groups,measurements=deepcopy((groups,measurements));witness,ports,rows,diversity=_cells(snapshot(model),groups,measurements)
12
+ budget.consume_many(sum(len(r['cells']) for r in rows));free=sum(x is None for r in rows for x in r['cells'])
13
+ return {'policy':'compact_acquisition_role_constraints_v119','groups':groups,'witness':witness,'ports':ports,'rows':rows,'changed_before_diversity':diversity,'completions':{'base':2,'exponent':free},'status':'UNCERTAIN_ATTRIBUTION' if free else 'DETERMINED_VISIBLE_ROLES'}
@@ -0,0 +1,66 @@
1
+ """Independent source/cell/complete-partition verifier for visible roles."""
2
+ from copy import deepcopy
3
+ from tgi.identity import decode,encode
4
+ from tgi.organization import OMEGA_CRIT
5
+ from tgi.acquisition_snapshot import acquisition_snapshot as snapshot
6
+ from tgi.acquisition_witness import verify_raw_acquisition_witness as verify_acquisition_witness
7
+ from tgi.compact_measured_path import _decimal_count
8
+ from tgi.frame_engine import canonical
9
+ from tgi.role_work import RoleSearchBudget
10
+
11
+
12
+ def verify_compact_role_constraints(acquisition,groups,measurements,certificate,*,max_search_steps=None):
13
+ budget=RoleSearchBudget(max_search_steps)
14
+ with budget.scope():
15
+ budget.consume()
16
+ try:
17
+ fields={'policy','groups','witness','ports','rows','changed_before_diversity','completions','status'}
18
+ c=certificate
19
+ if set(c)!=fields or c['policy']!='compact_acquisition_role_constraints_v119' or canonical(c['groups'])!=canonical(groups):return False
20
+ view=snapshot(acquisition);groups=deepcopy(groups);measurements=deepcopy(measurements)
21
+ if not verify_acquisition_witness(view,measurements,c['witness']):return False
22
+ if not isinstance(groups,list) or not groups:return False
23
+ measured={};expected={(s,i) for s,(frames,_) in view.episodes.items() for i in range(len(frames))}
24
+ for r in measurements:
25
+ k=(r['source'],r['frame'])
26
+ if k in measured or r['start']!=0 or r['stop']!=len(view.episodes[k[0]][0][k[1]]):return False
27
+ measured[k]=r
28
+ if set(measured)!=expected:return False
29
+ ports=[];used=set();cells=[];raw_inputs={};operations=[]
30
+ for group in groups:
31
+ if not isinstance(group,list) or not group:return False
32
+ observed={};action_values=[];op_bounds=set();windows={};before_values={}
33
+ for spec in group:
34
+ if not isinstance(spec,dict) or set(spec)!={'port','source'}:return False
35
+ p,s=spec['port'],spec['source']
36
+ encode(p)
37
+ if not isinstance(p,str) or not p or p in observed or s in used or s not in view.episodes:return False
38
+ frames=view.episodes[s][0]
39
+ if len(frames)!=3:return False
40
+ used.add(s)
41
+ if p not in ports:ports.append(p);raw_inputs[p]=set()
42
+ action_values.append(decode(frames[1]));bounds=[measured[s,i] for i in range(3)]
43
+ op_bounds.add((bounds[1]['clock'],bounds[1]['lower'],bounds[1]['upper']))
44
+ windows[p]=(bounds[0]['clock'],bounds[0]['lower'],bounds[2]['upper']);before_values[p]=frames[0]
45
+ value=None
46
+ if all(r['clock']==bounds[0]['clock'] for r in bounds) and bounds[0]['upper']<=bounds[1]['lower'] and bounds[1]['upper']<=bounds[2]['lower']:
47
+ value=0 if frames[0]==frames[2] else 1
48
+ observed[p]=value
49
+
50
+ if len(set(action_values))!=1 or len(op_bounds)!=1:return False
51
+ operations.append(next(iter(op_bounds)));cells.append((action_values[0],observed,windows,before_values))
52
+ if used!=set(view.episodes) or canonical(ports)!=canonical(c['ports']):return False
53
+ for index,(_,values,windows,before_values) in enumerate(cells):
54
+ for port in values:
55
+ clock,begin,end=windows[port]
56
+ for other,(op_clock,op_begin,op_end) in enumerate(operations):
57
+ if other==index:continue
58
+ if op_clock!=clock or not (op_end<begin or end<op_begin):values[port]=None;break
59
+ if values[port]==1:raw_inputs[port].add(before_values[port])
60
+ rows=[{'action':a,'cells':[values.get(p) for p in ports]} for a,values,_,_ in cells]
61
+ diversity=[len(raw_inputs[p]) for p in ports]
62
+ if canonical(rows)!=canonical(c['rows']) or canonical(diversity)!=canonical(c['changed_before_diversity']):return False
63
+ budget.consume_many(sum(len(r['cells']) for r in rows));free=sum(value is None for row in rows for value in row['cells'])
64
+ expected={'base':2,'exponent':free}
65
+ return canonical(c['completions'])==canonical(expected) and c['status']==('UNCERTAIN_ATTRIBUTION' if free else 'DETERMINED_VISIBLE_ROLES')
66
+ except (ValueError,TypeError,KeyError,IndexError,AttributeError):return False
@@ -0,0 +1,35 @@
1
+ """Immutable original frame evidence; explicitly cannot authorize knowledge."""
2
+ from types import MappingProxyType
3
+ from .organization import RawOrganization
4
+ from .organization_snapshot import _Frames
5
+ from .frame_engine import Receipt
6
+
7
+
8
+ class AcquisitionSnapshot(RawOrganization):
9
+ _acquisition_only=True
10
+
11
+ def __init__(self,engine):
12
+ if not isinstance(engine,RawOrganization):raise TypeError('Original acquisition model required')
13
+ if getattr(engine.frames,'_pending',None):raise ValueError('Pending frame is not complete acquisition evidence')
14
+ episodes=dict(engine.episodes)
15
+ for value in episodes.values():
16
+ if type(value) is not tuple or len(value)!=2 or type(value[0]) is not tuple or type(value[1]) is not tuple or any(type(f) is not tuple for f in value[0]) or any(type(r) is not Receipt for r in value[1]):raise ValueError('Immutable original episode/receipt containers required')
17
+ self.frames=_Frames(engine.frames.view());self.episodes=MappingProxyType(episodes)
18
+ self.organizations=MappingProxyType({});self.rejected_organizations=MappingProxyType({})
19
+ self._dirty=True;self._valid={}
20
+
21
+ def _alive(self,source):
22
+ if source not in self._valid:self._valid[source]=super()._alive(source)
23
+ return self._valid[source]
24
+
25
+ def observe(self,*args,**kwargs):raise TypeError('Acquisition snapshot is read-only')
26
+ def form(self,*args,**kwargs):raise TypeError('Acquisition snapshot cannot form knowledge')
27
+ def resolve(self,*args,**kwargs):raise TypeError('Acquisition snapshot cannot resolve knowledge')
28
+ def _phase_valid(self,*args,**kwargs):raise TypeError('Acquisition snapshot cannot admit knowledge phase')
29
+ def save(self,*args,**kwargs):raise TypeError('Persist original model, not an acquisition-only snapshot')
30
+ @classmethod
31
+ def load(cls,*args,**kwargs):raise TypeError('Load original model, then snapshot acquisition')
32
+
33
+
34
+ def acquisition_snapshot(engine):
35
+ return AcquisitionSnapshot(engine)
@@ -0,0 +1,21 @@
1
+ """Append-only acquisition with unchanged historical frame receipts."""
2
+ from .organization import RawOrganization
3
+ from .identity import encode,decode
4
+ from .frame_engine import canonical
5
+
6
+
7
+ class AcquisitionStream(RawOrganization):
8
+ def extend(self,source,frames):
9
+ """Accept a complete new prefix; identical retries are no-ops."""
10
+ if not isinstance(source,str) or not source.strip():raise ValueError('Source required')
11
+ encode(source)
12
+ if not isinstance(frames,(list,tuple)) or not frames:raise ValueError('Nonempty frames required')
13
+ raw=tuple(map(encode,frames))
14
+ if any(not f for f in raw):raise ValueError('Empty frame')
15
+ previous,receipts=self.episodes[source]
16
+ if len(raw)<len(previous) or raw[:len(previous)]!=previous:raise ValueError('Historical prefix changed')
17
+ if not self._alive(source):raise ValueError('Broken historical evidence')
18
+ if raw==previous:return
19
+ added=self.frames.ingest_batch((decode(raw[i]),canonical([source,i])) for i in range(len(previous),len(raw)))
20
+ self.episodes[source]=(raw,receipts+added)
21
+ self._dirty=True
@@ -0,0 +1,117 @@
1
+ """Source-bound measured-interval evidence; compatibility is not object identity."""
2
+ from heapq import heappop,heappush
3
+ from .organization_snapshot import snapshot
4
+ from .acquisition_snapshot import acquisition_snapshot
5
+ from .frame_engine import canonical
6
+ from .identity import encode,decode
7
+ from .incidence import _endpoint
8
+ from .role_work import RoleSearchBudget
9
+
10
+ _FIELDS={'source','frame','start','stop','clock','lower','upper'}
11
+
12
+ def _inputs(model,measurements,*,raw=False):
13
+ view=acquisition_snapshot(model) if raw else snapshot(model)
14
+ if not isinstance(measurements,list):raise ValueError('Measurements must be a list')
15
+ records=[];seen=set()
16
+ for r in measurements:
17
+ if not isinstance(r,dict) or set(r)!=_FIELDS:raise ValueError('Invalid measurement schema')
18
+ for key in ('source','clock'):
19
+ if not isinstance(r[key],str) or not r[key].strip():raise ValueError('Measurement authority required')
20
+ encode(r[key])
21
+ if any(type(r[k]) is not int for k in ('frame','start','stop','lower','upper')):raise ValueError('Integer bounds required')
22
+ if r['source'] not in view.episodes:raise ValueError('Unknown source')
23
+ frames=view.episodes[r['source']][0]
24
+ if not 0<=r['frame']<len(frames) or not 0<=r['start']<r['stop']<=len(frames[r['frame']]) or r['lower']>r['upper']:raise ValueError('Invalid measurement bounds')
25
+ key=(r['source'],r['frame'],r['start'],r['stop'])
26
+ if key in seen:raise ValueError('Duplicate occurrence measurement')
27
+ seen.add(key);records.append(dict(r))
28
+ sources=[]
29
+ for sid,(frames,_) in sorted(view.episodes.items()):
30
+ if not view._alive(sid):raise ValueError('Broken source')
31
+ sources.append({'source':sid,'frames':list(map(decode,frames))})
32
+ return view,sorted(records,key=canonical),sources
33
+
34
+ def _producer_interval_pairs(records):
35
+ """Closed interval sweep; all original cross-source partners survive."""
36
+ clocks={};pairs=[]
37
+ for i,r in enumerate(records):clocks.setdefault(r['clock'],[]).append(i)
38
+ for indices in clocks.values():
39
+ active={};ends=[]
40
+ for i in sorted(indices,key=lambda i:(records[i]['lower'],i)):
41
+ r=records[i];lo=r['lower']
42
+ while ends and ends[0][0]<lo:
43
+ _,j=heappop(ends);sid=records[j]['source'];del active[sid][j]
44
+ if not active[sid]:del active[sid]
45
+ for sid,bucket in active.items():
46
+ if sid==r['source']:continue
47
+ for j in bucket:
48
+ left,right=sorted((i,j));pairs.append({'left':left,'right':right,'intersection':[lo,min(r['upper'],records[j]['upper'])]})
49
+ active.setdefault(r['source'],{})[i]=None;heappush(ends,(r['upper'],i))
50
+ return sorted(pairs,key=lambda p:(p['left'],p['right']))
51
+
52
+
53
+ def _checker_interval_pairs(records):
54
+ """Independent endpoint-event reconstruction; starts precede equal ends."""
55
+ authorities={};edges=[]
56
+ for index,item in enumerate(records):
57
+ events=authorities.setdefault(item['clock'],[])
58
+ events.extend(((item['lower'],0,index),(item['upper'],1,index)))
59
+ for events in authorities.values():
60
+ live={}
61
+ for instant,kind,index in sorted(events):
62
+ item=records[index];source=item['source']
63
+ if kind:
64
+ live[source].remove(index)
65
+ if not live[source]:del live[source]
66
+ continue
67
+ for owner,others in live.items():
68
+ if owner==source:continue
69
+ for other in others:
70
+ a,b=(index,other) if index<other else (other,index)
71
+ edges.append({'left':a,'right':b,'intersection':[max(item['lower'],records[other]['lower']),min(item['upper'],records[other]['upper'])]})
72
+ live.setdefault(source,set()).add(index)
73
+ return sorted(edges,key=lambda e:(e['left'],e['right']))
74
+
75
+
76
+ def _certify_acquisition_witness(model,measurements,*,max_search_steps=None,raw=False):
77
+ budget=RoleSearchBudget(max_search_steps)
78
+ with budget.scope():
79
+ view,records,sources=_inputs(model,measurements,raw=raw);occurrences=[];pairs=[]
80
+ for r in records:
81
+ budget.consume();occurrences.append(_endpoint(view,r['source'],(r['frame'],r['start'],r['stop'])))
82
+ budget.consume_many(len(records)*(len(records)-1)//2)
83
+ pairs=_producer_interval_pairs(records)
84
+ return {'policy':'measured_interval_witness_v1','sources':sources,'measurements':records,'occurrences':occurrences,'pairs':pairs,'status':'COMPATIBLE_PAIRS' if pairs else 'NO_COMPATIBLE_PAIR'}
85
+
86
+ def _verify_acquisition_witness(model,measurements,certificate,*,max_search_steps=None,raw=False):
87
+ budget=RoleSearchBudget(max_search_steps)
88
+ with budget.scope():
89
+ try:
90
+ view,records,sources=_inputs(model,measurements,raw=raw)
91
+ if set(certificate)!={'policy','sources','measurements','occurrences','pairs','status'} or certificate['policy']!='measured_interval_witness_v1':return False
92
+ if canonical(certificate['sources'])!=canonical(sources) or canonical(certificate['measurements'])!=canonical(records):return False
93
+ endpoints=[];edges=[]
94
+ for i,r in enumerate(records):
95
+ budget.consume();frames,receipts=view.episodes[r['source']];fi=r['frame'];start=r['start'];stop=r['stop'];origin=receipts[fi].origin;offset=sum(map(len,frames[:fi]))
96
+ endpoints.append({'frame':fi,'start':start,'stop':stop,'event_span':[offset+start,offset+stop],'identities':list(frames[fi][start:stop]),'coordinates':[[origin[0]+p,*origin[1:]] for p in range(start,stop)]})
97
+ budget.consume_many(len(records)*(len(records)-1)//2)
98
+ edges=_checker_interval_pairs(records)
99
+ status='COMPATIBLE_PAIRS' if edges else 'NO_COMPATIBLE_PAIR'
100
+ return canonical(certificate['occurrences'])==canonical(endpoints) and canonical(certificate['pairs'])==canonical(edges) and certificate['status']==status
101
+ except (ValueError,TypeError,KeyError,IndexError,AttributeError):return False
102
+
103
+
104
+ def certify_acquisition_witness(model,measurements,*,max_search_steps=None):
105
+ return _certify_acquisition_witness(model,measurements,max_search_steps=max_search_steps)
106
+
107
+
108
+ def verify_acquisition_witness(model,measurements,certificate,*,max_search_steps=None):
109
+ return _verify_acquisition_witness(model,measurements,certificate,max_search_steps=max_search_steps)
110
+
111
+
112
+ def certify_raw_acquisition_witness(model,measurements,*,max_search_steps=None):
113
+ return _certify_acquisition_witness(model,measurements,max_search_steps=max_search_steps,raw=True)
114
+
115
+
116
+ def verify_raw_acquisition_witness(model,measurements,certificate,*,max_search_steps=None):
117
+ return _verify_acquisition_witness(model,measurements,certificate,max_search_steps=max_search_steps,raw=True)
@@ -0,0 +1,117 @@
1
+ """Complete shortest supported joint-state paths and expanded NMU lineage."""
2
+ from copy import deepcopy
3
+ from .identity import encode
4
+ from .acquisition_snapshot import acquisition_snapshot
5
+ from .frame_engine import canonical
6
+ from .observed_actuation_discovery import certify_observed_actuation_discovery
7
+ from .joint_frontier_acquisition import _requests
8
+ from .measured_context_laws import certify_measured_context_laws
9
+ from .role_work import RoleSearchBudget
10
+
11
+
12
+ def _seed_routes(state,budget):
13
+ result={}
14
+ for point in state['points']:
15
+ p=point['port'];occ=point['occurrence'];route=[]
16
+ for i,coord in enumerate(occ['coordinates']):
17
+ budget.consume();route.append({'kind':'observed','domain':'observed','port':p,'source':point['source'],'frame':occ['frame'],'position':i,'coordinate':deepcopy(coord)})
18
+ result[p]=[route]
19
+ return result
20
+
21
+
22
+ def _next_routes(previous,law,step,action,budget):
23
+ routes={};port=law['root_port']
24
+ for candidate in law['candidates']:
25
+ for proof in candidate['structural_response']['proofs']:
26
+ if proof['output']!=law['result']['output']:continue
27
+ for prior in previous:
28
+ route=[]
29
+ for point in proof['characters'][0]:
30
+ budget.consume()
31
+ if point['kind']=='trigger':
32
+ if point['frame']==0:route.append(deepcopy(prior[point['position']]))
33
+ else:route.append({'kind':'action','domain':'query_action','step':step,'action':action,'position':point['position']})
34
+ else:route.append({**deepcopy(point),'domain':'learned','port':port})
35
+ routes[canonical(route)]=route
36
+ for witness in candidate['crystal_paths']:
37
+ route=[]
38
+ for i,coord in enumerate(witness['occurrence']['coordinates']):
39
+ budget.consume();route.append({'kind':'crystal','domain':'learned','port':port,'source':witness['source'],'frame':2,'position':i,'coordinate':deepcopy(coord)})
40
+ routes[canonical(route)]=route
41
+ if not routes:raise ValueError('Resolved law lacks a complete character route')
42
+ return [routes[key] for key in sorted(routes)]
43
+
44
+
45
+ def certify_actuation_goal_frontier(model,groups,measurements,observation,observed_groups,observed_measurements,anchor_group,catalogue,catalogue_measurements,goal,*,max_depth=None,max_search_steps=None):
46
+ budget=RoleSearchBudget(max_search_steps)
47
+ with budget.scope():
48
+ budget.consume()
49
+ if max_depth is not None and (type(max_depth) is not int or max_depth<0):raise ValueError('Depth is None or a nonnegative integer')
50
+ model,observation=acquisition_snapshot(model),acquisition_snapshot(observation)
51
+ groups,measurements,observed_groups,observed_measurements=deepcopy((groups,measurements,observed_groups,observed_measurements))
52
+ discovery=certify_observed_actuation_discovery(model,groups,measurements,observation,observed_groups,observed_measurements,anchor_group,catalogue,catalogue_measurements);state=discovery['state_certificate'];goal=deepcopy(goal)
53
+ if not isinstance(goal,dict) or not goal or not set(goal)<=set(state['ports']):raise ValueError('Nonempty original-interface goal required')
54
+ for value in goal.values():
55
+ if not isinstance(value,str) or not value:raise ValueError('Nonempty raw goal frames required')
56
+ encode(value)
57
+ ready=state['result']['status']=='JOINT_STATE_READY';nodes=[{'state':deepcopy(state['state']),'depth':0,'kind':'OBSERVED_SCOPE_VALUES'}];known={canonical(state['state']):0};edges=[];predecessors={0:[]};frontier=[0] if ready and discovery['result']['catalogue_current'] else [];depth=0;blocked=[];goals=[0] if ready and all(state['state'][p]==v for p,v in goal.items()) else [];found=0 if goals else None
58
+ while frontier and found is None and (max_depth is None or depth<max_depth):
59
+ upcoming=[]
60
+ for source in frontier:
61
+ before=nodes[source]['state']
62
+ for action in discovery['available_actions']:
63
+ budget.consume();laws=[];after={};supported=True
64
+ for port in state['ports']:
65
+ budget.consume();context={p:before[p] for p in state['ports'] if p!=port};law=certify_measured_context_laws(model,groups,measurements,port,before[port],action,context);laws.append({'port':port,'certificate':law})
66
+ if law['result']['status']=='MEASURED_CONTEXT_LAW_RESOLVED':after[port]=law['result']['output'][0]
67
+ else:supported=False
68
+ successor=None;index=len(edges)
69
+ if supported:
70
+ key=canonical(after)
71
+ if key not in known:
72
+ successor=len(nodes);known[key]=successor;nodes.append({'state':after,'depth':depth+1,'kind':'PROJECTED'});predecessors[successor]=[];upcoming.append(successor)
73
+ else:successor=known[key]
74
+ if nodes[successor]['depth']==depth+1:predecessors[successor].append(index)
75
+ if all(after[p]==v for p,v in goal.items()):
76
+ found=depth+1 if found is None else found
77
+ if successor not in goals:goals.append(successor)
78
+ else:blocked.append(index)
79
+ edges.append({'source':source,'action':action,'laws':laws,'successor':successor,'supported':bool(supported)})
80
+ frontier=upcoming;depth+=1
81
+ if blocked:break
82
+ solutions=[]
83
+ for target in sorted(goals):
84
+ pending=[(target,[])]
85
+ while pending:
86
+ budget.consume();node,reverse=pending.pop()
87
+ if node:
88
+ for edge in reversed(predecessors[node]):pending.append((edges[edge]['source'],reverse+[edge]))
89
+ continue
90
+ path=list(reversed(reverse));owners=_seed_routes(state,budget);actions=[]
91
+ for step,edge_index in enumerate(path):
92
+ budget.consume();edge=edges[edge_index];actions.append(edge['action']);next_owners={}
93
+ for item in edge['laws']:next_owners[item['port']]=_next_routes(owners[item['port']],item['certificate'],step,edge['action'],budget)
94
+ owners=next_owners
95
+ solutions.append({'goal_node':target,'edges':path,'actions':actions,'lineage_routes':owners})
96
+ solutions.sort(key=lambda s:(s['actions'],s['edges']))
97
+ graph={'state_certificate':state,'nodes':nodes,'edges':edges,'result':{'blocked_edges':blocked}}
98
+ requests=_requests(graph,budget);choices=[]
99
+ for solution in solutions:choices.append({'kind':'SUPPORTED_GOAL','target':solution['goal_node'],**deepcopy(solution)})
100
+ for request in requests:
101
+ for prefix in request['prefixes']:choices.append({'kind':'FRONTIER_EXPERIENCE','target':request['edge'],'edges':prefix['edges']+[request['edge']],'actions':prefix['actions']+[request['action']],'lineage_routes':deepcopy(prefix['lineage_routes'])})
102
+ for target in frontier:
103
+ if target in goals:continue
104
+ paths=[(target,[])]
105
+ while paths:
106
+ budget.consume();node,reverse=paths.pop()
107
+ if node:
108
+ for edge_index in reversed(predecessors[node]):paths.append((edges[edge_index]['source'],reverse+[edge_index]))
109
+ continue
110
+ path=list(reversed(reverse));owners=_seed_routes(state,budget);actions=[]
111
+ for step,j in enumerate(path):
112
+ budget.consume();edge=edges[j];actions.append(edge['action']);owners={item['port']:_next_routes(owners[item['port']],item['certificate'],step,edge['action'],budget) for item in edge['laws']}
113
+ choices.append({'kind':'SUPPORTED_PREFIX','target':target,'edges':path,'actions':actions,'lineage_routes':owners})
114
+ choices.sort(key=lambda x:(x['kind'],x['target'],x['actions'],x['edges']))
115
+ status='GOAL_ALREADY_OBSERVED' if found==0 else 'OBSERVED_STATE_UNRESOLVED' if not ready else 'CATALOGUE_NOT_CURRENT' if not discovery['result']['catalogue_current'] else 'SUPPORTED_GOAL_READY' if found is not None else 'FRONTIER_EXPERIENCE_READY' if blocked else 'SUPPORTED_FRONTIER_CLOSED' if not frontier else 'DECLARED_DEPTH_REACHED'
116
+ result={'status':status,'shortest_supported_goal_length':found,'goal_nodes':sorted(goals),'blocked_edges':blocked,'frontier':frontier,'depth_reached':depth,'supported_frontier_exhausted':not bool(frontier),'choice_count':len(choices),'request_count':len(requests),'minimum_acquisition_distance':min((r['acquisition_distance'] for r in requests),default=None),'catalogue_current':discovery['result']['catalogue_current']}
117
+ return {'policy':'actuation_goal_frontier_v1','goal':goal,'max_depth':max_depth,'discovery':discovery,'state_certificate':state,'nodes':nodes,'edges':edges,'solutions':solutions,'requests':requests,'choices':choices,'result':result}
@@ -0,0 +1,147 @@
1
+ """Independent graph coverage, goal paths and correlated character-route check."""
2
+ from copy import deepcopy
3
+ from .identity import encode
4
+ from .acquisition_snapshot import acquisition_snapshot
5
+ from .frame_engine import canonical
6
+ from .observed_actuation_discovery_check import verify_observed_actuation_discovery
7
+ from .measured_context_laws_check import verify_measured_context_laws
8
+ from .role_work import RoleSearchBudget
9
+
10
+
11
+ def _initial_owners(state,budget):
12
+ owners={}
13
+ for point in state['points']:
14
+ route=[];occ=point['occurrence']
15
+ for i,coordinate in enumerate(occ['coordinates']):
16
+ budget.consume();route.append({'kind':'observed','domain':'observed','port':point['port'],'source':point['source'],'frame':occ['frame'],'position':i,'coordinate':deepcopy(coordinate)})
17
+ owners[point['port']]=[route]
18
+ return owners
19
+
20
+
21
+ def _expanded_owners(priors,law,step,action,budget):
22
+ distinct={};port=law['root_port']
23
+ for family in law['candidates']:
24
+ for proof in family['structural_response']['proofs']:
25
+ if proof['output']!=law['result']['output']:continue
26
+ for prior in priors:
27
+ current=[]
28
+ for point in proof['characters'][0]:
29
+ budget.consume()
30
+ if point['kind']=='crystal':current.append({**deepcopy(point),'domain':'learned','port':port})
31
+ elif point['frame']==0:current.append(deepcopy(prior[point['position']]))
32
+ elif point['frame']==1:current.append({'kind':'action','domain':'query_action','step':step,'action':action,'position':point['position']})
33
+ else:raise ValueError('Invalid original trigger frame')
34
+ distinct[canonical(current)]=current
35
+ for crystal in family['crystal_paths']:
36
+ current=[]
37
+ for position,coordinate in enumerate(crystal['occurrence']['coordinates']):
38
+ budget.consume();current.append({'kind':'crystal','domain':'learned','port':port,'source':crystal['source'],'frame':2,'position':position,'coordinate':deepcopy(coordinate)})
39
+ distinct[canonical(current)]=current
40
+ if not distinct:raise ValueError('Missing lineage route')
41
+ return [distinct[k] for k in sorted(distinct)]
42
+
43
+
44
+ def verify_actuation_goal_frontier(model,groups,measurements,observation,observed_groups,observed_measurements,anchor_group,catalogue,catalogue_measurements,goal,certificate,*,max_depth=None,max_search_steps=None):
45
+ budget=RoleSearchBudget(max_search_steps)
46
+ with budget.scope():
47
+ budget.consume()
48
+ try:
49
+ c=deepcopy(certificate)
50
+ if set(c)!={'policy','goal','max_depth','discovery','state_certificate','nodes','edges','solutions','requests','choices','result'} or c['policy']!='actuation_goal_frontier_v1':return False
51
+ if max_depth is not None and (type(max_depth) is not int or max_depth<0):return False
52
+ if canonical(c['goal'])!=canonical(goal) or type(c['max_depth']) is not type(max_depth) or c['max_depth']!=max_depth:return False
53
+ if any(type(c[key]) is not list for key in ('nodes','edges','solutions')):return False
54
+ model,observation=acquisition_snapshot(model),acquisition_snapshot(observation)
55
+ groups,measurements,observed_groups,observed_measurements=deepcopy((groups,measurements,observed_groups,observed_measurements))
56
+ state=c['state_certificate']
57
+ discovery=c['discovery']
58
+ if not verify_observed_actuation_discovery(model,groups,measurements,observation,observed_groups,observed_measurements,anchor_group,catalogue,catalogue_measurements,discovery) or canonical(state)!=canonical(discovery['state_certificate']):return False
59
+ if not isinstance(goal,dict) or not goal or not set(goal)<=set(state['ports']):return False
60
+ for value in goal.values():
61
+ if not isinstance(value,str) or not value:return False
62
+ encode(value)
63
+ ready=state['result']['status']=='JOINT_STATE_READY';expected_nodes=[{'state':deepcopy(state['state']),'depth':0,'kind':'OBSERVED_SCOPE_VALUES'}];registered={canonical(state['state']):0};parents={0:[]};layer=[0] if ready and discovery['result']['catalogue_current'] else [];level=0;cursor=0;blocked=[];goals=[0] if ready and all(state['state'][p]==v for p,v in goal.items()) else [];found=0 if goals else None
64
+ while layer and found is None and (max_depth is None or level<max_depth):
65
+ following=[]
66
+ for source in layer:
67
+ before=expected_nodes[source]['state']
68
+ for action in discovery['available_actions']:
69
+ budget.consume()
70
+ if cursor>=len(c['edges']):return False
71
+ edge=c['edges'][cursor]
72
+ if set(edge)!={'source','action','laws','successor','supported'} or type(edge['source']) is not int or edge['source']!=source or edge['action']!=action or len(edge['laws'])!=len(state['ports']):return False
73
+ after={};supported=True
74
+ for port,item in zip(state['ports'],edge['laws']):
75
+ budget.consume()
76
+ if set(item)!={'port','certificate'} or item['port']!=port:return False
77
+ context={p:before[p] for p in state['ports'] if p!=port};law=item['certificate']
78
+ if not verify_measured_context_laws(model,groups,measurements,port,before[port],action,context,law):return False
79
+ if law['result']['status']=='MEASURED_CONTEXT_LAW_RESOLVED':after[port]=law['result']['output'][0]
80
+ else:supported=False
81
+ successor=None
82
+ if supported:
83
+ key=canonical(after)
84
+ if key in registered:successor=registered[key]
85
+ else:
86
+ successor=len(expected_nodes);registered[key]=successor;expected_nodes.append({'state':after,'depth':level+1,'kind':'PROJECTED'});parents[successor]=[];following.append(successor)
87
+ if expected_nodes[successor]['depth']==level+1:parents[successor].append(cursor)
88
+ if all(after[p]==v for p,v in goal.items()):
89
+ found=level+1 if found is None else found
90
+ if successor not in goals:goals.append(successor)
91
+ else:blocked.append(cursor)
92
+ if type(edge['supported']) is not bool or edge['supported']!=supported or (successor is not None and type(edge['successor']) is not int) or edge['successor']!=successor:return False
93
+ cursor+=1
94
+ layer=following;level+=1
95
+ if blocked:break
96
+ if len(c['edges'])!=cursor or canonical(c['nodes'])!=canonical(expected_nodes):return False
97
+ expected_solutions=[]
98
+ for target in sorted(goals):
99
+ stack=[(target,[])]
100
+ while stack:
101
+ budget.consume();node,reverse=stack.pop()
102
+ if node!=0:
103
+ for edge_index in reversed(parents[node]):stack.append((c['edges'][edge_index]['source'],reverse+[edge_index]))
104
+ continue
105
+ path=list(reversed(reverse));owners=_initial_owners(state,budget);actions=[]
106
+ for step,edge_index in enumerate(path):
107
+ budget.consume();edge=c['edges'][edge_index];actions.append(edge['action']);updated={}
108
+ for item in edge['laws']:updated[item['port']]=_expanded_owners(owners[item['port']],item['certificate'],step,edge['action'],budget)
109
+ owners=updated
110
+ expected_solutions.append({'goal_node':target,'edges':path,'actions':actions,'lineage_routes':owners})
111
+ expected_solutions.sort(key=lambda s:(s['actions'],s['edges']))
112
+ if canonical(c['solutions'])!=canonical(expected_solutions):return False
113
+ requests=[]
114
+ for index in blocked:
115
+ edge=c['edges'][index];paths=[];stack=[(edge['source'],[])]
116
+ while stack:
117
+ budget.consume();node,reverse=stack.pop()
118
+ if node:
119
+ for parent in reversed(parents[node]):stack.append((c['edges'][parent]['source'],reverse+[parent]))
120
+ continue
121
+ path=list(reversed(reverse));owners=_initial_owners(state,budget);actions=[]
122
+ for step,j in enumerate(path):
123
+ budget.consume();e=c['edges'][j];actions.append(e['action']);owners={item['port']:_expanded_owners(owners[item['port']],item['certificate'],step,e['action'],budget) for item in e['laws']}
124
+ paths.append({'edges':path,'actions':actions,'lineage_routes':owners})
125
+ paths.sort(key=lambda p:(p['actions'],p['edges']));requests.append({'edge':index,'source':edge['source'],'action':edge['action'],'before':deepcopy(expected_nodes[edge['source']]['state']),'acquisition_distance':expected_nodes[edge['source']]['depth']+1,'unresolved_ports':[item['port'] for item in edge['laws'] if item['certificate']['result']['status']!='MEASURED_CONTEXT_LAW_RESOLVED'],'prefixes':paths})
126
+ choices=[]
127
+ for solution in expected_solutions:choices.append({'kind':'SUPPORTED_GOAL','target':solution['goal_node'],**deepcopy(solution)})
128
+ for request in requests:
129
+ for prefix in request['prefixes']:choices.append({'kind':'FRONTIER_EXPERIENCE','target':request['edge'],'edges':prefix['edges']+[request['edge']],'actions':prefix['actions']+[request['action']],'lineage_routes':deepcopy(prefix['lineage_routes'])})
130
+ for target in layer:
131
+ if target in goals:continue
132
+ pending=[(target,[])]
133
+ while pending:
134
+ budget.consume();node,reverse=pending.pop()
135
+ if node:
136
+ for parent in reversed(parents[node]):pending.append((c['edges'][parent]['source'],reverse+[parent]))
137
+ continue
138
+ path=list(reversed(reverse));owners=_initial_owners(state,budget);actions=[]
139
+ for step,j in enumerate(path):
140
+ budget.consume();edge=c['edges'][j];actions.append(edge['action']);owners={item['port']:_expanded_owners(owners[item['port']],item['certificate'],step,edge['action'],budget) for item in edge['laws']}
141
+ choices.append({'kind':'SUPPORTED_PREFIX','target':target,'edges':path,'actions':actions,'lineage_routes':owners})
142
+ choices.sort(key=lambda x:(x['kind'],x['target'],x['actions'],x['edges']))
143
+ if canonical(c['requests'])!=canonical(requests) or canonical(c['choices'])!=canonical(choices):return False
144
+ status='GOAL_ALREADY_OBSERVED' if found==0 else 'OBSERVED_STATE_UNRESOLVED' if not ready else 'CATALOGUE_NOT_CURRENT' if not discovery['result']['catalogue_current'] else 'SUPPORTED_GOAL_READY' if found is not None else 'FRONTIER_EXPERIENCE_READY' if blocked else 'SUPPORTED_FRONTIER_CLOSED' if not layer else 'DECLARED_DEPTH_REACHED'
145
+ result={'status':status,'shortest_supported_goal_length':found,'goal_nodes':sorted(goals),'blocked_edges':blocked,'frontier':layer,'depth_reached':level,'supported_frontier_exhausted':not bool(layer),'choice_count':len(choices),'request_count':len(requests),'minimum_acquisition_distance':min((r['acquisition_distance'] for r in requests),default=None),'catalogue_current':discovery['result']['catalogue_current']}
146
+ return canonical(c['result'])==canonical(result)
147
+ except (ValueError,TypeError,KeyError,IndexError,AttributeError):return False