Diff Coverage

Diff: origin/master...HEAD, staged and unstaged changes

Source File Diff Coverage (%) Missing Lines
hyper_parallel/codegen/__init__.py 100%  
hyper_parallel/codegen/artifact.py 96.0% 368
hyper_parallel/codegen/build.py 100%  
hyper_parallel/codegen/check/__init__.py 100%  
hyper_parallel/codegen/check/drift.py 87.5% 45
hyper_parallel/codegen/check/preflight.py 78.9% 157,167,433,456-460
hyper_parallel/codegen/check/structure.py 93.6% 45-47
hyper_parallel/codegen/cli.py 83.3% 92,98-99,108-109,127
hyper_parallel/codegen/emit/bundle.py 54.7% 99,111,113,149-150,154,157,161,175-180,183-184,189-192,196-197,205-210,218,237,262-263,267-268,273-274,280,289-290
hyper_parallel/codegen/emit/modeling.py 62.1% 118,124,132-133,139-140,143,162,191-192,199,203,330-332,334,339,346,368,447-450,453-454,462,519,531-534,538-540,552,559,567-569,578,581,584,587,592-593,597-598,606-607,611-612,619-622,631-635,638-640,644,669,678,723,729,759
hyper_parallel/codegen/emit/parallel.py 100%  
hyper_parallel/codegen/emit/patches.py 73.8% 78-81,89,102,112,120,124,126,133-139
hyper_parallel/codegen/emit/recorded.py 67.7% 69,80,83-84,86,110,147,157,162,166-167,240-241,250,260,265-268,270-271,273-276,279,310,327-328,333-341,345,357,374-385,395-401,404
hyper_parallel/codegen/emit/replacement.py 85.2% 29,35,41,46
hyper_parallel/codegen/generated_support.py 100%  
hyper_parallel/codegen/hash.py 87.5% 52
hyper_parallel/codegen/inline/framework_spec.py 29.7% 147,153,260-265,313-314,341,351,410,434,441,488-489,493-501
hyper_parallel/codegen/inline/ir.py 100%  
hyper_parallel/codegen/inline/meta_plan.py 7.7% 102,106-107,111-112,116-122
hyper_parallel/codegen/inline/patch_engine.py 84.1% 66-68,176-177,317,321,340,578-579,583,590,593,596,633,661,664
hyper_parallel/codegen/inline/pipeline.py 59.0% 64-65,68,73,75,82-83,96,135,138,156,179-180,190-191,193,200,230-233,238,243-244,250,255,259-264
hyper_parallel/codegen/inline/recognition.py 86.8% 215,218,221,232,252,274,278,291-293,316,325,333,348,359,363,423
hyper_parallel/codegen/inline/replacement_pass.py 0.0% 60,71
hyper_parallel/codegen/inline/spec_bundle.py 66.7% 67,74,79
hyper_parallel/codegen/inline/strategy_pass.py 59.2% 102,104-105,107-108,117-119,122-129,151,154,160,176
hyper_parallel/codegen/inline/templates.py 100%  
hyper_parallel/codegen/inline/yaml_rules.py 85.7% 66
hyper_parallel/codegen/manager.py 78.3% 80,82,89,123,264,308,313,341,357,361-362,371,374,383,388,407,411-412,431,434,447,451-452,456,462-464,468,488,493-501,508-510,518,523,564,570,623,625-628,633,636
hyper_parallel/codegen/meta.py 78.8% 184,190-191,195,197,199,203,231,244,252,273,300,315,320,322,336,355,357
hyper_parallel/codegen/model_build_overlay.py 75.0% 38-44,72-76,121,126,298,309,313-317,327,334,339,346-347,351-356
hyper_parallel/codegen/offline_build.py 100%  
hyper_parallel/codegen/plan/freeze.py 83.8% 47,347,365-368,385-389,452,461
hyper_parallel/codegen/planner_overlay.py 68.8% 34-37,42-45,63-64,72-81,87-88,100,110
hyper_parallel/codegen/session.py 85.7% 55,66,80,100,145,153,163-167,207,214,232-233,259-260,268,274
hyper_parallel/codegen/snapshot.py 80.0% 53,55,60,63,66-69,76,101-103,131,149,194,196,198,209,233,238,240,242,245,249,255,264-265,270,272,274,278,280,284-286,293
hyper_parallel/codegen/source/composition.py 89.7% 44,50,70-73,76-77,131,178,206
hyper_parallel/codegen/source/resolver.py 33.3% 430-433
hyper_parallel/codegen/train_sidecar.py 93.8% 58-59,162
hyper_parallel/trainer/config/parallelism.py 100%  
hyper_parallel/trainer/config/resolver.py 100%  
hyper_parallel/codegen/artifact.py
364
365
366
367
368
369
370
371
372
            if time.monotonic() >= deadline:
                raise TimeoutError(
                    f"codegen: timed out waiting for artifact lock {lock_path}"
                ) from None
            time.sleep(0.1)
    try:
        os.write(descriptor, str(os.getpid()).encode("ascii"))
        yield
    finally:
hyper_parallel/codegen/check/drift.py
41
42
43
44
45
46
47
48
49
        TypeError: If ``snapshot`` is not a :class:`CodegenSnapshot`.
        RuntimeError: If the artifact was generated from another snapshot.
    """
    if not isinstance(snapshot, CodegenSnapshot):
        raise TypeError("snapshot must be a CodegenSnapshot")
    current_signature = signature_from_snapshot(snapshot)
    if meta.signature != current_signature:
        raise RuntimeError(
            "codegen drift: snapshot signature mismatch "
hyper_parallel/codegen/check/preflight.py
153
154
155
156
157
158
159
160
161
            "snapshot_schema_version and snapshot_status"
        )
    if status == CodegenStatus.NOT_REQUIRED.value:
        if not getattr(meta, "snapshot_reason", None):
            raise RuntimeError(
                "codegen preflight: not_required snapshot is missing its reason"
            )
        if (
            getattr(meta, "param_plan", None)
163
164
165
166
167
168
169
170
171
            or getattr(meta, "plan_application", None)
            or (getattr(meta, "entrypoints", None) or {}).get("parallelize")
            or (getattr(meta, "covered", None) or {}).get("sharding_plan")
        ):
            raise RuntimeError(
                "codegen preflight: not_required snapshot contains executable plan data"
            )
        return
    if status == CodegenStatus.FAILED.value:
429
430
431
432
433
434
435
436
437
        )

    # Every trainable model parameter must be covered by an explicit plan
    # entry (exact FQN or a leaf under a grouped key).
    tied = _expand_tied_param_names(meta)
    uncovered = [
        fqn
        for fqn in _iter_trainable_params(model)
        if not any(fqn == key or fqn.startswith(f"{key}.") for key in planned)
452
453
454
455
456
457
458
459
460
461
462
463
464
    as its canonical counterpart, which is the side the plan records.  The
    non-canonical aliases therefore have no plan entry of their own by design
    and must not be reported as uncovered.
    """
    tied: set[str] = set()
    for pair in getattr(meta, "tied_pairs", None) or []:
        if len(pair) >= 2:
            tied.add(pair[1])
    return tied


# ---------------------------------------------------------------------------
# helpers
hyper_parallel/codegen/check/structure.py
41
42
43
44
45
46
47
48
49
50
51
        if not filename.endswith(".py") or filename == "__init__.py":
            continue
        try:
            tree = ast.parse(source_text, filename=filename)
        except SyntaxError as exc:
            errors.append(f"{filename}: invalid Python source ({exc.msg})")
            continue
        for class_node in (
            node for node in ast.walk(tree) if isinstance(node, ast.ClassDef)
        ):
            _verify_class(filename, class_node, errors)
hyper_parallel/codegen/cli.py
88
89
90
91
92
93
94
95
96
            preflight_integrity_check(config, yaml_path)
            layout = resolve_layout_for_config(config, yaml_path)
            meta = load_codegen_meta(layout.meta_path)
            if meta is not None:
                drifts = verify_drift_intact(meta, yaml_path, artifact_dir=layout.artifact_dir)
                if drifts:
                    failed = 1
                    logger.error("codegen: drift in %s: %s", yaml_path, "; ".join(drifts))
                else:
 94
 95
 96
 97
 98
 99
100
101
102
                    failed = 1
                    logger.error("codegen: drift in %s: %s", yaml_path, "; ".join(drifts))
                else:
                    logger.info("codegen: drift intact %s", yaml_path)
            logger.info("codegen: PASS %s", yaml_path)
        except Exception as exc:  # Aggregate failures while scanning all configs.
            failed = 1
            logger.error("codegen: FAIL %s: %s", yaml_path, exc)
    return failed
104
105
106
107
108
109
110
111
112
113

def cmd_check_pin(args: argparse.Namespace) -> int:
    """Validate a Transformers version constraint without generating artifacts."""
    status, installed, spec = verify_transformers_pin(args.transformers_pin)
    logger.info("codegen: transformers pin %s - installed %s (%s)", spec, installed, status)
    return 0


def cmd_train(args: argparse.Namespace) -> int:
    """Launch native training with rank-zero best-effort generation."""
123
124
125
126
127
128
129
130
    """Yield YAML files below root while skipping generated and environment directories."""
    if not os.path.isdir(root):
        return
    for dirpath, dirnames, filenames in os.walk(root):
        dirnames[:] = [name for name in dirnames if name not in _SKIP_DIRS]
        for name in sorted(filenames):
            if name.endswith((".yaml", ".yml")):
                yield os.path.join(dirpath, name)
hyper_parallel/codegen/emit/bundle.py
 95
 96
 97
 98
 99
100
101
102
103
    """
    if snapshot is not None:
        snapshot_payload = snapshot.to_dict()
        if getattr(meta, "snapshot_status", None) != snapshot_payload["status"]:
            raise ValueError("bundle meta and snapshot status do not match")
    if getattr(meta, "snapshot_status", None) == "not_required":
        logger.info("codegen: rendered audit-only bundle %s", layout.artifact_dir)
        modeling_name = os.path.basename(layout.modeling_path)
        return {
107
108
109
110
111
112
113
114
115
116
117
            os.path.basename(layout.diff_path): _NO_PATCH_DIFF,
            "__init__.py": _strip_trailing_whitespace(emit_init_file(layout)),
        }
    if patch_plan is None:
        from hyper_parallel.codegen.emit.patches import emission_patches_from_meta

        patch_plan = emission_patches_from_meta(meta)
    original_text = copy_original_modeling(meta.source)
    generated_text = _prepare_generated_python(
        emit_modeling_file(meta, patch_plan=patch_plan)
    )
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
    from hyper_parallel.codegen.source.resolver import resolve_remote_siblings

    resolved = resolve_remote_siblings(meta.source)
    if resolved:
        siblings, sibling_diffs = _emit_remote_siblings(resolved, meta, patch_plan)
        import_map = {
            os.path.basename(path): name
            for path, name in zip(resolved.values(), siblings)
        }
        files[modeling_name] = _rewrite_sibling_imports(
            files[modeling_name], import_map
        )
        files[os.path.basename(layout.diff_path)] = _strip_trailing_whitespace(
            emit_diff(original_text, files[modeling_name], layout)
        )
        files.update(siblings)
        files.update(sibling_diffs)
        if siblings:
            meta.remote_siblings = sorted(siblings)
    verify_generated_source_structure(files)
    verify_recorded_patch_bundle(files, patch_plan=patch_plan)
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
    meta: Any,
    patch_plan: Any,
) -> tuple[dict[str, str], dict[str, str]]:
    """Materialize remote-code siblings and their visible diffs."""
    siblings, originals, import_map = {}, {}, {}
    for path in resolved.values():
        basename = os.path.basename(path)
        with open(path, "r", encoding="utf-8", errors="replace") as handle:
            original = handle.read()
        materialized = _strip_trailing_whitespace(
            _materialize_sibling(original, meta, patch_plan, source_path=path)
        )
        rendered = _prepare_generated_python(materialized)
        output_name = (
            _generated_sibling_name(basename)
            if materialized != _strip_trailing_whitespace(original)
            else basename
        )
        import_map[basename] = output_name
        siblings[output_name] = rendered
        originals[output_name] = (basename, original)
    siblings = {
        name: _rewrite_sibling_imports(text, import_map)
        for name, text in siblings.items()
    }
    diffs = _remote_sibling_diffs(siblings, originals)
    return siblings, diffs


def _remote_sibling_diffs(
    siblings: dict[str, str],
201
202
203
204
205
206
207
208
209
210
211
212
213
214
    siblings: dict[str, str],
    originals: dict[str, tuple[str, str]],
) -> dict[str, str]:
    """Render diffs only for remote siblings whose source changed."""
    diffs = {}
    for output_name, rendered in siblings.items():
        basename, original = originals[output_name]
        if rendered == _strip_trailing_whitespace(original):
            continue
        diffs[f"{output_name}.diff"] = _strip_trailing_whitespace(
            unified_diff(
                _normalize_copied_source(original),
                rendered,
                fromfile=f"a/{basename}",
214
215
216
217
218
219
220
221
222
                fromfile=f"a/{basename}",
                tofile=f"b/{output_name}",
            )
        )
    return diffs


def _prepare_generated_python(source_text: str) -> str:
    """Mark copied source as generated and normalize comment-only URLs.
