morphtree 2.1.0__py3-none-win_amd64.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 (79) hide show
  1. morphtree/__init__.py +28 -0
  2. morphtree/__main__.py +3 -0
  3. morphtree/_experimental/__init__.py +1 -0
  4. morphtree/_experimental/admission.py +364 -0
  5. morphtree/_experimental/base.py +215 -0
  6. morphtree/_experimental/component_cache_v2.py +263 -0
  7. morphtree/_experimental/evolution_report.py +307 -0
  8. morphtree/_experimental/execution_v2.py +697 -0
  9. morphtree/_experimental/facade.py +289 -0
  10. morphtree/_experimental/integrated.py +748 -0
  11. morphtree/_experimental/learning.py +418 -0
  12. morphtree/_experimental/manifest.json +204 -0
  13. morphtree/_experimental/numeric_fixture.py +21 -0
  14. morphtree/_experimental/parameter_contract.py +38 -0
  15. morphtree/_experimental/postfit.py +51 -0
  16. morphtree/_experimental/preprocessing.py +133 -0
  17. morphtree/_experimental/processes.py +191 -0
  18. morphtree/_experimental/producer.py +542 -0
  19. morphtree/_experimental/product.py +156 -0
  20. morphtree/_experimental/product_cli.py +43 -0
  21. morphtree/_experimental/roundtrip_v3.py +311 -0
  22. morphtree/_experimental/runtime_io.py +65 -0
  23. morphtree/_experimental/sampling.py +26 -0
  24. morphtree/_experimental/support.py +281 -0
  25. morphtree/_experimental/target.py +59 -0
  26. morphtree/_experimental/training.py +53 -0
  27. morphtree/_experimental/worker.py +682 -0
  28. morphtree/_installed.py +17 -0
  29. morphtree/_native/__init__.py +1 -0
  30. morphtree/_native/bin/win_amd64/morphtree_kernels.dll +0 -0
  31. morphtree/_native/buffers.py +82 -0
  32. morphtree/_native/loader.py +39 -0
  33. morphtree/_native/manifest.json +29 -0
  34. morphtree/_native/runtime.py +48 -0
  35. morphtree/_native/src/histogram.c +61 -0
  36. morphtree/_native/src/traversal.c +51 -0
  37. morphtree/api.py +388 -0
  38. morphtree/api_compat.py +65 -0
  39. morphtree/backend.py +162 -0
  40. morphtree/booster.py +252 -0
  41. morphtree/cli.py +52 -0
  42. morphtree/config.py +262 -0
  43. morphtree/control.py +20 -0
  44. morphtree/data.py +300 -0
  45. morphtree/diagnostics.py +158 -0
  46. morphtree/estimators.py +156 -0
  47. morphtree/examples.py +25 -0
  48. morphtree/exporting.py +224 -0
  49. morphtree/legacy_artifacts.py +32 -0
  50. morphtree/metrics.py +156 -0
  51. morphtree/model.py +1010 -0
  52. morphtree/mutations.py +205 -0
  53. morphtree/native_lab_backend.py +79 -0
  54. morphtree/numpy_backend.py +180 -0
  55. morphtree/optuna_tuner.py +154 -0
  56. morphtree/persistence.py +414 -0
  57. morphtree/prediction_output.py +35 -0
  58. morphtree/prepared_bins.py +82 -0
  59. morphtree/public.py +106 -0
  60. morphtree/resource_plan.py +170 -0
  61. morphtree/scalable.py +781 -0
  62. morphtree/scalable_backend.py +74 -0
  63. morphtree/scalable_checkpoint.py +129 -0
  64. morphtree/scalable_data.py +255 -0
  65. morphtree/scalable_receipts.py +92 -0
  66. morphtree/scalable_target.py +68 -0
  67. morphtree/scalable_variants.py +133 -0
  68. morphtree/sklearn_view.py +79 -0
  69. morphtree/source_markers.py +25 -0
  70. morphtree/species.py +47 -0
  71. morphtree/temporary.py +65 -0
  72. morphtree/training_fragment.py +130 -0
  73. morphtree/tree.py +231 -0
  74. morphtree/tuning.py +150 -0
  75. morphtree-2.1.0.dist-info/METADATA +212 -0
  76. morphtree-2.1.0.dist-info/RECORD +79 -0
  77. morphtree-2.1.0.dist-info/WHEEL +4 -0
  78. morphtree-2.1.0.dist-info/entry_points.txt +2 -0
  79. morphtree-2.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,748 @@