233
234
235
236
237
238
239
240
241
        text,
        flags=re.MULTILINE,
    )
    if text.startswith(_GENERATED_SOURCE_HEADER):
        return text
    return (
        _GENERATED_SOURCE_HEADER
        + text.rstrip()
        + "\n"
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
    *,
    source_path: str,
) -> str:
    """Apply source-owned strategy and recorded patches to one sibling."""
    from hyper_parallel.codegen.emit.recorded import materialize_recorded_forwards
    from hyper_parallel.codegen.inline.pipeline import (
        render_inline_strategies_for_source_unit,
    )

    source = getattr(meta, "source", None)
    architecture = (
        source.get("architecture")
        if isinstance(source, dict)
        else getattr(source, "architecture", None)
    )
    model_type = getattr(meta, "model_class", None) or architecture
    rendered = render_inline_strategies_for_source_unit(
        source_text,
        meta,
        model_type=model_type,
        patch_plan=patch_plan,
276
277
278
279
280
281
282
283
284
        meta,
        model_type=model_type,
        patch_plan=patch_plan,
    )
    return materialize_recorded_forwards(
        rendered,
        meta,
        patch_plan=patch_plan,
        source_path=source_path,
285
286
287
288
289
290
291
292
293
294
    )


def _generated_sibling_name(basename: str) -> str:
    stem, extension = os.path.splitext(basename)
    return f"{stem}_gen_npu{extension}"


def _rewrite_sibling_imports(
    source_text: str,
hyper_parallel/codegen/emit/modeling.py
114
115
116
117
118
119
120
121
122
            i += 1
            continue
        # the spec must start with a relative (dots) operator
        j = i + 1
        while j < n and tokens[j].type in (
            tokenize.NL,
            tokenize.NEWLINE,
            tokenize.COMMENT,
        ):
120
121
122
123
124
125
126
127
128
            tokenize.NEWLINE,
            tokenize.COMMENT,
        ):
            j += 1
        if (
            j >= n
            or tokens[j].type != tokenize.OP
            or not set(tokens[j].string) <= {"."}
        ):
128
129
130
131
132
133
134
135
136
137
        ):
            i += 1
            continue
        dots_tok = tokens[j]
        dots = 0
        while (
            j < n
            and tokens[j].type == tokenize.OP
            and tokens[j].string
            and set(tokens[j].string) == {"."}
135
136
137
138
139
140
141
142
143
144
145
146
147
            and tokens[j].type == tokenize.OP
            and tokens[j].string
            and set(tokens[j].string) == {"."}
        ):
            dots += len(tokens[j].string)
            j += 1

        # collect the relative module path: NAME ('.' NAME)*
        k = j
        path: list[str] = []
        last_path_tok = None
        while k < n:
            t = tokens[k]
158
159
160
161
162
163
164
165
166

        # the path must be followed by the ``import`` keyword (allow a comment
        # line in between; a multiline symbol list comes *after* ``import``).
        m = k
        while m < n and tokens[m].type in (
            tokenize.NL,
            tokenize.NEWLINE,
            tokenize.COMMENT,
        ):
187
188
189
190
191
192
193
194
195
196
def _rewrite_dynamic_relative_imports(text: str, anchor: list[str]) -> str:
    """Rewrite imports whose resolved package is not valid Python syntax."""
    try:
        tree = ast.parse(text)
    except SyntaxError:
        return text
    edits = []
    for node in ast.walk(tree):
        if not isinstance(node, ast.ImportFrom) or node.level == 0:
            continue
195
196
197
198
199
200
201
202
203
204
205
206
207
        if not isinstance(node, ast.ImportFrom) or node.level == 0:
            continue
        absolute = _absolute_spec(anchor, node.level, (node.module or "").split("."))
        if absolute is None or _is_import_syntax_safe(absolute):
            continue
        assignments = []
        for alias in node.names:
            if alias.name == "*":
                raise ValueError(
                    f"codegen cannot rewrite a wildcard import from dynamic module {absolute!r}"
                )
            target = alias.asname or alias.name
            assignments.append(
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
        if isinstance(meta.source, dict)
        else getattr(meta.source, "module_name", "")
    )
    text = rewrite_relative_imports(text, module_name)
    text = compose_nested_model_sources(text, meta)
    text = _apply_inline_modeling(text, meta, patch_plan=patch_plan)
    from hyper_parallel.codegen.emit.recorded import materialize_recorded_forwards

    source_path = (
        meta.source.get("file_path")
        if isinstance(meta.source, dict)
        else getattr(meta.source, "file_path", None)
    )
    text = materialize_recorded_forwards(
        text,
        meta,
        patch_plan=patch_plan,
        source_path=(None if getattr(meta, "nested_components", None) else source_path),
342
343
344
345
346
347
348
349
350
        patch_plan=patch_plan,
        source_path=(None if getattr(meta, "nested_components", None) else source_path),
    )
    text = _lower_forward_boundaries(text, meta, module_name)
    _verify_recorded_patch_materialization(text, meta, patch_plan=patch_plan)
    return _banner(meta) + text


def _verify_recorded_patch_materialization(
364
365
366
367
368
369
370
371
372
    wrapper_records = (
        getattr(patches, "inner_wrappers", ()) if patches is not None else ()
    )
    if not local_records and not replacement_records and not wrapper_records:
        return
    tree = ast.parse(text)
    classes = _class_index(tree)
    materialized = getattr(meta, "materialized_patches", None)
    if isinstance(materialized, list):
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
                "local_compute",
                "bound_method_toggle_forward",
            )
            continue
        host = classes.get(class_name)
        if host is None:
            continue
        valid = {"_forward_impl", "forward"} <= _class_methods(
            host
        ) and "ep_enable" in _class_state_names(host)
        if valid:
            _record_materialized(
                materialized,
                record.module_fqn,
                class_name,
                "local_compute",
458
459
460
461
462
463
464
465
466
                "local_compute",
                "same_class_toggle_forward",
            )
        else:
            missing.append(f"{record.module_fqn} ({class_name})")
    return missing


def _verify_replacement_records(
515
516
517
518
519
520
521
522
523
        and "cp_enable" in _class_state_names(host)
        and _class_dispatch_reads_state(host, "cp_enable")
    ):
        return "same_class_toggle_forward"
    subclass = next(
        (
            node
            for node in classes.values()
            if any(
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
            and "forward" in _class_methods(node)
        ),
        None,
    )
    if subclass is not None:
        return "subclass_forward"
    target_type = getattr(record, "target_type", None)
    replacement_backed = any(
        item.module_fqn == record.module_fqn and item.replacement_type is target_type
        for item in replacements
    )
    if replacement_backed and {"_forward_impl", "forward"} <= _class_methods(host):
        return "replacement_forward_runtime_binding"
    return None


def _verify_wrapper_records(
    classes: dict[str, ast.ClassDef], records: Any, replacements: Any, materialized: Any
548
549
550
551
552
553
554
555
556
    for record in records:
        _, host_name, target_fqn = _wrapper_identity(record)
        host = classes.get(host_name)
        if host is None:
            continue
        source_form = _wrapper_source_form(classes, host, record, replacements)
        if source_form:
            _record_materialized(
                materialized, target_fqn, host_name, "inner_wrapper", source_form
555
556
557
558
559
560
561
562
563
            _record_materialized(
                materialized, target_fqn, host_name, "inner_wrapper", source_form
            )
        else:
            missing.append(f"{target_fqn} (inner wrapper for {host_name})")
    return missing


def _call_name(node: ast.AST) -> str | None:
563
564
565
566
567
568
569
570
571
572
573
def _call_name(node: ast.AST) -> str | None:
    """Return the terminal name of a constructor call expression."""
    if isinstance(node, ast.Name):
        return node.id
    if isinstance(node, ast.Attribute):
        return node.attr
    return None


def verify_recorded_patch_bundle(
    files: dict[str, str],
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
    *,
    patch_plan: Any = None,
) -> None:
    """Verify recorded local-compute patches across all generated source units."""
    records = (
        getattr(patch_plan, "local_computes", ()) if patch_plan is not None else ()
    )
    wrappers = (
        getattr(patch_plan, "inner_wrappers", ()) if patch_plan is not None else ()
    )
    trees = {
        name: ast.parse(text) for name, text in files.items() if name.endswith(".py")
    }
    missing = [
        f"{record.module_fqn} ({record.module_type.__name__})"
        for record in records
        if not any(_tree_has_local_record(tree, record) for tree in trees.values())
    ]
    if missing:
        raise RuntimeError(
            "codegen: recorded local-compute patches were not materialized "
            "in their owning source units: " + ", ".join(missing)
        )
    replacements = getattr(patch_plan, "module_replacements", ())
    missing_wrappers = [
        f"{record.module_fqn} ({_wrapper_identity(record)[1]})"
        for record in wrappers
        if not any(
            _tree_has_wrapper_record(tree, record, replacements)
602
603
604
605
606
607
608
609
610
611
612
613
614
615
            _tree_has_wrapper_record(tree, record, replacements)
            for tree in trees.values()
        )
    ]
    if missing_wrappers:
        raise RuntimeError(
            "codegen: recorded inner-wrapper patches were not materialized "
            "in their owning source units: " + ", ".join(missing_wrappers)
        )
    if any("HPCodegen" in text for text in files.values()):
        raise RuntimeError(
            "codegen: generated bundle contains forbidden HPCodegen class names"
        )

615
616
617
618
619
620
621
622
623
624
625
626


def _tree_has_local_record(tree: ast.AST, record: Any) -> bool:
    """Return whether one source tree materializes a local-compute record."""
    if _bound_function_patch_materialized(tree, record):
        return True
    host = _class_index(tree).get(record.module_type.__name__)
    return (
        host is not None
        and {"_forward_impl", "forward"} <= _class_methods(host)
        and "ep_enable" in _class_state_names(host)
    )
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648


def _tree_has_wrapper_record(tree: ast.AST, record: Any, replacements: Any) -> bool:
    """Return whether one source tree materializes an inner-wrapper record."""
    _, class_name, _ = _wrapper_identity(record)
    host = _class_index(tree).get(class_name)
    if host is None or "forward" not in _class_methods(host):
        return False
    if "cp_enable" in _class_state_names(host) and _class_dispatch_reads_state(
        host, "cp_enable"
    ):
        return True
    target_type = getattr(record, "target_type", None)
    replacement_backed = any(
        item.module_fqn == record.module_fqn and item.replacement_type is target_type
        for item in replacements
    )
    return replacement_backed and {"_forward_impl", "forward"} <= _class_methods(host)


def _class_dispatch_reads_state(host: ast.ClassDef, state_name: str) -> bool:
    """Return whether a class dispatches on one state flag in either layer."""
665
666
667
668
669
670
671
672
673
def _bound_function_patch_materialized(tree: ast.AST, record: Any) -> bool:
    """Return whether a ``MethodType`` forward has an explicit EP toggle."""
    function_name = getattr(record.original_forward, "__name__", "")
    if not function_name:
        return False
    impl_name = f"{function_name}_hp_impl"
    functions = {
        node.name: node
        for node in getattr(tree, "body", ())
674
675
676
677
678
679
680
681
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
    }
    wrapper = functions.get(function_name)
    if wrapper is None or impl_name not in functions:
        return False
    return _function_reads_ep_toggle(wrapper) and _tree_binds_method_impl(
        tree, impl_name
    )
719
720
721
722
723
724
725
726
727

    from hyper_parallel.codegen.inline import render_inline_modeling

    source = getattr(meta, "source", None)
    architecture = (
        source.get("architecture")
        if isinstance(source, dict)
        else getattr(source, "architecture", None)
    )
725
726
727
728
729
730
731
732
733
        if isinstance(source, dict)
        else getattr(source, "architecture", None)
    )
    model_type = getattr(meta, "model_class", None) or architecture
    return render_inline_modeling(
        text,
        meta,
        model_type=model_type,
        patch_plan=patch_plan,
755
756
757
758
759
760
761
762
763
    behavior (params sharded by the native Phase A reuse, no forward rewrite).
    When the map is absent, the source remains untouched and runtime dispatch
    handles the boundaries.
    """
    from hyper_parallel.codegen.emit.parallel import lower_forward_boundaries

    boundary_classes = getattr(meta, "boundary_classes", None) or {}
    if not boundary_classes:
        return text
hyper_parallel/codegen/emit/patches.py
74
75
76
77
78
79
80
81
82
83
84
85


def emission_patches_from_meta(meta: Any) -> Optional[EmissionPatchSet]:
    """Rehydrate emitter views from JSON-safe snapshot metadata."""
    data = getattr(meta, "emission_patches", None)
    if not data:
        return None
    replacements = tuple(
        ModuleReplacementPatch(
            module_fqn=item["module_fqn"],
            source_type=_resolve_symbol(item["source_type"]),
            replacement_type=_resolve_symbol(item["replacement_type"]),
85
86
87
88
89
90
91
92
93
            replacement_type=_resolve_symbol(item["replacement_type"]),
        )
        for item in data.get("module_replacements", ())
    )
    local_computes = tuple(
        LocalComputePatch(
            module_fqn=item["module_fqn"],
            module_type=_resolve_symbol(item["module_type"]),
            factory=_resolve_symbol(item["factory"]),
 98
 99
100
101
102
103
104
105
106
            installed_forward=None,
        )
        for item in data.get("local_computes", ())
    )
    inner_wrappers = tuple(
        InnerWrapperPatch(
            module_fqn=item["module_fqn"],
            target_fqn=item["target_fqn"],
            wrapper=_resolve_symbol(item["wrapper"]),
108
109
110
111
112
113
114
115
116
            target_type=_resolve_symbol(item["target_type"]),
        )
        for item in data.get("inner_wrappers", ())
    )
    return EmissionPatchSet(replacements, local_computes, inner_wrappers)


def local_compute_binding_name(target: Any) -> str:
    """Return the explicit instance attribute used for one compute factory."""
116
117
118
119
120
121
122
123
124
125
126
127
128
129
    """Return the explicit instance attribute used for one compute factory."""
    if isinstance(target, Mapping):
        target = target.get("_target_") or target.get("target") or target.get("name")
    else:
        target = getattr(target, "_target_", target)
    if isinstance(target, str):
        name = target.rsplit(":", 1)[-1].rsplit(".", 1)[-1]
    else:
        name = getattr(target, "__name__", "")
    if not name or not name.isidentifier() or keyword.iskeyword(name):
        raise ValueError(
            f"codegen: local-compute target {target!r} has no valid binding name"
        )
    return name
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    return name


def _resolve_symbol(path: str) -> Any:
    module_name, separator, qualname = path.partition(":")
    if not separator:
        raise ValueError(f"codegen: invalid patch symbol path {path!r}")
    value = importlib.import_module(module_name)
    for segment in qualname.split("."):
        value = getattr(value, segment)
    return value


__all__ = ["EmissionPatchSet", "emission_patches_from_meta", "local_compute_binding_name"]
hyper_parallel/codegen/emit/recorded.py
65
66
67
68
69
70
71
72
73
    for record in records:
        if source_path is not None and not _record_belongs_to_source(
            record, source_path
        ):
            continue
        original = _unbound(record.original_forward)
        groups[(record.module_type, _source_function_name(original))].append(record)

    rendered = source_text
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
        groups.items(), key=lambda item: (item[0][0].__name__, item[0][1])
    ):
        _require_one_contract(group, meta)
        if source_function and _has_module_function(rendered, source_function):
            rendered = _materialize_bound_module_function(
                rendered, source_function, group[0], meta
            )
            materialized = True
            continue
        if not _has_source_class(rendered, host_type.__name__):
            continue
        rendered = _materialize_source_class(
            rendered, host_type.__name__, group[0], meta
        )
        materialized = True
106
107
108
109
110
111
112
113
114
        local = injection.get("local_compute_fn")
        module_fqn = injection.get("match")
        class_name = boundary_classes.get(module_fqn)
        if local is None or not module_fqn or class_name not in source_classes:
            continue
        grouped[class_name].append(SimpleNamespace(
            module_fqn=module_fqn,
            factory=_callable_identity(local),
        ))
143
144
145
146
147
148
149
150
    param_plan = getattr(meta, "param_plan", None) or {}
    boundary_classes = getattr(meta, "boundary_classes", None) or {}
    for module_fqn, owner_class in boundary_classes.items():
        if owner_class != class_name:
            continue
        entry = param_plan.get(module_fqn)
        if isinstance(entry, dict) and entry.get("is_boundary"):
            entry["skip_source_lowering"] = True
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def _callable_identity(value: Any) -> str:
    """Return a stable identity for a frozen callable declaration."""
    if isinstance(value, dict):
        return str(value.get("_target_") or value.get("target") or value.get("name"))
    return str(value)


def _record_belongs_to_source(record: Any, source_path: str) -> bool:
    """Return whether a recorded host is defined by this source unit."""
    candidates = (
        inspect.getsourcefile(record.module_type),
        inspect.getsourcefile(_unbound(record.original_forward)),
    )
    expected = os.path.normcase(os.path.abspath(source_path))
    return any(
        candidate is not None
        and os.path.normcase(os.path.abspath(candidate)) == expected
        for candidate in candidates
    )
236
237
238
239
240
241
242
243
244
        for record in records
    }
    factories = {record.factory for record in records}
    if len(contracts) != 1 or len(factories) != 1:
        fqns = ", ".join(sorted(record.module_fqn for record in records))
        raise RuntimeError(
            "codegen: recorded modules sharing one forward have incompatible "
            f"patch contracts: {fqns}"
        )
246
247
248
249
250
251
252
253

def _entry_for_record(meta: Any, record: Any) -> dict[str, Any]:
    entry = (getattr(meta, "param_plan", None) or {}).get(record.module_fqn)
    if entry is None:
        raise RuntimeError(
            f"codegen: recorded patch {record.module_fqn!r} has no frozen plan entry"
        )
    return entry
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
def _injection_for_record(meta: Any, record: Any) -> dict[str, Any] | None:
    for injection in getattr(meta, "injections", None) or ():
        if injection.get("match") == record.module_fqn:
            return injection
    return None


def _function_info(node: ast.FunctionDef | ast.AsyncFunctionDef, source_text: str) -> FunctionInfo:
    """Build source-index information for one recorded function."""
    lines = source_text.splitlines(keepends=True)
    offsets = [0]
    for line in lines:
        offsets.append(offsets[-1] + len(line))

    def start(line_number: int) -> int:
        return offsets[line_number - 1]

    positional = [arg.arg for arg in (*node.args.posonlyargs, *node.args.args)]
    if positional and positional[0] in ("self", "module"):
        positional.pop(0)
    first_line = min(
        [node.lineno, *(item.lineno for item in node.decorator_list)]
    )
    return FunctionInfo(
        name=node.name,
        body_start=start(node.body[0].lineno),
        body_end=offsets[node.end_lineno],
        def_offset=start(first_line),
306
307
308
309
310
311
312
313
314
            _render_output_redistribute(),
            form,
        )
    else:
        body = _build_forward_body(source_text, injection, func, form, emitted)
    fallback = _render_forward_call(func).replace("outputs =", "return", 1)
    return "\n".join([
        "        if self.ep_enable:",
        textwrap.indent(body, "    "),
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
    record: Any,
    meta: Any,
) -> str:
    """Turn an instance-bound module function into impl + explicit wrapper."""
    tree = ast.parse(source_text)
    node = next(
        item for item in tree.body
        if isinstance(item, (ast.FunctionDef, ast.AsyncFunctionDef))
        and item.name == function_name
    )
    info = _function_info(node, source_text)
    impl_name = f"{function_name}_hp_impl"
    original = source_text[info.def_offset:info.body_end]
    original = original.replace(f"def {function_name}(", f"def {impl_name}(", 1)
    if not original.endswith("\n"):
        original += "\n"
    body = textwrap.dedent(_recorded_body(source_text, info, record, meta))
    body_edit = TextEdit(info.body_start, info.body_end, textwrap.indent(body, "    "))
    rendered = apply_edits(
        source_text,
        [TextEdit(info.def_offset, info.def_offset, original + "\n"), body_edit],
    )
    return _bind_module_impl(rendered, function_name, impl_name)


def _materialize_source_class(
    source_text: str,
353
354
355
356
357
358
359
360
361
) -> str:
    """Rewrite a source-defined host even when old meta normalization skips it."""
    func = build_source_index(source_text).find_forward(class_name)
    if func is None:
        raise RuntimeError(
            f"codegen: recorded source host {class_name!r} defines no forward"
        )
    body = _recorded_body(source_text, func, record, meta)
    impl = _build_forward_impl_edit(
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389


def _bind_module_impl(source_text: str, wrapper_name: str, impl_name: str) -> str:
    """Add the instance ``_forward_impl`` binding beside MethodType(forward)."""
    tree = ast.parse(source_text)
    lines = source_text.splitlines(keepends=True)
    offsets = [0]
    for line in lines:
        offsets.append(offsets[-1] + len(line))
    edits: list[TextEdit] = []
    for node in ast.walk(tree):
        if not isinstance(node, ast.Assign) or len(node.targets) != 1:
            continue
        target = node.targets[0]
        value = node.value
        if not (
            isinstance(target, ast.Attribute)
            and target.attr == "forward"
            and isinstance(value, ast.Call)
            and isinstance(value.func, ast.Name)
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
            and value.args
            and isinstance(value.args[0], ast.Name)
            and value.args[0].id == wrapper_name
        ):
            continue
        owner = ast.unparse(target.value)
        indent = " " * node.col_offset
        binding = f"{indent}{owner}._forward_impl = MethodType({impl_name}, {owner})\n"
        edits.append(TextEdit(offsets[node.lineno - 1], offsets[node.lineno - 1], binding))
    if not edits:
        raise RuntimeError(
            f"codegen: source function {wrapper_name!r} is not installed with MethodType"
        )
    return apply_edits(source_text, edits)


__all__ = ["materialize_recorded_forwards"]
hyper_parallel/codegen/emit/replacement.py
25
26
27
28
29
30
31
32
33
    never recompiles rules or inspects a live model.
    """
    payload = snapshot.to_dict() if hasattr(snapshot, "to_dict") else snapshot
    if not isinstance(payload, dict):
        raise TypeError("replacement snapshot must be a CodegenSnapshot or dict")
    replacements = payload.get("replacements", {})
    declarations = replacements.get("declarations", ())
    applications = replacements.get("applications", ())
    declarations_by_id = {item["rule_id"]: item for item in declarations}
31
32
33
34
35
36
37
38
39
    declarations = replacements.get("declarations", ())
    applications = replacements.get("applications", ())
    declarations_by_id = {item["rule_id"]: item for item in declarations}
    if len(declarations_by_id) != len(declarations):
        raise ValueError("replacement snapshot contains duplicate rule_id values")
    records = []
    for application in applications:
        rule_id = application.get("rule_id")
        declaration = declarations_by_id.get(rule_id)
37
38
39
40
41
42
43
44
45
46
47
48
49
50
    for application in applications:
        rule_id = application.get("rule_id")
        declaration = declarations_by_id.get(rule_id)
        if declaration is None:
            raise ValueError(
                f"replacement application references unknown rule_id {rule_id!r}"
            )
        source_identity = application.get("source_type") or declaration.get("source_type")
        if not isinstance(source_identity, str) or not source_identity:
            raise ValueError(
                f"replacement application {rule_id!r} has no resolved source_type"
            )
        source_type = source_identity.replace(":", ".", 1)
        record = {
hyper_parallel/codegen/hash.py
48
49
50
51
52
53
54
55
56
def canonical_snapshot_payload(snapshot: Any) -> str:
    """Serialize the stable identity projection of a build snapshot."""
    signature_payload = getattr(snapshot, "signature_payload", None)
    if not callable(signature_payload):
        raise TypeError("snapshot must provide signature_payload()")
    return canonical_json(signature_payload())


def signature_from_snapshot(snapshot: Any, *, prefix: int = 12) -> str:
hyper_parallel/codegen/inline/framework_spec.py
143
144
145
146
147
148
149
150
151
    except ImportError:
        return None
    component = getattr(module, attr, None)
    if not isinstance(component, type):
        return None
    if (
        target.startswith(_COMPONENTS_PREFIX)
        or getattr(component, "_hp_module_replacement", False)
    ):
149
150
151
152
153
154
155
156
157
        target.startswith(_COMPONENTS_PREFIX)
        or getattr(component, "_hp_module_replacement", False)
    ):
        return component
    return None


def _component_replacement_target(component: type) -> ReplacementTarget | None:
    """Read a wrap-style component's own constructor as its replacement target.
256
257
258
259
260
261
262
263
264
265
266
267
268
269
        [] if target.interface else [ImportPatch(target.module, (target.component,))]
    )
    snippets: tuple[ModuleSnippetPatch, ...] = ()
    if target.interface:
        provider = _family_provider(model_type, "codegen")
        renderer = getattr(provider, "render_replacement_source", None)
        if not callable(renderer):
            return None
        render_source = cast(Callable[..., Any], renderer)
        expanded = render_source(  # pylint: disable=not-callable
            component, interface=_interface_function(factory, target)
        )
        imports.extend(
            ImportPatch(module="", names=(), raw=line) for line in expanded.imports
309
310
311
312
313
314
315
316
317
318
    if target is None:
        return None
    if _direct_component_class(target) is not None:
        return _component_replacement_spec(target, model_type, module_type=module_type)
    if not adapter_path_parts(target):
        return None
    model_type = _family_key(model_type, target)
    factory = _factory_function(target, model_type)
    if factory is None:
        return None
337
338
339
340
341
342
343
344
345
    needs no codegen declaration.  A factory with no constructor call to sink --
    or a rule with no ``module_type`` naming the source class it replaces -- has
    no spec, and the rule is left to the native path.
    """
    del target
    # The source class the constructor call replaces: without the rule's
    # ``module_type`` there is no call site to rewrite, and guessing one would
    # silently target the wrong class.
    old_ctor = class_name_of(module_type)
347
348
349
350
351
352
353
354
355
        return None
    replacement = replacement_target(factory)
    if replacement is None:
        return None
    return _build_replacement_spec(factory, replacement, old_ctor, model_type)


def _component_replacement_spec(
    target: str, model_type: str | None, *, module_type: str | None
406
407
408
409
410
411
412
413
414
def _resolve_strategy_spec(
    target: str, model_type: str | None, inner_wrapper: bool
) -> StrategySpec | None:
    if inner_wrapper and adapter_path_parts(target):
        return _cp_strategy_spec(target)
    return None


def _cp_strategy_spec(target: str) -> StrategySpec:
430
431
432
433
434
435
436
437
438
    strategy (imports only), preserving the runtime wrapper path.
    """
    resolved = inner_wrapper_target(target)
    if resolved is None:
        return StrategySpec(kind=CP_ATTENTION_KIND, imports=())
    if resolved.inline_body is not None:
        return StrategySpec(
            kind=CP_ATTENTION_KIND,
            subclass_shell=resolved.inline_body,
437
438
439
440
441
442
443
444
445
            kind=CP_ATTENTION_KIND,
            subclass_shell=resolved.inline_body,
            imports=(),
        )
    from hyper_parallel.codegen.inline.templates import (  # pylint: disable=C0415
        cp_dispatch_shell_body,
    )

    return StrategySpec(
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
    """
    replacement_specs: dict[str, Any] = {}
    strategy_specs: dict[str, Any] = {}
    for entry in overrides or ():
        replace_target = _target_path(entry.get("replace_module"))
        if replace_target is not None:
            spec = replacement_spec_for(
                replace_target, model_type, module_type=entry.get("module_type")
            )
            replacement_specs[replace_target] = asdict(spec) if spec is not None else None
        local_target = _target_path(entry.get("local_compute_fn"))
        if local_target is not None:
            spec = strategy_spec_for(local_target, model_type)
            strategy_specs[local_target] = asdict(spec) if spec is not None else None
        inner_target = _target_path(entry.get("inner_wrapper"))
        if inner_target is not None:
            spec = strategy_spec_for(inner_target, model_type, inner_wrapper=True)
            strategy_specs[inner_target] = asdict(spec) if spec is not None else None
    return {"replacement_specs": replacement_specs, "strategy_specs": strategy_specs}


__all__ = [
hyper_parallel/codegen/inline/meta_plan.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
        target = rule.local_compute_target
        if target is None:
            continue
        spec = strategy_spec(target, model_type)
        if spec is None or spec.body_template is None:
            continue
        if spec.strip_boundary_subpatterns:
            strip_patterns = spec.strip_boundary_subpatterns
        if spec.target_class is not None:
            host_classes = {spec.target_class}
        else:
            # The block class is a per-model fact derived from the boundary
            # map, never a registered literal (see build_strategy_patches).
            host_classes = rule_block_classes(rule, boundary_classes)
        if host_classes:
            # Persist the derived classes so a re-emission of this
            # already-normalized meta (whose boundary entries the strip below
            # consumes) can still resolve its patch hosts.
            recorded = set(getattr(meta, "external_state_classes", None) or ())
            meta.external_state_classes = sorted(recorded | host_classes)
        for fqn, cls in boundary_classes.items():
            if cls not in host_classes:
                continue
            if any(fnmatch(fqn, pattern) for pattern in rule.match):
                ep_fqns.add(fqn)
    if not ep_fqns:
        return
    mark_fqns: set[str] = set()
    for ep_fqn in ep_fqns:
hyper_parallel/codegen/inline/patch_engine.py
62
63
64
65
66
67
68
69
70
71
72
    if waves:
        first_pass.extend(_constructor_edits(source_text, waves[0], hits))
    text = apply_edits(source_text, first_pass) if first_pass else source_text
    for wave in waves[1:]:
        wave_edits = _constructor_edits(text, wave, hits)
        if wave_edits:
            text = apply_edits(text, wave_edits)
    deferred_edits = _deferred_replacement_edits(
        text,
        patch_set.constructor_replaces,
        hits,
172
173
174
175
176
177
178
179
180
181
                )
            )
        ]
        if not wave:
            names = sorted({patch.old_ctor for patch in remaining})
            raise ValueError(
                f"codegen: constructor replacement dependency cycle among {names}"
            )
        chosen = {id(patch) for patch in wave}
        remaining = [patch for patch in remaining if id(patch) not in chosen]
313
314
315
316
317
318
319
320
321
322
323
324
325
    offsets = _line_offsets(source_text)
    insertions: dict[int, list[str]] = defaultdict(list)
    for patch in pending:
        if patch.mode != "wrap_source":
            continue
        root_attr = patch.scope_fqns[0].split(".", 1)[0]
        constructors = _root_constructors(tree, root_attr)
        if len(constructors) != 1:
            continue
        function = constructors[0]
        _, end = _node_span(function.body[-1], offsets)
        insertions[end].append(_render_deferred_replacement(patch))
        hits[patch.old_ctor] += 1
336
337
338
339
340
341
342
343
344
        if not isinstance(node, ast.ClassDef):
            continue
        for child in node.body:
            if not isinstance(child, ast.FunctionDef) or child.name != "__init__":
                continue
            if any(
                isinstance(target, ast.Attribute)
                and isinstance(target.value, ast.Name)
                and target.value.id == "self"
574
575
576
577
578
579
580
581
582
583
584
585
586
587
    """

    if _HIDDEN_ARG_TOKEN not in body:
        return body
    if not func.param_names:
        raise RuntimeError(
            f"codegen: inline strategy body references {_HIDDEN_ARG_TOKEN!r} "
            "but the target method has no positional parameter to bind it to"
        )
    return body.replace(_HIDDEN_ARG_TOKEN, func.param_names[0])


def _bind_forward_args(body: str, func: "FunctionInfo") -> str:
    """Bind a dispatch shell's argument token to the original signature."""
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
def _bind_forward_args(body: str, func: "FunctionInfo") -> str:
    """Bind a dispatch shell's argument token to the original signature."""
    token = "__hp_forward_args__"
    if token not in body:
        return body
    args = list(func.param_names)
    if func.vararg_name:
        args.append(f"*{func.vararg_name}")
    args.extend(f"{name}={name}" for name in func.kwonly_names)
    if func.kwarg_name:
        args.append(f"**{func.kwarg_name}")
    return body.replace(token, ", ".join(args))


def _forward_extract_edits(
629
630
631
632
633
634
635
636
637
        prefix = "\n".join(state_lines) + "\n\n" if state_lines else ""
        if patch.merge_original_body:
            fallback = _forward_impl_fallback(func)
            if fallback not in body:
                raise RuntimeError(
                    f"codegen: merged strategy for {patch.class_name}."
                    f"{patch.method_name} has no original-forward fallback"
                )
            dispatch = body.replace(fallback, "", 1).rstrip()
657
658
659
660
661
662
663
664
665
666
667
668
def _forward_impl_fallback(func: FunctionInfo) -> str:
    """Render the dispatch-shell fallback that calls the extracted method."""
    args = list(func.param_names)
    if func.vararg_name:
        args.append(f"*{func.vararg_name}")
    args.extend(f"{name}={name}" for name in func.kwonly_names)
    if func.kwarg_name:
        args.append(f"**{func.kwarg_name}")
    return f"return self._forward_impl({', '.join(args)})"


def _call_name(node: ast.AST) -> str | None:
hyper_parallel/codegen/inline/pipeline.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

    rules = collect_inline_rules(meta)
    if not rules:
        return source_text
    patches = patch_plan
    recorded_local_compute = bool(
        getattr(patches, "local_computes", ()) if patches is not None else ()
    )
    strategy_rules = (
        tuple(replace(rule, local_compute_target=None) for rule in rules)
        if recorded_local_compute
        else rules
    )
    _require_inline_coverage(strategy_rules, model_type)
    replacement_patches = build_replacement_patches(rules, model_type)
    strategy_patches = build_strategy_patches(
        strategy_rules,
        model_type,
        _observed_boundary_classes(meta, patch_plan),
        getattr(meta, "external_state_classes", None),
78
79
80
81
82
83
84
85
86
87
        _observed_boundary_classes(meta, patch_plan),
        getattr(meta, "external_state_classes", None),
    )
    patch_set = _merge_patch_sets(replacement_patches, strategy_patches)
    _add_recorded_forward_host_imports(source_text, patch_set, patch_plan)
    _materialize_imported_forward_hosts(source_text, patch_set)
    rendered = apply_patch_set(source_text, patch_set)
    # The copied modeling source brings its own decorated helpers that share
    # names with the library functions the artifact imports, and a local
    # definition wins over the import: the native path calls the library
 92
 93
 94
 95
 96
 97
 98
 99
100
    # on purpose) keep their definitions.
    rendered = drop_shadowed_definitions(
        rendered, _library_import_names(rendered) & _decorated_names(source_text)
    )
    normalize_inline_meta(meta, strategy_rules, model_type)
    return rendered


def _add_recorded_forward_host_imports(
131
132
133
134
135
136
137
138
139
140
141
142
        for record in replacements
    }
    for patch in patch_set.forward_extracts:
        if patch.class_name in source_classes or patch.class_name in imported_names:
            continue
        replacement_type = replacement_types.get(patch.class_name)
        if replacement_type is None:
            continue
        patch_set.imports.append(
            ImportPatch(replacement_type.__module__, (replacement_type.__name__,))
        )
        imported_names.add(patch.class_name)
152
153
154
155
156
157
158
159
160
    )
    for record in wrappers:
        target_type = getattr(record, "target_type", None)
        if target_type is None:
            continue
        target_fqn = (
            record.module_fqn
            if record.target_fqn == "self"
            else f"{record.module_fqn}.{record.target_fqn}"
175
176
177
178
179
180
181
182
183
184
    remaining = []
    rendered: set[str] = set()
    for patch in patch_set.forward_extracts:
        if patch.class_name in source_classes:
            remaining.append(patch)
            continue
        import_index = next(
            (
                index
                for index, item in enumerate(patch_set.imports)
186
187
188
189
190
191
192
193
194
195
196
197
            ),
            None,
        )
        if import_index is None:
            remaining.append(patch)
            continue
        if patch.class_name in rendered:
            continue
        rendered.add(patch.class_name)
        imported = patch_set.imports[import_index]
        other_names = tuple(name for name in imported.names if name != patch.class_name)
        alias = f"_{patch.class_name}Base"
196
197
198
199
200
201
202
203
204
        other_names = tuple(name for name in imported.names if name != patch.class_name)
        alias = f"_{patch.class_name}Base"
        replacement_imports = []
        if other_names:
            replacement_imports.append(ImportPatch(imported.module, other_names))
        replacement_imports.append(ImportPatch(
            module="",
            names=(),
            raw=f"from {imported.module} import {patch.class_name} as {alias}",
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    *,
    patch_plan: Any = None,
) -> str:
    """Render only strategy forwards owned by one sibling source unit."""
    rules = collect_inline_rules(meta)
    if not rules:
        return source_text
    recorded_local_compute = bool(
        getattr(patch_plan, "local_computes", ())
        if patch_plan is not None
        else ()
    )
    strategy_rules = (
        tuple(replace(rule, local_compute_target=None) for rule in rules)
        if recorded_local_compute
        else rules
    )
    _require_inline_coverage(strategy_rules, model_type)
    patches = build_strategy_patches(
        strategy_rules,
        model_type,
        _observed_boundary_classes(meta, patch_plan),
        getattr(meta, "external_state_classes", None),
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
        model_type,
        _observed_boundary_classes(meta, patch_plan),
        getattr(meta, "external_state_classes", None),
    )
    source_classes = {
        node.name
        for node in ast.parse(source_text).body
        if isinstance(node, ast.ClassDef)
    }
    patches.forward_extracts = [
        patch for patch in patches.forward_extracts
        if patch.class_name in source_classes
    ]
    if not patches.forward_extracts:
        return source_text
    patches.module_snippets.clear()
    patches.constructor_replaces.clear()
    patches.class_removals.clear()
    return apply_patch_set(source_text, patches)


def _library_import_names(text: str) -> set[str]:
    """Names the artifact imports from the library, i.e. the winning bindings.
hyper_parallel/codegen/inline/recognition.py
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

def inner_wrapper_target(factory_path: str | None) -> InnerWrapperTarget | None:
    """Recover an inner wrapper's emitted helper contract from its source."""
    if not factory_path:
        return None
    module_name, _, factory_name = factory_path.rpartition(".")
    if not module_name or not factory_name:
        return None
    tree = _module_source_tree(module_name)
    if tree is None:
        return None
    factory_node = next(
        (
            node
            for node in tree.body
228
229
230
231
232
233
234
235
236
        ),
        None,
    )
    if factory_node is None:
        return None
    request_owner = _request_owner(factory_node, tree)
    replacement_name = (
        _rewrite_request_callable(request_owner)
        if request_owner is not None
248
249
250
251
252
253
254
255
256
    }
    if not helper_name or helper_name not in module_functions:
        inline_body = _nested_forward_body(request_owner, replacement_name)
        if inline_body is None:
            return None
        return InnerWrapperTarget(inline_body=inline_body)
    return InnerWrapperTarget(
        helper_module=module_name,
        helper_name=helper_name,
270
271
272
273
274
275
276
277
278
279
280
281
282
    for node in ast.walk(factory_node):
        if not isinstance(node, ast.Return) or not isinstance(node.value, ast.Call):
            continue
        if not isinstance(node.value.func, ast.Name):
            continue
        delegate = functions.get(node.value.func.id)
        if delegate is not None and _rewrite_request_callable(delegate) is not None:
            return delegate
    return None


def _module_source_tree(module_name: str) -> ast.Module | None:
    """Load a module's source AST without importing optional accelerator deps."""
287
288
289
290
291
292
293
294
295
296
297
            continue
        try:
            with open(path, "r", encoding="utf-8") as handle:
                return ast.parse(handle.read())
        except (OSError, SyntaxError, UnicodeError):
            return None
    return None


def _rewrite_request_callable(tree: ast.AST) -> str | None:
    """Return the replacement callable passed to ``_ForwardRewriteRequest``."""
312
313
314
315
316
317
318
319
320
        for child in ast.walk(node):
            if isinstance(child, ast.Return) and isinstance(child.value, ast.Call):
                if isinstance(child.value.func, ast.Name):
                    return child.value.func.id
    return None


def _cp_mesh_companion_attr(tree: ast.AST) -> str | None:
    """Return the companion attribute whose value is the wrapper's CP mesh."""
321
322
323
324
325
326
327
328
329
    for node in ast.walk(tree):
        if not isinstance(node, ast.keyword) or node.arg != "companion_attrs":
            continue
        if not isinstance(node.value, ast.Dict):
            continue
        for key, value in zip(node.value.keys, node.value.values):
            if (
                isinstance(key, ast.Constant)
                and isinstance(key.value, str)
329
330
331
332
333
334
335
336
337
                and isinstance(key.value, str)
                and isinstance(value, ast.Name)
                and value.id == "cp_mesh"
            ):
                return key.value
    return None


def _nested_forward_body(tree: ast.AST, replacement_name: str | None) -> str | None:
344
345
346
347
348
349
350
351
352
    state reads with instance attributes and the saved original forward with
    ``super().forward``; the imported-host materializer supplies the subclass.
    """
    if not replacement_name:
        return None
    forward = next(
        (
            node
            for node in ast.walk(tree)
355
356
357
358
359
360
361
362
363
364
365
366
        ),
        None,
    )
    if forward is None:
        return None
    companion_attrs = _companion_attr_bindings(tree)
    original_forward = _original_forward_binding(tree)
    if original_forward is None:
        return None

    class ClosureBindings(ast.NodeTransformer):
        """Rewrite captured closure bindings to generated-instance state."""
419
420
421
422
423
424
425
426
427
    for node in ast.walk(tree):
        if not isinstance(node, ast.keyword) or node.arg != "companion_attrs":
            continue
        if not isinstance(node.value, ast.Dict):
            continue
        for key, value in zip(node.value.keys, node.value.values):
            if (
                isinstance(key, ast.Constant)
                and isinstance(key.value, str)
hyper_parallel/codegen/inline/replacement_pass.py
56
57
58
59
60
61
62
63
64
    """

    patch_set = InlinePatchSet()
    scopes_by_target: dict[str, set[str]] = defaultdict(set)
    fqns_by_target: dict[str, set[str]] = defaultdict(set)
    specs_by_target: dict[str, Any] = {}
    for rule in rules:
        target = rule.replace_target
        if target is None:
67
68
69
70
71
72
73
74
75
        if spec is None:
            continue
        specs_by_target.setdefault(target, spec)
        scopes_by_target[target].update(_scope_attrs(rule))
        fqns_by_target[target].update(fqn for fqn in rule.match if fqn)
    for target, spec in specs_by_target.items():
        scope_attrs = tuple(sorted(scopes_by_target[target]))
        if not scope_attrs:
            logger.warning(
hyper_parallel/codegen/inline/spec_bundle.py
63
64
65
66
67
68
69
70
71

    def __post_init__(self) -> None:
        """Require a complete method patch or an imports-only declaration."""
        if self.target_class is not None and self.body_template is None:
            raise ValueError("Inline strategy target_class requires a body_template")
        if self.target_class is not None and (not self.target_class or not self.body_template.strip()):
            raise ValueError("Inline strategy class and body must be nonempty")
        if not self.method_name.isidentifier():
            raise ValueError("Inline strategy method_name must be a Python identifier")
70
71
72
73
74
75
76
77
78
79
80
81
82
83
        if not self.method_name.isidentifier():
            raise ValueError("Inline strategy method_name must be a Python identifier")
        if self.subclass_shell is not None:
            if self.target_class is not None or self.body_template is not None:
                raise ValueError(
                    "Inline strategy subclass_shell is exclusive with "
                    "target_class and body_template"
                )
            if not self.subclass_shell.strip():
                raise ValueError("Inline strategy subclass shell must be nonempty")


__all__ = [
    "ReplacementSpec",
hyper_parallel/codegen/inline/strategy_pass.py
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
                    patch_set, spec, rule, target, model_type,
                    boundary_classes, subclassed,
                )
                continue
            if spec.body_template is None:
                continue
            if spec.target_class is not None:
                host_classes = {spec.target_class}
            else:
                host_classes = rule_block_classes(rule, boundary_classes)
                if not host_classes:
                    # Re-emission of an already-normalized meta: the boundary
                    # entries the first pass stripped are gone, but the pass
                    # persisted the derived classes in
                    # ``meta.external_state_classes`` — the surviving record of
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
                    # which classes an inline body replaced. (Today the EP
                    # shell is the only body-bearing strategy, so the whole
                    # record is this rule's host set; a second body-bearing
                    # strategy would need a kind filter here.)
                    host_classes = set(external_state_classes or ())
                if not host_classes:
                    raise _unmaterialized_strategy_error(
                        spec.kind, target, rule, model_type
                    )
            for host_class in sorted(host_classes):
                key = (host_class, spec.method_name)
                if key in emitted:
                    if emitted[key] != spec.body_template:
                        raise ValueError(f"Conflicting inline strategies for {host_class}.{spec.method_name}")
                    continue
                emitted[key] = spec.body_template
                patch_set.forward_extracts.append(
                    ForwardExtractPatch(
                        class_name=host_class,
                        method_name=spec.method_name,
                        body=spec.body_template,
147
148
149
150
151
152
153
154
155
156
157
158
) -> None:
    """Materialize CP dispatch in the original host class exactly once."""
    host_classes = rule_block_classes(rule, boundary_classes)
    if not host_classes:
        raise _unmaterialized_strategy_error(spec.kind, target, rule, model_type)
    helper_names = [name for patch in spec.imports for name in patch.names]
    if len(helper_names) > 1:
        raise ValueError(
            f"codegen: CP strategy {target!r} carries multiple helper "
            f"imports for one subclass shell: {helper_names}"
        )
    for host_class in sorted(host_classes):
156
157
158
159
160
161
162
163
164
            f"imports for one subclass shell: {helper_names}"
        )
    for host_class in sorted(host_classes):
        if host_class in subclassed:
            continue
        subclassed.add(host_class)
        patch_set.forward_extracts.append(
            ForwardExtractPatch(
                class_name=host_class,
172
173
174
175
176
177
178
179
180
def _unmaterialized_strategy_error(
    kind: str, target: str, rule: InlineRule, model_type: str | None
) -> RuntimeError:
    """The error for a declared strategy that selects no boundary module."""
    return RuntimeError(
        f"codegen: {kind} strategy {target!r} matched no boundary "
        f"module (patterns {list(rule.match)}, model_type="
        f"{model_type!r}) — the declared strategy cannot be "
        "materialized; check the match pattern or the plan's "
hyper_parallel/codegen/inline/yaml_rules.py
62
63
64
65
66
67
68
69
70
        and parts[:2] == ["hyper_parallel", "models"]
        and parts[3] == "adapter"
    ):
        return declared
    return record.get("factory")


def _matches(record: dict[str, Any]) -> tuple[str, ...]:
    value = record.get("fqns") or record.get("match") or record.get("fqn")
hyper_parallel/codegen/manager.py
76
77
78
79
80
81
82
83
84
85
86
    Distributed launchers must use a dedicated sidecar instead of invoking
    this function independently on every training rank.
    """
    if not isinstance(snapshot, CodegenSnapshot):
        raise TypeError("snapshot must be a CodegenSnapshot")
    if snapshot.status not in (CodegenStatus.DERIVED, CodegenStatus.NOT_REQUIRED):
        raise ValueError(
            "snapshot-driven generation requires status 'derived' or 'not_required', "
            f"got {snapshot.status.value!r}"
        )
    payload = snapshot.to_dict()
85
86
87
88
89
90
91
92
93
        )
    payload = snapshot.to_dict()
    source = payload["source"]
    if not source.get("file_path"):
        raise ValueError("snapshot source must include a modeling file_path")
    model_type = source.get("model_type")
    public_model_type = artifact_model_type(str(model_type)) if model_type else None
    model_name = (
        _model_type_to_modeling_token(str(public_model_type))
119
120
121
122
123
124
125
126
127

    with artifact_generation_lock(layout, timeout_s=timeout_s):
        existing = load_codegen_meta(layout.meta_path)
        if existing is not None and not should_regenerate(existing, signature):
            return layout
        logger.info(
            "codegen: generating snapshot artifact %s (signature %s)",
            layout.artifact_dir,
            signature,
260
261
262
263
264
265
266
267
268
    )
    source_type = _source_type_identity(source, class_name)
    observed_type = boundary_types.get(module_fqn)
    if source_type is None and _is_remote_boundary_type(observed_type):
        source_type = observed_type
    bound_forward = _bound_forward_identity(source, module_fqn)
    local = _snapshot_local_compute(
        injection,
        source,
304
305
306
307
308
309
310
311
312
313
314
315
316
317
    local_compute = injection.get("local_compute_fn")
    if local_compute is None:
        return None
    if declared_type is None:
        raise ValueError(
            "snapshot local_compute_fn requires a source module and "
            f"boundary class for {module_fqn!r}"
        )
    if source_type is None and bound_forward is None:
        return None
    module_type = (
        (_imported_type_identity(source, class_name) if bound_forward else source_type)
        or source_type
        or declared_type
337
338
339
340
341
342
343
344
345
    if wrapper is None:
        return None
    target_type = replacement_types.get(module_fqn) or source_type or declared_type
    if target_type is None:
        raise ValueError(
            "snapshot inner_wrapper requires an observed replacement or "
            f"boundary class for {module_fqn!r}"
        )
    return {
353
354
355
356
357
358
359
360
361
362
363
364
365
366
def _source_class_names(source: dict[str, Any]) -> set[str]:
    """Return classes defined by the snapshot's modeling source file."""
    file_path = source.get("file_path")
    if not file_path:
        return set()
    try:
        with open(file_path, "r", encoding="utf-8", errors="replace") as handle:
            tree = ast.parse(handle.read(), filename=file_path)
    except (OSError, SyntaxError):
        return set()
    return {node.name for node in tree.body if isinstance(node, ast.ClassDef)}


def _source_type_identity(
367
368
369
370
371
372
373
374
375
376
377
378
    source: dict[str, Any], class_name: Optional[str]
) -> Optional[str]:
    """Resolve a class to the remote source unit that actually defines it."""
    if not class_name:
        return None
    module_name = source.get("module_name")
    if not isinstance(module_name, str) or not module_name:
        return None
    if class_name in _source_class_names(source):
        return f"{module_name}:{class_name}"

    package, separator, _ = module_name.rpartition(".")
379
380
381
382
383
384
385
386
387
388
389
390
391
392
    candidates = []
    for path in resolve_remote_siblings(source).values():
        sibling_source = {"file_path": path}
        if class_name not in _source_class_names(sibling_source):
            continue
        stem = os.path.splitext(os.path.basename(path))[0]
        sibling_module = f"{package}.{stem}" if separator else stem
        candidates.append(f"{sibling_module}:{class_name}")
    if len(candidates) > 1:
        raise ValueError(
            f"snapshot class {class_name!r} is defined by multiple bundled source units: "
            f"{sorted(candidates)}"
        )
    return candidates[0] if candidates else None
403
404
405
406
407
408
409
410
411
412
413
414
415
416
    """
    file_path = source.get("file_path")
    module_name = source.get("module_name")
    if not file_path or not module_name or not module_fqn:
        return None
    try:
        with open(file_path, "r", encoding="utf-8", errors="replace") as handle:
            tree = ast.parse(handle.read(), filename=file_path)
    except (OSError, SyntaxError):
        return None

    boundary_name = module_fqn.rsplit(".", 1)[-1]
    candidates = set()
    for node in ast.walk(tree):
427
428
429
430
431
432
433
434
435
436
437
438
            or _ast_name(call.func) != "MethodType"
            or not call.args
            or not isinstance(call.args[0], ast.Name)
        ):
            continue
        candidates.add(call.args[0].id)
    if len(candidates) > 1:
        raise ValueError(
            f"snapshot boundary {module_fqn!r} has multiple MethodType forwards: "
            f"{sorted(candidates)}"
        )
    return f"{module_name}:{next(iter(candidates))}" if candidates else None
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
) -> Optional[str]:
    """Resolve an imported boundary class from modules referenced by the source."""
    file_path = source.get("file_path")
    if not file_path or not class_name:
        return None
    try:
        with open(file_path, "r", encoding="utf-8", errors="replace") as handle:
            tree = ast.parse(handle.read(), filename=file_path)
    except (OSError, SyntaxError):
        return None

    explicit_modules = _explicit_import_modules(tree, class_name)
    if len(explicit_modules) > 1:
        raise ValueError(
            f"snapshot class {class_name!r} is imported from multiple modules: "
            f"{sorted(explicit_modules)}"
        )
    if explicit_modules:
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
            f"{sorted(explicit_modules)}"
        )
    if explicit_modules:
        return f"{next(iter(explicit_modules))}:{class_name}"
    candidates = _exporting_import_modules(tree, class_name)
    if len(candidates) > 1:
        raise ValueError(
            f"snapshot class {class_name!r} is exported by multiple imported modules: "
            f"{candidates}"
        )
    return candidates[0] if candidates else None


def _explicit_import_modules(tree: ast.AST, class_name: str) -> set[str]:
    """Return modules that explicitly import one class name."""
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505


def _exporting_import_modules(tree: ast.AST, class_name: str) -> list[str]:
    """Return imported modules that export one class name."""
    modules = {
        node.module
        for node in tree.body
        if isinstance(node, ast.ImportFrom) and node.level == 0 and node.module
    }
    candidates = []
    for module_name in sorted(modules):
        try:
            module = importlib.import_module(module_name)
        except (ImportError, AttributeError):
            continue
        if hasattr(module, class_name):
            candidates.append(f"{module_name}:{class_name}")
    return candidates


def _ast_name(node: ast.AST) -> Optional[str]:
    """Return the terminal name of a callable expression."""
504
505
506
507
508
509
510
511
512
513
514
def _ast_name(node: ast.AST) -> Optional[str]:
    """Return the terminal name of a callable expression."""
    if isinstance(node, ast.Name):
        return node.id
    if isinstance(node, ast.Attribute):
        return node.attr
    return None


def _snapshot_target_path(target: Any) -> str:
    """Return an importable ``module:qualname`` from a frozen Target value."""
514
515
516
517
518
519
520
521
522
523
524
525
526
527
    """Return an importable ``module:qualname`` from a frozen Target value."""
    if isinstance(target, dict):
        target = target.get("_target_") or target.get("target")
    if not isinstance(target, str) or not target:
        raise ValueError(f"snapshot injection target is not importable: {target!r}")
    if ":" in target:
        return target
    module_name, separator, name = target.rpartition(".")
    if not separator or not module_name or not name:
        raise ValueError(f"snapshot injection target is not importable: {target!r}")
    return f"{module_name}:{name}"


def preflight_integrity_check(
560
561
562
563
564
565
566
567
568
        layout = ArtifactLayout.build_default(layout.artifact_dir, meta.model_name)
    verify_meta_required_fields(meta)
    verify_snapshot_contract(meta)
    if meta.snapshot_schema_version is None:
        raise RuntimeError(
            "codegen preflight: legacy artifacts are no longer supported; "
            "regenerate with 'python -m hyper_parallel.codegen generate'"
        )
    verify_output_hashes(meta, layout)
566
567
568
569
570
571
572
573
574
            "regenerate with 'python -m hyper_parallel.codegen generate'"
        )
    verify_output_hashes(meta, layout)
    if meta.snapshot_status == CodegenStatus.NOT_REQUIRED.value:
        return
    verify_generated_source(layout)
    verify_boundary_forms(meta, layout)
    verify_param_plan(meta, model=None)
    warn_skipped_overrides(meta)
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
    model = getattr(config, "model", None)
    target_path = getattr(model, "_target_path", None)
    target = getattr(model, "_target_", None)
    if not isinstance(target_path, str) and isinstance(target, str):
        target_path = target
    if not isinstance(target_path, str) and callable(target):
        module_name = getattr(target, "__module__", None)
        qualname = getattr(target, "__qualname__", None)
        if module_name and qualname:
            target_path = f"{module_name}.{qualname}"
    if not isinstance(target_path, str):
        return None
    prefix = "hyper_parallel.models."
    if not target_path.startswith(prefix):
        return None
    family, separator, _ = target_path[len(prefix) :].partition(".")
    if not separator or not family:
        return None
    return family_dir_for_model_type(family)


def _model_type_to_modeling_token(model_type: str) -> str:
hyper_parallel/codegen/meta.py
180
181
182
183
184
185
186
187
188
            raise TypeError(f"codegen_meta field {key!r} must be a dict")
    if "snapshot_schema_version" in data:
        version = data["snapshot_schema_version"]
        if not isinstance(version, int) or isinstance(version, bool) or version < 1:
            raise TypeError(
                "codegen_meta field 'snapshot_schema_version' must be a positive int"
            )
    if "snapshot_status" in data:
        try:
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
            )
    if "snapshot_status" in data:
        try:
            CodegenStatus(data["snapshot_status"])
        except (TypeError, ValueError) as exc:
            raise TypeError(
                "codegen_meta field 'snapshot_status' must be a known codegen status"
            ) from exc
    if "snapshot_reason" in data and not isinstance(data["snapshot_reason"], str):
        raise TypeError("codegen_meta field 'snapshot_reason' must be a string")
    if "snapshot_failure" in data and not isinstance(data["snapshot_failure"], dict):
        raise TypeError("codegen_meta field 'snapshot_failure' must be a dict")
    if "plan_application" in data and not isinstance(data["plan_application"], dict):
        raise TypeError("codegen_meta field 'plan_application' must be a dict")
    if "snapshot_replacements" in data and not isinstance(
        data["snapshot_replacements"], dict
    ):
        raise TypeError("codegen_meta field 'snapshot_replacements' must be a dict")
    if "entrypoints" in data:
        entrypoints = data["entrypoints"]
        if not isinstance(entrypoints, dict) or not all(
            isinstance(k, str) and isinstance(v, str) for k, v in entrypoints.items()
227
228
229
230
231
232
233
234
235
            raise TypeError(
                "codegen_meta field 'module_overrides' must be a list[dict]"
            )
    if "emission_patches" in data and not isinstance(data["emission_patches"], dict):
        raise TypeError("codegen_meta field 'emission_patches' must be a dict")
    if "remote_siblings" in data:
        siblings = data["remote_siblings"]
        if not isinstance(siblings, list) or not all(
            isinstance(item, str) for item in siblings
240
241
242
243
244
245
246
247
248
        if not isinstance(boundary_types, dict) or not all(
            isinstance(key, str) and isinstance(value, str)
            for key, value in boundary_types.items()
        ):
            raise TypeError(
                "codegen_meta field 'boundary_types' must be a dict[str, str]"
            )
    if "nested_components" in data:
        components = data["nested_components"]
248
249
250
251
252
253
254
255
256
        components = data["nested_components"]
        if not isinstance(components, list) or not all(
            isinstance(item, dict) for item in components
        ):
            raise TypeError(
                "codegen_meta field 'nested_components' must be a list[dict]"
            )
    if "external_state_classes" in data:
        class_names = data["external_state_classes"]
269
270
271
272
273
274
275
276
277
    status = data.get("snapshot_status")
    if version is None and status is None:
        return
    if version is None or status is None:
        raise ValueError(
            "snapshot metadata must include snapshot_schema_version and snapshot_status"
        )

    plan_fields = (
296
297
298
299
300
301
302
303
304
        CodegenStatus.FAILED.value: _validate_failed_snapshot_meta,
    }
    validator = validators.get(status)
    if validator is None:
        raise ValueError(f"snapshot metadata status {status!r} is not publishable")
    validator(data, has_plan_data, plan_application, covered, parallelize)


def _validate_derived_snapshot_meta(
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
    """Validate fields owned by a derived snapshot."""
    del unused_plan_data
    applications = (data.get("snapshot_replacements") or {}).get("applications") or []
    if (not data.get("param_plan") and not applications) or not plan_application:
        raise ValueError(
            "derived snapshot metadata requires plan_application and either "
            "a non-empty param_plan or observed replacement applications"
        )
    if covered.get("sharding_plan") is not True:
        raise ValueError("derived snapshot metadata must cover sharding_plan")
    if parallelize:
        raise ValueError(
            "derived snapshot metadata must not expose a training parallelize entrypoint"
        )

332
333
334
335
336
337
338
339
340
    parallelize: Any,
) -> None:
    """Validate fields owned by a not-required snapshot."""
    if not data.get("snapshot_reason"):
        raise ValueError("not_required snapshot metadata requires snapshot_reason")
    if has_plan_data or plan_application:
        raise ValueError("not_required snapshot metadata must not contain plan data")
    if covered.get("sharding_plan") is not False or parallelize:
        raise ValueError(
351
352
353
354
355
356
357
358
359
360
) -> None:
    """Validate fields owned by a failed snapshot."""
    del unused_covered
    if not data.get("snapshot_failure"):
        raise ValueError("failed snapshot metadata requires snapshot_failure")
    if has_plan_data or plan_application or parallelize:
        raise ValueError(
            "failed snapshot metadata must not contain executable plan data"
        )

hyper_parallel/codegen/model_build_overlay.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48


def _prepare_model_source_compat(hf_config: Any) -> None:
    """Run an optional model-owned compatibility hook before construction."""
    model_type = getattr(hf_config, "model_type", None)
    adapter = get_model_adapter(model_type) if model_type else None
    loader = getattr(adapter, "codegen", None) if adapter is not None else None
    provider = loader() if loader is not None else None
    prepare = getattr(provider, "prepare_model_import", None)
    if prepare is not None:
        prepare()


@dataclass
class CodegenModelBuildResult:
68
69
70
71
72
73
74
75
76
77
78
79
80
    pretrained_model_name_or_path: Any,
    is_hf_model: bool,
) -> None:
    """Record deterministic source identity from the constructed meta model."""
    model_type = type(model)
    source_path = inspect.getsourcefile(model_type)
    architectures = list(getattr(hf_config, "architectures", None) or ())
    architecture = architectures[0] if architectures else model_type.__name__
    session.record_source({
        "model_type": getattr(hf_config, "model_type", None),
        "architecture": architecture,
        "architectures": architectures,
        "model_class": f"{model_type.__module__}:{model_type.__qualname__}",
117
118
119
120
121
122
123
124
125
126
127
128
129
130
            applications=(),
            unmatched=exc.unmatched,
        )
        raise
    session.record_replacements(
        declarations=replacement_api.describe_replacement_declarations(specs),
        applications=applications,
        unmatched=(),
    )
    return model


@contextmanager
def _observe_replacement_installations(
294
295
296
297
298
299
300
301
302
        model_init_dtype=None,
        **kwargs,
    ) -> Any:
        """Construct and observe a meta model without runtime infrastructure."""
        del (
            fsdp2_manager,
            validate_placement,
            compile_config,
            activation_checkpoint,
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
            allow_cache_entry_mutation,
            activation_swap,
            model_init_dtype,
        )
        init_kwargs = auto_model._model_init_kwargs(  # pylint: disable=protected-access
            dict(kwargs),
            load_base_model=False,
        )
        if "trust_remote_code" in kwargs:
            init_kwargs["trust_remote_code"] = kwargs["trust_remote_code"]
        _prepare_model_source_compat(hf_config)
        with _codegen_model_init_context():
            _, model = auto_model._init_model(  # pylint: disable=protected-access
                cls,
                None,
                hf_config,
                attn_implementation,
323
324
325
326
327
328
329
330
331
                is_hf_model,
                *model_args,
                **init_kwargs,
            )
        _record_source(
            session,
            model,
            hf_config,
            pretrained_model_name_or_path,
330
331
332
333
334
335
336
337
338
339
340
341
342
343
            hf_config,
            pretrained_model_name_or_path,
            is_hf_model,
        )
        model_builder._apply_pre_sharding_features(  # pylint: disable=protected-access
            peft_config,
            qat_config,
            fp8_config,
        )
        model = _observe_replacements(
            model,
            distributed_setup,
            getattr(distributed_setup, "low_precision_config", None),
            load_base_model,
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
            getattr(distributed_setup, "low_precision_config", None),
            load_base_model,
            session,
        )
        if freeze_config is not None:
            model_builder._apply_parameter_freezing(  # pylint: disable=protected-access
                model,
                freeze_config,
            )
        _observe_plan(model, mesh, sharding_planner, is_hf_model, session)
        snapshot = _publish_session(session, artifact_dir, result)
        result.snapshot = snapshot
        model._hp_codegen_snapshot = snapshot  # pylint: disable=protected-access
        model.train()
        return model

    return _build_model

hyper_parallel/codegen/plan/freeze.py
43
44
45
46
47
48
49
50
51

    @staticmethod
    def to_string(p) -> str:
        if p.uneven_shard:
            raise TypeError(
                "cannot freeze StridedShard(uneven_shard=True): uneven shards "
                "are FSDP-internal placements and never belong to the frozen "
                "plan (planner contracts use plain dims or negative dim "
                "indices)"
343
344
345
346
347
348
349
350
351
        return {}
    result = {}
    for fqn, value in sorted(source_shard_info.items()):
        if not isinstance(value, tuple) or len(value) != 2:
            raise TypeError(
                f"source_shard_info[{fqn!r}] must be a (placements, mesh) pair"
            )
        placements, mesh = value
        mesh_dim_names = tuple(getattr(mesh, "mesh_dim_names", ()) or ())
361
362
363
364
365
366
367
368
369
370
371
372
def _freeze_ep_bindings(plan: Any) -> list[dict[str, Any]]:
    """Record boundaries whose native plan resolved an active EP contract."""
    result = []
    for fqn, spec in sorted((getattr(plan, "modules", {}) or {}).items()):
        ep_size = int(getattr(spec, "_ep_size", 0) or 0)
        if ep_size <= 0:
            continue
        result.append({
            "fqn": fqn,
            "ep_size": ep_size,
            "ep_stack": _value_to_dict(getattr(spec, "_ep_stack", {}) or {}),
            "local_compute_fn": _value_to_dict(
381
382
383
384
385
386
387
388
389
390
391
392
393
def _freeze_resolved_wrappers(plan: Any) -> list[dict[str, Any]]:
    """Record the inner-wrapper identities written back by native apply."""
    result = []
    for fqn, spec in sorted((getattr(plan, "modules", {}) or {}).items()):
        wrapper = getattr(spec, "_resolved_inner_wrapper", None)
        target = getattr(spec, "_resolved_inner_target", None)
        if wrapper is None and target is None:
            continue
        result.append({"fqn": fqn, "wrapper": wrapper, "target": target})
    return result


def _freeze_boundary_classes(plan: Any, model: Any) -> dict[str, str]:
448
449
450
451
452
453
454
455
456
            owner_module == root_module
            or owner_module.startswith("torch.")
            or owner_module.startswith("hyper_parallel.")
        ):
            continue
        parts = boundary_fqn.split(".")
        candidates = []
        for index in range(1, len(parts) + 1):
            ancestor_fqn = ".".join(parts[:index])
457
458
459
460
461
462
463
464
465
            ancestor_type = type(model.get_submodule(ancestor_fqn))
            if ancestor_type.__module__ == owner_module:
                candidates.append((ancestor_fqn, ancestor_type))
        if not candidates:
            continue
        component_fqn, component_type = candidates[0]
        identity = f"{component_type.__module__}:{component_type.__qualname__}"
        components[(component_fqn, identity)] = {
            "fqn": component_fqn,
hyper_parallel/codegen/planner_overlay.py
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49


def _override_declared_params(plan_overrides: dict[str, Any], model: Any) -> set[str]:
    """Return parameter FQNs already owned by exact or glob overrides."""
    module_names = tuple(name for name, _ in model.named_modules())
    declared = set()
    for key, spec in plan_overrides.items():
        matches = (
            (name for name in module_names if fnmatchcase(name, key))
            if any(char in key for char in "*?[")
            else (key,)
        )
        for module_fqn in matches:
            prefix = f"{module_fqn}." if module_fqn else ""
            declared.update(prefix + name for name in (spec.params or {}))
    return declared


class CodegenShardingPlanner(ShardingPlanner):
    """Add audit-only coverage without changing the Trainer's native planner."""
59
60
61
62
63
64
65
66
67
68
        groups = super()._group_by_boundary(param_roles)
        normalized: dict[str, list[tuple[str, ParamRole]]] = {}
        for module_fqn, group in groups.items():
            if self._infer_boundary_type(module_fqn, group) != "unknown":
                normalized[module_fqn] = group
                continue
            for param_fqn, role in group:
                owner = param_fqn.rsplit(".", 1)[0]
                normalized.setdefault(owner, []).append((param_fqn, role))
        return normalized
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
        return normalized

    def _derive_boundary_specs(self, plan: Any, boundary_groups: Any, **kwargs: Any) -> None:
        """Append explicit replicated audit entries after native derivation."""
        super()._derive_boundary_specs(plan, boundary_groups, **kwargs)
        if not self._derive:
            return
        model = kwargs["model"]
        parameters_by_name = dict(model.named_parameters())
        override_declared = _override_declared_params(self._plan_overrides, model)
        for boundary_fqn, group in boundary_groups.items():
            if boundary_fqn in plan.modules:
                continue
            fallback = self._build_replicated_fallback_spec(
                boundary_fqn,
                group,
                parameters_by_name,
                override_declared,
83
84
85
86
87
88
89
90
91
92
                group,
                parameters_by_name,
                override_declared,
            )
            if fallback is not None:
                plan.modules[boundary_fqn] = fallback

    @staticmethod
    def _build_replicated_fallback_spec(
        boundary_fqn: str,
 96
 97
 98
 99
100
101
102
103
104
    ) -> Optional[ModuleShardingSpec]:
        """Declare communication-free metadata for replicated leftovers."""
        replicable = (ParamRole.REPLICATED, ParamRole.NORM, ParamRole.BIAS)
        if any(role not in replicable for _, role in group):
            return None
        prefix = f"{boundary_fqn}." if boundary_fqn else ""
        params: dict[str, NamedPlacement] = {}
        for param_fqn, _ in group:
            parameter = parameters_by_name.get(param_fqn)
106
107
108
109
110
111
112
113
114
                continue
            relative = param_fqn[len(prefix):] if prefix else param_fqn
            params[relative] = _multi_dim(tp=Replicate(), cp=Replicate(), ep=Replicate())
        if not params:
            return None
        return ModuleShardingSpec(params=params, in_src={}, in_dst={}, is_boundary=False)


@contextmanager
hyper_parallel/codegen/session.py
51
52
53
54
55
56
57
58
59

    @property
    def status(self) -> CodegenStatus:
        """Return the current session status."""
        return self._status

    @property
    def has_replacement_applications(self) -> bool:
        """Whether native model construction installed any replacement."""
62
63
64
65
66
67
68
69
70
    def record_source(self, source: Mapping[str, Any]) -> None:
        """Record source and model identity once while collecting."""
        self._require_open(CodegenStatus.COLLECTING)
        if self._source_recorded:
            raise RuntimeError("codegen source has already been recorded")
        self._source = self._as_mapping(source, "source")
        self._source_recorded = True

    def record_replacements(
76
77
78
79
80
81
82
83
84
    ) -> None:
        """Record native replacement declarations and observed applications."""
        self._require_open(CodegenStatus.COLLECTING)
        if self._replacements_recorded:
            raise RuntimeError("codegen replacements have already been recorded")
        self._replacements = ReplacementSnapshot.from_data(
            declarations=declarations,
            applications=applications,
            unmatched=unmatched,
 96
 97
 98
 99
100
101
102
103
104
    def record_plan_application(self, application: Mapping[str, Any]) -> None:
        """Record how the native plan resolved against the live model."""
        self._require_open(CodegenStatus.DERIVED)
        if self._plan_application is not None:
            raise RuntimeError("codegen plan application has already been recorded")
        self._plan_application = self._as_mapping(application, "plan_application")

    def observe_plan(self, plan: Any, model: Any, mesh: Any) -> None:
        """Freeze a native planner result without exposing codegen to the builder."""
141
142
143
144
145
146
147
148
149
    def mark_not_required(self, reason: str) -> None:
        """Finish collection when the native build has no sharding plan."""
        self._require_open(CodegenStatus.COLLECTING)
        if not self._source_recorded:
            raise RuntimeError("record_source() must run before mark_not_required()")
        self._reason = self._require_reason(reason)
        self._status = CodegenStatus.NOT_REQUIRED

    def mark_generating(self) -> None:
149
150
151
152
153
154
155
156
157
    def mark_generating(self) -> None:
        """Mark the future side-effecting generation boundary."""
        self._require_open(CodegenStatus.DERIVED)
        if self._plan_application is None:
            raise RuntimeError("record_plan_application() must run before generation")
        self._status = CodegenStatus.GENERATING

    def mark_generated(self) -> None:
        """Mark successful generation."""
159
160
161
162
163
164
165
166
167
168
169
170
171
        self._status = CodegenStatus.GENERATED

    def mark_skipped(self, reason: str) -> None:
        """Mark generation as intentionally skipped with a stable reason."""
        self._require_open(CodegenStatus.COLLECTING, CodegenStatus.DERIVED)
        if not self._source_recorded:
            raise RuntimeError("record_source() must run before mark_skipped()")
        self._reason = self._require_reason(reason)
        self._status = CodegenStatus.SKIPPED

    def mark_failed(
        self,
        stage: str,
203
204
205
206
207
208
209
210
211
            RuntimeError: If collection or generation is incomplete.
        """
        if self._finished:
            if self._snapshot is None:
                raise RuntimeError("finished codegen session has no snapshot")
            return self._snapshot
        if self._status == CodegenStatus.COLLECTING:
            raise RuntimeError("codegen session is still collecting")
        if self._status == CodegenStatus.DERIVED and self._plan_application is None:
210
211
212
213
214
215
216
217
218
            raise RuntimeError("codegen session is still collecting")
        if self._status == CodegenStatus.DERIVED and self._plan_application is None:
            raise RuntimeError("derived codegen session is missing plan application")
        if self._status == CodegenStatus.GENERATING:
            raise RuntimeError("codegen session is still generating")
        if self._status == CodegenStatus.DERIVED and generator is not None:
            publish_snapshot = self._build_snapshot(CodegenStatus.DERIVED)
            self.mark_generating()
            try:
228
229
230
231
232
233
234
235
236
237
        elif self._status == CodegenStatus.NOT_REQUIRED and generator is not None:
            publish_snapshot = self._build_snapshot(CodegenStatus.NOT_REQUIRED)
            try:
                generator(publish_snapshot)
            except Exception as exc:  # Publication must not invalidate native build.
                self.mark_failed(
                    "generation",
                    str(exc) or type(exc).__name__,
                    {"exception_type": type(exc).__name__},
                )
255
256
257
258
259
260
261
262
263
264
    def _require_open(self, *statuses: CodegenStatus) -> None:
        if self._finished:
            raise RuntimeError("codegen session is already finished")
        if statuses and self._status not in statuses:
            expected = ", ".join(status.value for status in statuses)
            raise RuntimeError(
                f"codegen session is {self._status.value}; expected one of: {expected}"
            )

    @staticmethod
264
265
266
267
268
269
270
271
272
    @staticmethod
    def _as_mapping(value: Mapping[str, Any], path: str) -> FrozenMapping:
        frozen = freeze_json(value, path=path)
        if not isinstance(frozen, FrozenMapping):
            raise TypeError(f"{path} must be a mapping")
        return frozen

    @staticmethod
    def _require_reason(reason: str) -> str:
270
271
272
273
274
275
276
277
278

    @staticmethod
    def _require_reason(reason: str) -> str:
        if not isinstance(reason, str) or not reason.strip():
            raise ValueError("codegen reason must be a non-empty string")
        return reason


__all__ = ["CodegenBuildSession"]
hyper_parallel/codegen/snapshot.py
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

    def __post_init__(self) -> None:
        keys = tuple(key for key, _ in self._items)
        if any(not isinstance(key, str) for key in keys):
            raise TypeError("FrozenMapping keys must be strings")
        if keys != tuple(sorted(set(keys))):
            raise ValueError("FrozenMapping keys must be unique and sorted")
        if any(not _is_frozen_json(value) for _, value in self._items):
            raise TypeError("FrozenMapping values must be immutable JSON values")

    def __iter__(self) -> Iterator[str]:
        return (key for key, _ in self._items)

    def __len__(self) -> int:
        return len(self._items)

    def __getitem__(self, key: str) -> FrozenJson:
        for item_key, value in self._items:
            if item_key == key:
                return value
        raise KeyError(key)


def _is_frozen_json(value: Any) -> bool:
    if value is None or isinstance(value, (bool, int, str)):
72
73
74
75
76
77
78
79
80
def _is_frozen_json(value: Any) -> bool:
    if value is None or isinstance(value, (bool, int, str)):
        return True
    if isinstance(value, float):
        return math.isfinite(value)
    if isinstance(value, FrozenMapping):
        return True
    if isinstance(value, tuple):
        return all(_is_frozen_json(item) for item in value)
 97
 98
 99
100
101
102
103
104
105
106
107
    """
    if value is None or isinstance(value, (bool, int, str)):
        return value
    if isinstance(value, float):
        if not math.isfinite(value):
            raise ValueError(f"{path} contains a non-finite float")
        return value
    if isinstance(value, Mapping):
        if not all(isinstance(key, str) for key in value):
            raise ValueError(f"{path} mapping keys must be strings")
        items = []
127
128
129
130
131
132
133
134
135

def _freeze_mapping(value: Mapping[str, Any], path: str) -> FrozenMapping:
    frozen = freeze_json(value, path=path)
    if not isinstance(frozen, FrozenMapping):
        raise TypeError(f"{path} must be a mapping")
    return frozen


@dataclass(frozen=True)
145
146
147
148
149
150
151
152
153
            value = getattr(self, name)
            if not isinstance(value, tuple) or not all(
                isinstance(item, FrozenMapping) for item in value
            ):
                raise TypeError(f"replacement {name} must be a tuple of FrozenMapping")

    @classmethod
    def from_data(
        cls,
190
191
192
193
194
195
196
197
198
199
200
201
202
    details: FrozenMapping = field(default_factory=FrozenMapping)

    def __post_init__(self) -> None:
        if not isinstance(self.stage, str) or not self.stage:
            raise ValueError("failure stage must be a non-empty string")
        if not isinstance(self.reason, str) or not self.reason:
            raise ValueError("failure reason must be a non-empty string")
        if not isinstance(self.details, FrozenMapping):
            raise TypeError("failure details must be a FrozenMapping")

    @classmethod
    def from_data(
        cls,
205
206
207
208
209
210
211
212
213
        details: Optional[Mapping[str, Any]] = None,
    ) -> "FailureSnapshot":
        """Build a validated failure record."""
        if not stage or not reason:
            raise ValueError("failure stage and reason must be non-empty")
        return cls(stage, reason, _freeze_mapping(details or {}, "failure.details"))

    def to_dict(self) -> dict[str, Any]:
        """Return the JSON representation of this failure record."""
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    schema_version: int = SNAPSHOT_SCHEMA_VERSION

    def __post_init__(self) -> None:
        if self.schema_version != SNAPSHOT_SCHEMA_VERSION:
            raise ValueError(
                f"unsupported snapshot schema version {self.schema_version}; "
                f"expected {SNAPSHOT_SCHEMA_VERSION}"
            )
        if not isinstance(self.status, CodegenStatus):
            raise TypeError("snapshot status must be a CodegenStatus")
        if not isinstance(self.replacements, ReplacementSnapshot):
            raise TypeError("snapshot replacements must be a ReplacementSnapshot")
        if self.failure is not None and not isinstance(self.failure, FailureSnapshot):
            raise TypeError("snapshot failure must be a FailureSnapshot or None")
        for name in ("source", "diagnostics"):
            if not isinstance(getattr(self, name), FrozenMapping):
                raise TypeError(f"snapshot {name} must be a FrozenMapping")
        for name in ("plan", "plan_application"):
            value = getattr(self, name)
            if value is not None and not isinstance(value, FrozenMapping):
                raise TypeError(f"snapshot {name} must be a FrozenMapping or None")

    @classmethod
    def from_dict(cls, data: Mapping[str, Any]) -> "CodegenSnapshot":
        """Rebuild and validate a snapshot from its JSON representation."""
251
252
253
254
255
256
257
258
259
    @classmethod
    def from_dict(cls, data: Mapping[str, Any]) -> "CodegenSnapshot":
        """Rebuild and validate a snapshot from its JSON representation."""
        if not isinstance(data, Mapping):
            raise TypeError("snapshot payload must be a mapping")
        version = data.get("schema_version")
        if version != SNAPSHOT_SCHEMA_VERSION:
            raise ValueError(
                f"unsupported snapshot schema version {version!r}; "
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
                f"expected {SNAPSHOT_SCHEMA_VERSION}"
            )
        try:
            status = CodegenStatus(data.get("status"))
        except (TypeError, ValueError) as exc:
            raise ValueError(f"unknown snapshot status {data.get('status')!r}") from exc
        source = data.get("source", {})
        replacements = data.get("replacements", {})
        diagnostics = data.get("diagnostics", {})
        if not isinstance(source, Mapping):
            raise TypeError("snapshot source must be a mapping")
        if not isinstance(replacements, Mapping):
            raise TypeError("snapshot replacements must be a mapping")
        if not isinstance(diagnostics, Mapping):
            raise TypeError("snapshot diagnostics must be a mapping")
        plan = data.get("plan")
        plan_application = data.get("plan_application")
        if plan is not None and not isinstance(plan, Mapping):
            raise TypeError("snapshot plan must be a mapping or None")
        if plan_application is not None and not isinstance(plan_application, Mapping):
            raise TypeError("snapshot plan_application must be a mapping or None")
        failure_data = data.get("failure")
        failure = None
        if failure_data is not None:
            if not isinstance(failure_data, Mapping):
                raise TypeError("snapshot failure must be a mapping or None")
            failure = FailureSnapshot.from_data(
                failure_data.get("stage"),
                failure_data.get("reason"),
                failure_data.get("details"),
            )
289
290
291
292
293
294
295
296
297
                failure_data.get("details"),
            )
        reason = data.get("reason")
        if reason is not None and not isinstance(reason, str):
            raise TypeError("snapshot reason must be a string or None")
        return cls(
            status=status,
            source=_freeze_mapping(source, "source"),
            replacements=ReplacementSnapshot.from_data(
hyper_parallel/codegen/source/composition.py
40
41
42
43
44
45
46
47
48
        One source string containing the primary and nested model definitions.
    """
    components = getattr(meta, "nested_components", None) or ()
    if not components:
        return source_text
    rendered = source_text
    included_modules: set[str] = set()
    for component in components:
        identity = component.get("type")
46
47
48
49
50
51
52
53
54
    included_modules: set[str] = set()
    for component in components:
        identity = component.get("type")
        if not isinstance(identity, str) or ":" not in identity:
            raise ValueError(f"invalid nested component identity: {identity!r}")
        module_name, class_name = identity.split(":", 1)
        class_name = class_name.rsplit(".", 1)[-1]
        replaced = _replace_auto_model_construction(
            rendered,
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81


def _read_module_source(module_name: str) -> str:
    """Read an installed module without importing its runtime dependencies."""
    spec = importlib.util.find_spec(module_name)
    path = None if spec is None else spec.origin
    if not path or not os.path.isfile(path):
        raise FileNotFoundError(
            f"codegen: nested model source {module_name!r} is not readable"
        )
    with open(path, "r", encoding="utf-8", errors="replace") as handle:
        return handle.read()


def _append_source_module(primary: str, nested: str, module_name: str) -> str:
    """Append one nested module after removing module-only syntax."""
127
128
129
130
131
132
133
134
135
    return result


def _is_docstring(node: ast.Expr) -> bool:
    return isinstance(node.value, ast.Constant) and isinstance(node.value.value, str)


class _RenameBindings(ast.NodeTransformer):
    """Rename colliding nested-module globals and their references."""
174
175
176
177
178
179
180
181
182
        """Render imports whose dynamic package contains non-Python identifiers."""
        assignments = []
        for alias in node.names:
            if alias.name == "*":
                raise ValueError(
                    f"codegen cannot compose a wildcard import from dynamic module {module!r}"
                )
            imported = ast.Call(
                func=ast.Name(id="__import__", ctx=ast.Load()),
202
203
204
205
206
207
208
209
210
) -> str | None:
    """Replace an observed AutoModel construction, or reject the candidate."""
    attribute = component_fqn.rsplit(".", 1)[-1]
    if not attribute:
        raise ValueError("nested component FQN must not be empty")
    pattern = re.compile(
        rf"(?m)^(?P<indent>\s*)self\.{re.escape(attribute)}\s*=\s*"
        r"AutoModel\.from_config\((?P<config>[^\n]+)\)\s*$"
    )
hyper_parallel/codegen/source/resolver.py
426
427
428
429
430
431
432
433
434
435
436
437
    path = getattr(model, "pretrained_model_name_or_path", None)
    if path is None:
        path = getattr(model, "model_name_or_path", None)
    if path is None:
        path = getattr(model, "config_path", None)
    if path is None:
        kwargs = getattr(model, "_kwargs", {})
        path = kwargs.get("pretrained_model_name_or_path") or kwargs.get("config_path", "")
    return path or ""


def _trust_remote_code(config: Any) -> bool:
hyper_parallel/codegen/train_sidecar.py
54
55
56
57
58
59
60
61
62
63
def _monitor_sidecar(process: subprocess.Popen, config_path: str) -> None:
    """Reap the Codegen process and report failure without stopping training."""
    return_code = process.wait()
    if return_code == 0:
        logger.info("Codegen sidecar completed for %s", config_path)
        return
    logger.warning(
        "Codegen sidecar failed for %s with exit code %s; native training continues",
        config_path,
        return_code,
158
159
160
161
162
163
164
165
166
    """
    resolved_config = str(Path(config_path).resolve())
    resolved_entry = str(Path(trainer_entry).resolve())
    if not Path(resolved_entry).is_file():
        raise FileNotFoundError(f"native Trainer entry does not exist: {resolved_entry}")
    start_codegen_sidecar(resolved_config, overrides)
    os.execv(
        sys.executable,
        [sys.executable, resolved_entry, resolved_config, *overrides],