1
+ """Installed COMP002 hooks for the existing LearningControl, not a new learner.
2
+
3
+ Copied into the private wheel with relative imports. No import of this file as
4
+ workspace runtime and no implicit authority from the public fit API.
5
+ """
6
+ import copy
7
+ from dataclasses import asdict
8
+ from morphtree.config import AlgorithmGenome
9
+ from morphtree.mutations import propose_mutations
10
+ from .admission import AdmissionError, digest
11
+ from .product import MorphTree as Consumer
12
+ from .learning import LearningControl, mutation_admission
13
+ from .support import FamilyChoice, TaskFinalizer
14
+ from .execution_v2 import ACTIVE, require_session, SearchBudgetExhausted
15
+
16
+
17
+ def learning_program(packet):
18
+ """Bounded native procedure, separate from numbers, weights and lineage.
19
+
20
+ The instructions are derived from the existing executable genome, never
21
+ arbitrary Python. This is the current native grammar, not a new general
22
+ programming language or evidence that every primitive is scientifically useful.
23
+ """
24
+ task, family = packet['task'], packet['family']
25
+ if task not in ('binary', 'multiclass', 'regression') or family not in ('boost', 'bag'):
26
+ raise ValueError('Existing native task/family required')
27
+ genome = AlgorithmGenome(**packet['recipe']['genome'])
28
+ if task != 'binary' and genome != AlgorithmGenome():
29
+ # Only the separately versioned native capability may admit this.
30
+ # Consolidated/older runtimes keep rejecting nonbinary transformations.
31
+ from morphtree import config as native_config
32
+ validate=getattr(native_config,'validate_task_genome',None)
33
+ if not callable(validate):
34
+ raise ValueError('Nonbinary structural dispatch is not qualified')
35
+ validate(task,genome)
36
+ body={'schema':'comp008-native-learning-program-v2', 'version':2, 'task':task,
37
+ 'family':family, 'genome':genome.to_dict(),
38
+ 'instructions':[
39
+ {'op':'preprocess', 'implementation':'native.TRAIN_only_encoder'},
40
+ {'op':'learning', 'implementation':'native.sequential_derivatives' if family=='boost'
41
+ else 'native.bootstrap_independent_one_stage'},
42
+ {'op':'tree_growth', 'implementation':genome.growth_policy},
43
+ {'op':'split_score', 'stack':list(genome.split_program)},
44
+ {'op':'leaf_update', 'implementation':genome.leaf_policy},
45
+ {'op':'prediction', 'implementation':'native.stage_sum' if family=='boost' else 'native.member_mean'}],
46
+ 'execution':'EXISTING_NATIVE_CONSTRUCTORS', 'code_evaluation':'NONE',
47
+ 'grammar':'EXISTING_ALGORITHM_GENOME_NATIVE_PRIMITIVES',
48
+ 'sampling':'native.configured_row_sampling' if family=='boost' else 'native.bootstrap',
49
+ 'state_update':'native.sequential_boosting' if family=='boost' else 'native.independent_member_append',
50
+ 'termination':'FIXED_NATIVE_LEARNING_BUDGET_AND_COOPERATIVE_CANCEL'}
51
+ return dict(body,program_id='mt-program:'+digest(body))
52
+
53
+
54
+ def program_dispatch(program):
55
+ """Validate all instructions against their actual native dispatch."""
56
+ packet={'task':program['task'], 'family':program['family'],
57
+ 'recipe':{'genome':program['genome']}}
58
+ if program != learning_program(packet):
59
+ raise ValueError('Program instructions do not describe the native implementation')
60
+ return program['family'], AlgorithmGenome(**program['genome'])
61
+
62
+
63
+ def transformed_program(parent, proposal):
64
+ family, genome = program_dispatch(parent)
65
+ changed=[k for k,v in genome.to_dict().items() if proposal.genome.to_dict()[k]!=v]
66
+ if changed != [proposal.gene]:
67
+ raise ValueError('One actual typed native gene must change, not a numeric alias')
68
+ return learning_program({'task':parent['task'],'family':family,
69
+ 'recipe':{'genome':proposal.genome.to_dict()}})
70
+
71
+
72
+ def evolution_context(context, selected, program, *, authenticate):
73
+ """Validate information timing; authentication stays with the owned producer.
74
+
75
+ An OOF label, hash or fold declaration alone cannot authenticate a producer.
76
+ Current installed sessions have no such producer and therefore abstain. A
77
+ later LIVE binding needs its own actual fold-artifact qualification.
78
+ """
79
+ required={'role','parent_packet_sha256','program_sha256','learning_identity',
80
+ 'profile','allowed_programs','evidence'}
81
+ if type(context) is not dict or set(context)!=required:
82
+ raise ValueError('Exact internal diagnostic context required')
83
+ if (context['role']!='TRAIN_OOF' or context['parent_packet_sha256']!=digest(selected)
84
+ or context['program_sha256']!=digest(program)
85
+ or context['learning_identity']!=selected['learning_identity']):
86
+ raise ValueError('Only current fixed-parent TRAIN OOF may guide a transformation')
87
+ if not callable(authenticate) or authenticate(copy.deepcopy(context),copy.deepcopy(selected)) is not True:
88
+ raise ValueError('Actual OOF producer/artifacts have not been authenticated')
89
+ rows=context['profile'].get('diagnoses')
90
+ if type(rows) is not list or len(rows)>32 or len({r['name'] for r in rows})!=len(rows):
91
+ raise ValueError('Bounded distinct diagnostic hypotheses required')
92
+ for r in rows:
93
+ if not isinstance(r['name'],str) or any(type(r.get(k)) not in (int,float) or not 0<=r[k]<=1 for k in ('strength','confidence')):
94
+ raise ValueError('Finite bounded diagnostic strengths/confidences')
95
+ allowed=context['allowed_programs']
96
+ if type(allowed) is not list or len(allowed)>64 or len(set(allowed))!=len(allowed):
97
+ raise ValueError('Explicit bounded admitted program identities required')
98
+ return context
99
+
100
+
101
+ class StructuralChoice(FamilyChoice):
102
+ """Same coordinator checks/strict loss ordering, one typed growth proposal.
103
+
104
+ FamilyChoice's family-change precondition is deliberately replaced only
105
+ for this versioned structural case. Verification and anchor semantics stay
106
+ those of the original coordinator.
107
+ """
108
+ def offer_growth(self, candidate):
109
+ if self.failed or self.done:raise RuntimeError('Terminal structural decision; no replay')
110
+ before = copy.deepcopy(self.best)
111
+ old = before['packet']; new = candidate
112
+ if new['task'] != 'binary' or old['task'] != 'binary':
113
+ raise ValueError('Existing binary growth operator only')
114
+ if new['recipe']['genome'] != AlgorithmGenome(growth_policy='depthwise').to_dict():
115
+ raise ValueError('Exact existing depthwise rule required')
116
+ try:
117
+ checked = self._checked(candidate)
118
+ if checked['loss'] < before['loss']:
119
+ self.best = checked
120
+ # Recheck retained predictions, including a candidate that lost.
121
+ again = self._checked(self.best['packet'])
122
+ if again != self.best: raise ValueError('Retained anchor changed')
123
+ self.checkpoint({'phase': 'STRUCTURAL', 'status': 'COMPLETED',
124
+ 'retained': self.best['packet']['id'], 'candidate': new['id'],
125
+ 'decision': 'ACCEPT' if self.best['packet']['id']==new['id'] else 'ROLLBACK'})
126
+ self.done=True
127
+ return self.best
128
+ except BaseException:
129
+ self.best = before
130
+ self.failed=True
131
+ raise
132
+
133
+ def offer_transform(self, candidate, program):
134
+ """Reuse original verified anchor/loss semantics for a typed child.
135
+
136
+ A new instance is used for each step, anchored to the current retained
137
+ weights. Strict ties retain the parent. No in-place update is claimed.
138
+ """
139
+ if self.failed or self.done:raise RuntimeError('Terminal structural decision')
140
+ before=copy.deepcopy(self.best)
141
+ try:
142
+ if (candidate['family']!=self.anchor['family']
143
+ or candidate['params']!=self.anchor['params']
144
+ or candidate['recipe']['classes']!=self.anchor['recipe']['classes']
145
+ or candidate['recipe']['encoder']!=self.anchor['recipe']['encoder']
146
+ or learning_program(candidate)!=program
147
+ or learning_program(self.anchor)==program):
148
+ raise ValueError('Child must execute the proposed program with frozen numbers/data')
149
+ checked=self._checked(candidate)
150
+ if checked['loss']<before['loss']:self.best=checked
151
+ if self._checked(self.best['packet'])!=self.best:
152
+ raise ValueError('Retained parent/child predictions changed')
153
+ self.checkpoint({'phase':'EVOLUTION','status':'COMPLETED',
154
+ 'parent':self.anchor['id'],'candidate':candidate['id'],
155
+ 'retained':self.best['packet']['id'],
156
+ 'decision':'ACCEPT' if self.best['packet']['id']==candidate['id'] else 'ROLLBACK'})
157
+ self.done=True
158
+ return self.best
159
+ except BaseException:
160
+ self.best=before;self.failed=True
161
+ raise
162
+
163
+
164
+ class MorphTree(Consumer):
165
+ """Original orchestration reached through the installed canonical API.
166
+
167
+ An exact current session is mandatory. A software session only supplies
168
+ explicitly constructed/retained weights; PREFIT stops before native work.
169
+ """
170
+ _numeric_plan = LearningControl._numeric_plan
171
+ _log = LearningControl._log
172
+
173
+ def __init__(self, *, task='auto', families='boost', morphing='none', tuning='none', **kwargs):
174
+ super().__init__(task=task, families=families, morphing=morphing, tuning=tuning, **kwargs)
175
+ self._research_growth = False
176
+ self._evolving_program = False # New public source opts in; old installed v6 is preserved.
177
+ self._max_mutations = 2
178
+
179
+ @classmethod
180
+ def baseline(cls, *, family='boost', **kwargs):
181
+ if family not in ('boost', 'bag') or set(kwargs) & {'families', 'morphing'}:
182
+ raise ValueError('Baseline requires one native family and no structural search')
183
+ return cls(families=family, morphing='none', **kwargs)
184
+
185
+ @classmethod
186
+ def adaptive(cls, **kwargs):
187
+ if set(kwargs) & {'families', 'morphing'}:
188
+ raise ValueError('Adaptive uses common native family exploration and diagnostic abstention')
189
+ return cls(families='auto', morphing='auto', **kwargs)
190
+
191
+ @classmethod
192
+ def research(cls, *, operators, **kwargs):
193
+ if tuple(operators) != ('growth_policy:depthwise',):
194
+ raise ValueError('Explicit qualified research operator required')
195
+ obj = cls.adaptive(**kwargs)
196
+ obj._research_growth = True
197
+ return obj
198
+
199
+ @property
200
+ def mode(self):
201
+ if self._research_growth:
202
+ return 'research'
203
+ return 'adaptive' if self.families == 'auto' or self.morphing == 'auto' else 'baseline'
204
+
205
+ def _make_executor(self):
206
+ return require_session().executor(self)
207
+
208
+ def _execution_check(self):
209
+ require_session() # require_session already checks the same Session.
210
+
211
+ def _search_budget_open(self):
212
+ s=ACTIVE.get()
213
+ return s is None or s.mode!='PUBLIC_USER' or not s._search_closed
214
+
215
+ def _close_search_budget(self,reason):
216
+ s=ACTIVE.get()
217
+ if s is None or s.mode!='PUBLIC_USER':raise PermissionError('No ordinary search scope')
218
+ s.finish_search(reason)
219
+
220
+ def _finish_search_if_public(self,reason):
221
+ s=ACTIVE.get()
222
+ if s is not None and s.mode=='PUBLIC_USER':s.finish_search(reason)
223
+
224
+ def _begin_numeric_window(self):
225
+ s=ACTIVE.get()
226
+ if s is not None and s.mode=='PUBLIC_USER':
227
+ if s._search_deadline is None:s.begin_search()
228
+ else:s.check() # No renewal after family/structural work.
229
+
230
+ def _admit_learning_batch(self,task,family,params,kind):
231
+ s=require_session()
232
+ if s.mode=='PUBLIC_USER':s.admit_batch(task,family,asdict(params),kind=kind)
233
+
234
+ def _budget_stopped(self,stage,anchor,attempt,log,error):
235
+ self._close_search_budget('SEARCH_BUDGET_'+stage)
236
+ attempt['search_budget_stop']={'stage':stage,'retained':anchor['id'],
237
+ 'reason':str(error),'tuning_complete':False}
238
+ log('search_budget_stopped',**copy.deepcopy(attempt['search_budget_stop']))
239
+
240
+ def _record_event(self, event):
241
+ require_session().event('ORCHESTRATION', value=event)
242
+
243
+ def _capture_report_packet(self, packet, model, selection, train):
244
+ """Retain actual executed objects for post-fit verification, not authority."""
245
+ self._report_evidence[packet['id']] = (copy.deepcopy(packet), model,
246
+ copy.deepcopy(selection), copy.deepcopy(train))
247
+
248
+ def _verify_evolution_report(self, *, finalization=None):
249
+ from .evolution_report import verified_evolution_report
250
+ from .base import _payloads
251
+ from .support import risk
252
+ session=require_session()
253
+ from . import component_cache_v2 as cache
254
+ from .runtime_io import artifact_path
255
+ from .execution_v2 import validate_model
256
+ from .support import FamilyModel
257
+ snapshots=None
258
+ def components():
259
+ # Projection-local snapshot only. No reusable runtime/cache trust.
260
+ # Decode each completed component once,then recheck matching receipt,
261
+ # artifact hash and provenance on every packet/final verification.
262
+ nonlocal snapshots
263
+ if snapshots is None:
264
+ snapshots={}
265
+ for path in session.store.keys.glob('*/COMPLETE.json'):
266
+ session.check();row=cache._read(path)
267
+ request=cache.FitRequest(cache.canonical(row['request']))
268
+ receipt=session.store._result(request,path.parent)
269
+ native=validate_model(artifact_path(receipt['artifact']['path']),request.value())
270
+ normalized=_payloads(FamilyModel(row['request']['task'],[native],[1.]))[0]
271
+ snapshots[request.key]=(path,request,receipt,normalized)
272
+ return snapshots
273
+ def verify(packet):
274
+ p,model,search,train=self._report_evidence[packet['id']]
275
+ if p!=packet or digest(_payloads(model))!=packet['artifact_sha256']:
276
+ raise ValueError('Report refers to altered native weights or packet')
277
+ # Request keys are bound to exactly these native payloads by the
278
+ # committed store and executor. Reopen each receipt, do not count
279
+ # a family packet as one physical bagging member.
280
+ keys=[]
281
+ payloads=_payloads(model)
282
+ for path,request,receipt,normalized in components().values():
283
+ v=request.value()
284
+ if (normalized in payloads and v['task']==packet['task'] and v['rows']==len(train['y'])
285
+ and v['family']==packet['family']
286
+ and v['structure']==packet['recipe']['genome']):
287
+ session.check()
288
+ if session.store._result(request,path.parent)!=receipt:
289
+ raise ValueError('Report receipt/provenance changed after snapshot')
290
+ keys.append(request.key)
291
+ if len(keys)!=len(payloads):raise ValueError('Missing committed report components')
292
+ return {'packet_sha256':digest(packet),'component_keys':keys,
293
+ 'prediction':model.probabilities_or_values(search['X']),
294
+ 'TRAIN_primary':risk(packet['task'],train['y'],model.probabilities_or_values(train['X']),packet['recipe']['classes']),
295
+ 'artifacts':{'native_payload_sha256':packet['artifact_sha256']}}
296
+ def oof(row):
297
+ p=session._diagnostic_proofs.get(row['context'])
298
+ if p is None or not session.verify_evolution_context(p['context'],p['parent']):
299
+ raise ValueError('Missing authenticated OOF proof for report')
300
+ from . import component_cache_v2 as cache
301
+ from .runtime_io import artifact_path
302
+ proof=cache._read(artifact_path(p['artifact']))
303
+ receipts=[x for f in proof['folds'] for x in f['receipts']]
304
+ keys={cache.FitRequest(cache.canonical(x['request'])).key for x in receipts}
305
+ cached=sum(r['event']=='CACHE_HIT' and r.get('key') in keys for r in session.store.events())
306
+ return {'context':row['context'],'parent':digest(p['parent']),
307
+ 'program_sha256':p['context']['program_sha256'],'components':len(receipts),
308
+ 'cache_components':cached,'mode':proof['mode'],'evidence':p['context']['evidence'],
309
+ 'seconds':proof['acquisition_seconds_operational'],
310
+ 'component_keys':sorted(keys),
311
+ 'artifacts':{'path':p['artifact'],'sha256':p['sha256']}}
312
+ packets={n:p[0] for n,p in self._report_evidence.items()}
313
+ def metric(packet,pred):
314
+ search=self._report_evidence[packet['id']][2]
315
+ return risk(packet['task'],search['y'],pred,packet['recipe']['classes'])
316
+ final=self.last_attempt_['best_verified_anchor']
317
+ def unadopted(keys):
318
+ if session.mode!='PUBLIC_USER' or not self.last_attempt_.get('search_budget_stop'):
319
+ raise ValueError('Only explicit public typed-cutoff recovery may account unadopted work')
320
+ rows={}
321
+ for key in keys:
322
+ session.check();path=artifact_path(session.store.keys/key/'INTENT.json')
323
+ intent=cache._read(path);request=cache.FitRequest(cache.canonical(intent['request']))
324
+ if request.key!=key or intent['key']!=key:raise ValueError('Invalid incomplete component intent')
325
+ committed=key in components();artifact=None
326
+ if committed:
327
+ cp,r,receipt,_=components()[key]
328
+ if r!=request or session.store._result(r,cp.parent)!=receipt:
329
+ raise ValueError('Unadopted completed component changed')
330
+ artifact=copy.deepcopy(receipt['artifact'])
331
+ rows[key]={'key':key,'intent_sha256':cache.sha(path),
332
+ 'committed':committed,'artifact':artifact,'used_in_final_model':False}
333
+ return rows
334
+ projection=verified_evolution_report(session.store.events(),packets=packets,
335
+ verify_packet=verify,verify_oof=oof,program=learning_program,metric=metric,
336
+ final_packet=final,mode=session.mode,finalization=finalization,
337
+ budget_recovery=unadopted if session.mode=='PUBLIC_USER' else None)
338
+ projection['component_audit']={'native_decodes':len(snapshots or {}),
339
+ 'scope':'ONE_DECODE_PER_COMMITTED_COMPONENT_PER_PROJECTION',
340
+ 'integrity':'Matching receipt/artifact/provenance rechecked on every packet and final verification;no cross-projection cache'}
341
+ m=self.report_['morphing'];m['verified_report']=projection
342
+ m.update(diagnosis_executed=projection['diagnosis_executed'],
343
+ decision='EVOLUTION_EVALUATED' if projection['steps'] else 'ABSTAIN_NO_ADMITTED_TRANSFORMATION',
344
+ information_acquisition={'new_OOF':projection['counts']['OOF_physical_fits_completed'],
345
+ 'new_fits':projection['counts']['OOF_physical_fits_completed'],
346
+ 'measured_seconds':projection['OOF_acquisition_method_seconds'],
347
+ 'cost_scope':projection['cost_scope']})
348
+ if projection.get('budget_recovery'):
349
+ m['decision']='PARTIAL_SEARCH_BUDGET_VERIFIED_ANCHOR_RETURNED'
350
+ m['information_acquisition']['complete_contexts']=projection['counts']['OOF_contexts_acquired']
351
+ m['information_acquisition']['OOF_information_status']='Only committed fold proofs are diagnostic contexts;partial native OOF work is unadopted'
352
+ self.report_['limitations']=[
353
+ 'No independent adaptive utility/performance/platform qualification',
354
+ 'Child FULL_RETRAIN; no in-place warm start',
355
+ 'Training export is an executor-bound fragment, not autonomous search',
356
+ 'Ordinary user-data execution is not a scientific source/owner permit' if session.mode=='PUBLIC_USER' else 'General public training outside exact owned admission is blocked']
357
+ self.orchestration_report_=copy.deepcopy(self.report_)
358
+ return projection
359
+
360
+ def _parameters(self, params):
361
+ return require_session().parameters(params)
362
+
363
+ def _structure_packet(self, genome, classes, members, encoder):
364
+ session = require_session()
365
+ lineage = session.packet_lineage(genome) if hasattr(session, 'packet_lineage') else {}
366
+ if not lineage and genome!=AlgorithmGenome() and hasattr(self,'_active_evolution_parent'):
367
+ parent=self._active_evolution_parent
368
+ lineage={'gene':'growth_policy','parent_packet_sha256':digest(parent),
369
+ 'from':copy.deepcopy(parent['recipe']['genome']),'to':genome.to_dict(),
370
+ 'reason':'OOF_HEURISTIC_HYPOTHESIS_NOT_CAUSAL_UTILITY'}
371
+ return {'genome':genome.to_dict(), 'classes':list(range(len(classes))),
372
+ 'members':members, 'encoder':encoder.to_dict(), 'lineage':lineage}
373
+
374
+ def _extra_opportunities(self):
375
+ if self._evolving_program and self.morphing=='auto':return self._max_mutations
376
+ return int(require_session().structural and self.morphing=='auto' and self._research_growth)
377
+
378
+ def _optional_optuna(self):
379
+ return require_session().optional_optuna()
380
+
381
+ def _numeric_admitted(self, executor):
382
+ return require_session().numeric_admitted(executor)
383
+
384
+ def _load_optuna(self):
385
+ return require_session().load_optuna()
386
+
387
+ def _diagnose(self, context):
388
+ if context != {'OOF':None, 'admitted_operators':[]}:
389
+ raise ValueError('No caller-supplied OOF/GUARD in this profile')
390
+ result = mutation_admission(self.morphing)
391
+ if self.morphing == 'auto':
392
+ result.update(diagnosis_status='ABSTAIN_NO_AUTHENTIC_FIXED_TRAIN_OOF',
393
+ decision='ABSTAIN_DIAGNOSTIC_GUIDANCE', utility='INCONCLUSIVE')
394
+ return result
395
+
396
+ def _structural_stage(self, selected, result, acquire, verify, selection, params, log, attempt):
397
+ if self._evolving_program:
398
+ try:return self._evolve_program(selected,result,acquire,verify,selection,params,log,attempt)
399
+ except SearchBudgetExhausted as exc:
400
+ anchor=copy.deepcopy(attempt['best_verified_anchor'])
401
+ self._budget_stopped('EVOLUTION',anchor,attempt,log,exc)
402
+ trace=attempt['evolution']
403
+ if trace['steps'] and trace['steps'][-1]['status']=='INTERRUPTED':
404
+ step=trace['steps'][-1]
405
+ log('evolution_interrupted',index=step['index'],parent=step['parent'],
406
+ retained=anchor['id'],reason='TYPED_SEARCH_BUDGET',
407
+ decision='RESTORE_VERIFIED_PARENT')
408
+ trace.update(stop='SEARCH_BUDGET_DURING_EVOLUTION',retained=anchor['id'],
409
+ accepted_program=learning_program(anchor))
410
+ log('evolution_complete',program=learning_program(anchor),stop=trace['stop'],
411
+ retained=anchor['id'],utility='NOT_DEMONSTRATED')
412
+ from .support import risk
413
+ prediction=verify(anchor,selection)
414
+ return anchor,{'packet':anchor,'prediction':prediction,
415
+ 'loss':risk(anchor['task'],selection['y'],prediction,anchor['recipe']['classes'])}
416
+ session = require_session()
417
+ if not self._research_growth or not session.structural or self.morphing=='none' or selected['task']!='binary':
418
+ return selected, result
419
+ # Explicit static technical nomination, never inferred diagnostic value.
420
+ proposals = [p for p in propose_mutations(AlgorithmGenome(), {'diagnoses':[]})
421
+ if p.gene=='growth_policy' and p.genome.growth_policy=='depthwise']
422
+ if len(proposals)!=1: raise ValueError('Existing canonical operator missing/ambiguous')
423
+ proposal = proposals[0]
424
+ log('structural_proposal', gene=proposal.gene, genome=proposal.genome.to_dict(), parent_packet=copy.deepcopy(selected),
425
+ origin='EXPLICIT_STATIC_TECHNICAL_NOMINATION_NOT_SELF_DIAGNOSIS')
426
+ coordinator = StructuralChoice(selected, selection, verify=verify,
427
+ checkpoint=lambda e:log('structural_selection', **e))
428
+ technical={'origin':'STATIC_TECHNICAL_NOT_DIAGNOSTIC_GUIDANCE',
429
+ 'gene':proposal.gene,'parent_id':selected['id'],
430
+ 'parent_packet_sha256':digest(selected),'candidate_id':'growth:depthwise',
431
+ 'candidate_genome':proposal.genome.to_dict(),'status':'INTENT'}
432
+ attempt['structural']=technical
433
+ try:
434
+ # The selected family is preserved; bag members reset just as in Base.
435
+ candidate = acquire('growth:depthwise', selected['family'], params, proposal.genome)
436
+ result = coordinator.offer_growth(candidate)
437
+ selected = result['packet']
438
+ attempt['best_verified_anchor'] = copy.deepcopy(selected)
439
+ technical.update(status='COMPLETED',retained=selected['id'],
440
+ decision='ACCEPT' if selected['id']=='growth:depthwise' else 'ROLLBACK',
441
+ SEARCH_primary=result['loss'])
442
+ except (TimeoutError, KeyboardInterrupt):
443
+ raise
444
+ except Exception as exc:
445
+ session.check() # STOP/deadline must not be swallowed as a candidate failure.
446
+ log('structural_rollback', reason=type(exc).__name__, message=str(exc),
447
+ retained=selected['id'])
448
+ result = coordinator.best
449
+ technical.update(status='FAILED_ROLLED_BACK',retained=selected['id'],
450
+ decision='ROLLBACK',error=type(exc).__name__,message=str(exc))
451
+ return selected, result
452
+
453
+ def _evolve_program(self, selected, result, acquire, verify, selection, params, log, attempt):
454
+ """Continue from accepted native programs; no static winner preselection.
455
+
456
+ Uses the same component acquisition/coordinator. Every current child is
457
+ explicitly a FULL_RETRAIN, not warm start. Original weights stay intact.
458
+ Session/worker/store own physical caps, STOP and deadlines; this finite
459
+ opportunity limit never grants learning authority or resets their caps.
460
+ """
461
+ session=require_session();current=learning_program(selected)
462
+ trace={'schema':'comp007-evolution-trace-v1','initial_program':copy.deepcopy(current),
463
+ 'initial_anchor':selected['id'],'steps':[], 'diagnostics':[], 'evidence':session.mode,
464
+ 'stop':'UNKNOWN','accepted_program':copy.deepcopy(current),
465
+ 'continuation':'ACCEPTED_PROGRAM_AND_RETAINED_PARENT_WEIGHTS',
466
+ 'warm_start_implemented':False,'global_optimum_claim':False,
467
+ 'max_mutation_opportunities':self._max_mutations}
468
+ attempt['evolution']=trace
469
+ seen={digest(current)};attempted=0
470
+ def stopped(reason):
471
+ trace.update(stop=reason,retained=selected['id'])
472
+ log('evolution_complete',program=copy.deepcopy(current),stop=reason,
473
+ retained=selected['id'],utility='NOT_DEMONSTRATED')
474
+ return selected,result
475
+ if self.morphing=='none':return stopped('EXPLICIT_BASELINE')
476
+ if selected['task']!='binary':
477
+ from morphtree.diagnostics import ErrorProfiler
478
+ if not callable(getattr(ErrorProfiler,'profile_task',None)):
479
+ return stopped('ABSTAIN_NONBINARY_STRUCTURAL_DISPATCH_UNQUALIFIED')
480
+ if not callable(getattr(session,'evolution_context',None)):
481
+ return stopped('ABSTAIN_NO_AUTHENTIC_FIXED_PARENT_TRAIN_OOF')
482
+ while attempted<self._max_mutations:
483
+ if not self._search_budget_open():return stopped('SEARCH_BUDGET_BEFORE_DIAGNOSIS')
484
+ session.check()
485
+ context=session.evolution_context(copy.deepcopy(selected),copy.deepcopy(current))
486
+ if context is None:
487
+ trace['stop']='ABSTAIN_INSUFFICIENT_DIAGNOSTIC_INFORMATION';break
488
+ context=evolution_context(context,selected,current,
489
+ authenticate=getattr(session,'verify_evolution_context',None))
490
+ trace['diagnostics'].append({'parent':selected['id'],'program_sha256':digest(current),
491
+ 'context_sha256':digest(context),'profile':copy.deepcopy(context['profile']),
492
+ 'evidence':context['evidence'],'causal_status':'HYPOTHESES_NOT_IDENTIFIED_CAUSES'})
493
+ log('diagnosis_completed',parent=selected['id'],parent_packet_sha256=digest(selected),
494
+ context_sha256=digest(context),program_sha256=digest(current),evidence=context['evidence'])
495
+ strengths={r['name']:r['strength']*r['confidence'] for r in context['profile']['diagnoses']}
496
+ proposals=[]
497
+ for p in propose_mutations(AlgorithmGenome(**current['genome']),context['profile']):
498
+ # Existing proposals are hypotheses, never automatic admission.
499
+ try:child=transformed_program(current,p)
500
+ except ValueError as exc:
501
+ log('evolution_proposal_rejected',gene=p.gene,
502
+ reason='INCOMPATIBLE_TYPED_PROGRAM',detail=str(exc))
503
+ continue # No training or admission follows this proposal.
504
+ key=digest(child)
505
+ signal=p.reason.removeprefix('Hypothesis ').split(':',1)[0]
506
+ if key not in seen and key in context['allowed_programs'] and strengths.get(signal,0)>0:
507
+ proposals.append((p,child,key))
508
+ if not proposals:
509
+ trace['stop']='NO_ADMITTED_UNTRIED_DIAGNOSTIC_TRANSFORMATION';break
510
+ p,child,key=proposals[0];seen.add(key);attempted+=1
511
+ before=copy.deepcopy(selected)
512
+ step={'index':attempted,'parent':before['id'],'parent_program_sha256':digest(current),
513
+ 'parent_packet_sha256':digest(before),
514
+ 'child_program':copy.deepcopy(child),'gene':p.gene,'hypothesis':p.reason,
515
+ 'diagnostic_context_sha256':digest(context),'diagnostic_evidence':context['evidence'],
516
+ 'execution':'FULL_RETRAIN_REQUIRED_NOT_IN_PLACE','status':'INTENT',
517
+ 'numeric_parameters_sha256':digest(before['params']),
518
+ 'cost_before':copy.deepcopy(session.counters()) if callable(getattr(session,'counters',None)) else 'UNKNOWN'}
519
+ trace['steps'].append(step);log('evolution_intent',**copy.deepcopy(step))
520
+ coordinator=StructuralChoice(before,selection,verify=verify,
521
+ checkpoint=lambda e:log('evolution_selection',**e))
522
+ try:
523
+ family,genome=program_dispatch(child)
524
+ self._active_evolution_parent=copy.deepcopy(before)
525
+ candidate=acquire('evolution:'+str(attempted),family,type(params)(**before['params']),genome)
526
+ result=coordinator.offer_transform(candidate,child);selected=result['packet']
527
+ accepted=selected['id']==candidate['id']
528
+ step.update(status='COMPLETED',decision='ACCEPT' if accepted else 'ROLLBACK',
529
+ retained=selected['id'],SEARCH_primary=result['loss'])
530
+ if accepted:current=copy.deepcopy(child)
531
+ # Re-diagnosis next iteration is bound to THIS accepted parent.
532
+ attempt['best_verified_anchor']=copy.deepcopy(selected)
533
+ trace['accepted_program']=copy.deepcopy(current)
534
+ if not accepted and set(context['allowed_programs'])<=seen:
535
+ # The identical parent/context cannot nominate any unseen
536
+ # admitted program. Do not reacquire/reverify its OOF just
537
+ # to rediscover the same exhausted candidate set.
538
+ trace['stop']='NO_UNTRIED_ALLOWED_PROGRAM_AFTER_ROLLBACK'
539
+ break
540
+ except (TimeoutError,KeyboardInterrupt):
541
+ step.update(status='INTERRUPTED',decision='RESTORE_VERIFIED_PARENT',retained=before['id'])
542
+ raise
543
+ except Exception as exc:
544
+ step.update(status='FAILED',decision='ROLLBACK',retained=before['id'],error=type(exc).__name__)
545
+ selected=before;result=coordinator.best
546
+ session.check() # Never swallow STOP/deadline as a mere candidate error.
547
+ log('evolution_failure',retained=before['id'],error=type(exc).__name__)
548
+ trace['stop']='CANDIDATE_ERROR_ROLLBACK';break
549
+ finally:
550
+ self.__dict__.pop('_active_evolution_parent',None)
551
+ step['cost_after']=copy.deepcopy(session.counters()) if callable(getattr(session,'counters',None)) else 'UNKNOWN'
552
+ else:trace['stop']='MUTATION_OPPORTUNITY_BUDGET_EXHAUSTED'
553
+ trace['retained']=selected['id']
554
+ log('evolution_complete',program=copy.deepcopy(current),stop=trace['stop'],
555
+ retained=selected['id'],utility='NOT_DEMONSTRATED')
556
+ return selected,result
557
+
558
+ def fit(self, X, y):
559
+ # Post-learning report verification is part of the transaction too.
560
+ # Existing fitted objects remain recoverable if that verification fails.
561
+ before=dict(self.__dict__)
562
+ try:return self._fit_with_verified_reporting(X,y)
563
+ except BaseException:
564
+ attempt=copy.deepcopy(getattr(self,'last_attempt_',{}))
565
+ self.__dict__.clear();self.__dict__.update(before)
566
+ self.last_attempt_=attempt
567
+ if attempt.get('status')=='PASS':
568
+ self.last_attempt_.update(status='FAIL',stop_reason='REPORT_VERIFICATION_FAILED_RESTORED_PRIOR_OBJECT')
569
+ raise
570
+
571
+ def _fit_with_verified_reporting(self, X, y):
572
+ session = require_session()
573
+ session.bind_input(self, X, y)
574
+ if session.mode=='PUBLIC_USER':session.begin_search()
575
+ self._report_evidence = {}
576
+ self._workdir = str(session.root)
577
+ # Reuse the original finite fit loop (generated hooks documented in build).
578
+ with session.orchestration_operation(self):
579
+ result = LearningControl.fit(self, X, y)
580
+ self._input_sha256 = None
581
+ if session.mode=='FIXTURE' and self.report_['trials']:
582
+ self.report_['trial_evidence']='SIMULATED_OPTUNA_FIXTURE_NOT_REAL_TRIALS'
583
+ elif session.mode=='PUBLIC_USER' and self.report_['trials']:
584
+ self.report_['trial_evidence']='USER_DATA_REAL_OPTUNA_NOT_SCIENTIFIC_CONFIRMATION'
585
+ elif session.mode=='LIVE' and self.report_['trials']:
586
+ self.report_['trial_evidence']='EXACT_OWNER_BOUND_REAL_OPTUNA_TRIALS'
587
+ technical=self.last_attempt_.get('structural')
588
+ if technical is not None:
589
+ self.report_['morphing']['technical_structural_exploration']=copy.deepcopy(technical)
590
+ self.report_['morphing']['attempted']=[technical['candidate_id']]
591
+ key='accepted' if technical['decision']=='ACCEPT' else 'rollback'
592
+ self.report_['morphing'][key]=[technical['candidate_id']]
593
+ self.report_['stop_details']['structural']='FINITE_TECHNICAL_COMPARISON_'+technical['status']
594
+ evolution=self.last_attempt_.get('evolution')
595
+ if evolution is not None:
596
+ self.algorithm_program_=copy.deepcopy(evolution['accepted_program'])
597
+ self.program_history_=copy.deepcopy(evolution)
598
+ self.report_['morphing']['evolution']=copy.deepcopy(evolution)
599
+ if evolution['diagnostics']:
600
+ self.report_['morphing'].update(
601
+ diagnosis_status='CONSUMED_INTERNAL_FIXED_PARENT_PROFILES_'+session.mode,
602
+ diagnostic_profiles_consumed=len(evolution['diagnostics']),
603
+ rediagnosis='CURRENT_RETAINED_PARENT_BOUND_CONTEXTS',utility='INCONCLUSIVE')
604
+ self.report_['morphing']['attempted']=[s['index'] for s in evolution['steps']]
605
+ self.report_['morphing']['accepted']=[s['index'] for s in evolution['steps'] if s.get('decision')=='ACCEPT']
606
+ self.report_['morphing']['rollback']=[s['index'] for s in evolution['steps'] if s.get('decision')=='ROLLBACK']
607
+ self.report_['stop_details']['structural']=evolution['stop']
608
+ self.report_['accounting']['physical_fits']=session.physical
609
+ self.report_['execution_mode']=self.mode
610
+ if self.report_['tuning'] in ('OPTUNA_STOPPED_SEARCH_BUDGET','SKIPPED_SEARCH_BUDGET') or self.last_attempt_.get('search_budget_stop'):
611
+ self.report_['stop_details']['numeric']=self.report_['tuning']
612
+ self.report_['stop_reason']='SEARCH_BUDGET_RESERVED_FOR_FINALIZATION'
613
+ self.stop_reason_=self.report_['stop_reason']
614
+ self.last_attempt_['stop_reason']=self.stop_reason_
615
+ if not self.report_['trials'] and 'tuned' in self._variants:
616
+ self._variants.pop('tuned');self._selected_variant='pure'
617
+ if self.last_attempt_.get('search_budget_stop'):
618
+ self.report_['stop_details']['family']='COMPLETE' if not self.report_['families']['not_evaluated'] else 'PARTIAL_BUDGET'
619
+ self.report_['events'].append({'operation':'FIT_TERMINATION',
620
+ 'model':'COMPLETE_VERIFIED_ANCHOR',
621
+ 'search':'PARTIAL_BUDGET' if self.last_attempt_.get('search_budget_stop') else 'CONFIGURED_PATH_COMPLETE',
622
+ 'tuning':self.report_['tuning'],'families':copy.deepcopy(self.report_['families'])})
623
+ self.orchestration_report_ = copy.deepcopy(self.report_)
624
+ # Existing V3 outer report is strict. Keep full cost/decisions in events;
625
+ # do not broaden its schema or drop native/recipe state.
626
+ allowed = {'schema','task','metric','classes','seed','best_family','SEARCH_primary',
627
+ 'selection','tuning','trials','morphing','stop_reason','worker_admission','events',
628
+ 'refit_performed','GUARD_used','final_model_role','wall_seconds',
629
+ 'process_cpu_seconds','descendant_cpu','peak_RSS','cost_scope','limitations'}
630
+ extras = {k:v for k,v in self.report_.items() if k not in allowed}
631
+ self.report_ = {k:v for k,v in self.report_.items() if k in allowed}
632
+ self.report_['events'].append({'operation':'COMP003_ACCOUNTING_AND_SCOPE',
633
+ 'details':extras, 'counts':session.counters(), 'scope':session.mode})
634
+ self._cost = session.counters()
635
+ self.last_attempt_['physical_fits']=session.physical
636
+ # Fixtures may be saved only under the explicitly versioned fixture
637
+ # envelope, and retain their software evidence label after loading.
638
+ from .producer import evolution_profile
639
+ form='product006-frozen-form-v1' if session.mode=='PUBLIC_USER' else 'product002-frozen-form-v1'
640
+ for variant in self._variants.values():
641
+ variant['recipe']['schema']=form
642
+ variant['exportable']=True
643
+ self.best_recipe_['schema']=form
644
+ if evolution is not None:
645
+ self._verify_evolution_report()
646
+ self._cost=session.counters()
647
+ return result
648
+
649
+ def get_algorithm_program(self):
650
+ self._fitted()
651
+ if not hasattr(self,'algorithm_program_'):
652
+ raise ValueError('This historical model has no recorded evolving training program')
653
+ return copy.deepcopy(self.algorithm_program_)
654
+
655
+ def describe_algorithm(self):
656
+ p=self.get_algorithm_program();history=self.program_history_
657
+ return {'program':p,'evolution':copy.deepcopy(history),
658
+ 'training_code_export':'EXECUTOR_BOUND_TRAIN_ENCODED_FRAGMENT_NOT_STANDALONE',
659
+ 'inference_export':'USE_EXISTING_EXPORT_PYTHON',
660
+ 'utility':'INCONCLUSIVE','continuation':'FULL_RETRAIN_CHILDREN; RETAIN_PARENT_ON_ROLLBACK'}
661
+
662
+ def export_algorithm(self,path):
663
+ """Export a validated native training fragment, NOT autonomous training.
664
+
665
+ The generated code requires this installed runtime and an already
666
+ admitted/prepared Session, TRAIN encoding, identity and inspect scope.
667
+ It neither creates a grant nor reproduces the whole evolutionary search.
668
+ Data and generated arbitrary source never enter executable expressions.
669
+ """
670
+ self._io()
671
+ from .runtime_io import artifact_path, publish
672
+ p=self.get_algorithm_program();program_dispatch(p)
673
+ from morphtree.config import HyperParams
674
+ from pathlib import Path
675
+ from .admission import sha
676
+ HyperParams(**self.best_recipe_['params'])
677
+ text='''# MorphTree validated native training fragment; not standalone.
678
+ # Requires an admitted installed Session and encoded TRAIN with exact provenance.
679
+ # No search, OOF, new authority or arbitrary evaluation is generated here.
680
+ from morphtree.config import HyperParams
681
+ from morphtree._experimental.integrated import program_dispatch
682
+ from morphtree._experimental.execution_v2 import require_session
683
+ PROGRAM = %r
684
+ PARAMETERS = %r
685
+ SEED = %r
686
+ RUNTIME_MANIFEST_SHA256 = %r
687
+ EXPORT_SCOPE = 'EXECUTOR_BOUND_TRAIN_ENCODED_FRAGMENT_NOT_END_TO_END_SEARCH'
688
+ def train_encoded(X, y, *, identity):
689
+ family, genome = program_dispatch(PROGRAM)
690
+ session = require_session()
691
+ if session.engine.identity['manifest_sha256'] != RUNTIME_MANIFEST_SHA256:
692
+ raise ValueError('Training fragment requires its exact admitted runtime manifest')
693
+ return session.executor(None).fit_family(PROGRAM['task'], family, X, y,
694
+ seed=SEED, params=HyperParams(**PARAMETERS), genome=genome,
695
+ check=session.check, identity=identity)
696
+ ''' % (p,copy.deepcopy(self.best_recipe_['params']),self.best_recipe_['seed'],
697
+ sha(Path(__file__).with_name('manifest.json')))
698
+ publish(artifact_path(path),text,lambda:None)
699
+
700
+ def get_mutation_history(self):
701
+ self.get_algorithm_program()
702
+ return copy.deepcopy(self.program_history_)
703
+
704
+ def get_recipe(self):
705
+ return self.recipe()
706
+
707
+ def get_search_report(self):
708
+ """Verified projection when available; never relabel legacy summaries."""
709
+ self._fitted()
710
+ projection=self.report_.get('morphing',{}).get('verified_report')
711
+ if projection is None:
712
+ return {'status':'HISTORICAL_UNRECONCILED_REPORT','verified':False,
713
+ 'report':self.report()}
714
+ value=copy.deepcopy(projection)
715
+ if not hasattr(self,'_report_evidence'):
716
+ value['recorded_status']=value['status']
717
+ value['status']='PERSISTED_REPORT_NOT_REVERIFIED'
718
+ value['verified']=False
719
+ value['reverification']='PERSISTED_REPORT_JOURNAL_NOT_REOPENED'
720
+ else:value['verified']=True
721
+ return value
722
+
723
+ @classmethod
724
+ def load(cls,path,*,sha256,workdir):
725
+ obj=super().load(path,sha256=sha256,workdir=workdir)
726
+ trace=obj.report_.get('morphing',{}).get('evolution')
727
+ if trace is not None:
728
+ # The report is descriptive, never fit authority. Reconstruct its
729
+ # final program only if it describes the safely loaded native form.
730
+ if type(trace) is not dict or trace.get('schema')!='comp007-evolution-trace-v1':
731
+ raise ValueError('Unknown program history')
732
+ expected=learning_program({'task':obj.task_,'family':obj.best_family_,
733
+ 'recipe':obj.best_recipe_['structure']})
734
+ if trace.get('accepted_program')!=expected:
735
+ raise ValueError('Recorded learning program differs from loaded native model')
736
+ cap=trace.get('max_mutation_opportunities')
737
+ if type(cap) is not int or not 0<=cap<=8 or type(trace.get('steps')) is not list or len(trace['steps'])>cap:
738
+ raise ValueError('Invalid bounded program history')
739
+ obj.algorithm_program_=copy.deepcopy(expected)
740
+ obj.program_history_=copy.deepcopy(trace);obj._max_mutations=cap
741
+ return obj
742
+
743
+ def cost_report(self):
744
+ if hasattr(self, '_cost'):
745
+ return copy.deepcopy(self._cost)|{'scope':self.report_['worker_admission'],
746
+ 'performance_qualified':False,'peak_RSS':'UNKNOWN'}
747
+ return super().cost_report()
748
+