emit.go raw

   1  // Package emit reconstructs Go source code from a lattice's bonded AST elements.
   2  //
   3  // The emitter reads bonded elements and projects them back into source code.
   4  // The lattice's structure determines what code is emitted — it writes itself out.
   5  //
   6  // Body-level elements (assign, return, if, for, expr, etc.) carry their
   7  // parent function name and rendered source text separated by \x00. The
   8  // emitter groups these by parent to reconstruct function bodies.
   9  //
  10  // When body elements exist, the emitter produces actual executable code.
  11  // When only declarations and literals exist (legacy mode), it falls back
  12  // to self-logging skeleton code for behavioral equivalence.
  13  package emit
  14  
  15  import (
  16  	"crypto/rand"
  17  	"encoding/binary"
  18  	"fmt"
  19  	"go/parser"
  20  	"go/token"
  21  	"io"
  22  	"os"
  23  	"path/filepath"
  24  	"sort"
  25  	"strings"
  26  	"sync"
  27  
  28  	"git.mleku.dev/mleku/dendrite/pkg/causal"
  29  	"git.mleku.dev/mleku/dendrite/pkg/enzyme"
  30  	"git.mleku.dev/mleku/dendrite/pkg/lattice"
  31  )
  32  
  33  // Fragment is a bonded element extracted from the lattice for emission.
  34  type Fragment struct {
  35  	NodeID lattice.NodeID
  36  	Type   string
  37  	Value  string
  38  	LockIn lattice.LockInDepth
  39  }
  40  
  41  // bodyTags are element types that represent statements inside function bodies.
  42  var bodyTags = map[string]bool{
  43  	"assign": true, "return": true, "if": true, "for": true,
  44  	"switch": true, "select": true, "go": true, "send": true,
  45  	"expr": true, "defer": true, "decl": true, "branch": true,
  46  	"case": true, "comm": true,
  47  }
  48  
  49  // Harvest collects all bonded elements from a lattice, grouped by file
  50  // (if file markers exist) or as a single unnamed group.
  51  func Harvest(l *lattice.Lattice) map[string][]Fragment {
  52  	files := make(map[string][]Fragment)
  53  	currentFile := ""
  54  
  55  	nodes := l.Nodes()
  56  	sort.Slice(nodes, func(i, j int) bool {
  57  		return nodes[i].ID() < nodes[j].ID()
  58  	})
  59  
  60  	for _, n := range nodes {
  61  		if !n.Occupied() {
  62  			continue
  63  		}
  64  		e := n.Occupant()
  65  
  66  		// Skip reference material — these elements influence lattice
  67  		// topology during growth but should not appear in emitted output.
  68  		if enzyme.IsRef(e) {
  69  			continue
  70  		}
  71  
  72  		val := ""
  73  		if e.Value() != nil {
  74  			val = fmt.Sprintf("%v", e.Value())
  75  		}
  76  
  77  		if e.Type() == "file" {
  78  			currentFile = val
  79  			continue
  80  		}
  81  
  82  		// Grammar rules are structural context, not emittable code.
  83  		if e.Type() == "grammar-rule" {
  84  			continue
  85  		}
  86  
  87  		f := Fragment{
  88  			NodeID: n.ID(),
  89  			Type:   e.Type(),
  90  			Value:  val,
  91  			LockIn: n.LockIn(),
  92  		}
  93  		files[currentFile] = append(files[currentFile], f)
  94  	}
  95  
  96  	return files
  97  }
  98  
  99  // bodyStmt holds a parsed body-level statement with its parent function.
 100  type bodyStmt struct {
 101  	Parent  string
 102  	Source  string
 103  	LineNum int // original source line number (0 = unknown)
 104  	NodeID  lattice.NodeID
 105  	LockIn  lattice.LockInDepth
 106  	Tag     string
 107  }
 108  
 109  // parseBodyValue splits "parent\x00source" from a body element's value.
 110  // Returns empty parent if no separator found (legacy element).
 111  // Used for fields, directives, and other two-part values.
 112  func parseBodyValue(val string) (parent, source string) {
 113  	idx := strings.IndexByte(val, '\x00')
 114  	if idx < 0 {
 115  		return "", val
 116  	}
 117  	return val[:idx], val[idx+1:]
 118  }
 119  
 120  // parseBodyStmt splits body element values in two supported formats:
 121  //   - Three-part: "parent\x00linenum\x00source" (new: carries source position)
 122  //   - Two-part:   "parent\x00source" (legacy: no position info)
 123  //
 124  // Returns empty parent if no separator found.
 125  func parseBodyStmt(val string) (parent string, lineNum int, source string) {
 126  	idx := strings.IndexByte(val, '\x00')
 127  	if idx < 0 {
 128  		return "", 0, val
 129  	}
 130  	rest := val[idx+1:]
 131  	parent = val[:idx]
 132  
 133  	// Check for three-part format: is there another \x00?
 134  	idx2 := strings.IndexByte(rest, '\x00')
 135  	if idx2 >= 0 {
 136  		// Three-part: parent\x00linenum\x00source
 137  		lineStr := rest[:idx2]
 138  		source = rest[idx2+1:]
 139  		ln := 0
 140  		for _, ch := range lineStr {
 141  			if ch >= '0' && ch <= '9' {
 142  				ln = ln*10 + int(ch-'0')
 143  			}
 144  		}
 145  		return parent, ln, source
 146  	}
 147  
 148  	// Two-part: parent\x00source (legacy)
 149  	return parent, 0, rest
 150  }
 151  
 152  // funcDecl holds information about a function or method declaration.
 153  type funcDecl struct {
 154  	Name      string // bare name for matching body statements
 155  	Signature string // full value from the enzyme (e.g., "main()" or "Foo.Hello() string")
 156  	IsMethod  bool
 157  	RecvVar   string // receiver variable name (e.g., "c", "e") — empty means use "x"
 158  	NodeID    lattice.NodeID
 159  }
 160  
 161  // parseFuncName extracts the bare function name from a func/method value.
 162  // "main()" → "main", "Foo.Hello() string" → "Hello"
 163  func parseFuncName(val string, isMethod bool) string {
 164  	name := val
 165  	if isMethod {
 166  		// "Foo.Hello() string" → "Hello() string"
 167  		if dot := strings.IndexByte(name, '.'); dot >= 0 {
 168  			name = name[dot+1:]
 169  		}
 170  	}
 171  	// "main()" → "main"
 172  	if paren := strings.IndexByte(name, '('); paren >= 0 {
 173  		name = name[:paren]
 174  	}
 175  	return name
 176  }
 177  
 178  // EmitGo writes reconstructed Go source from harvested fragments.
 179  // Uses "main" as the package name. See EmitGoPackage for arbitrary packages.
 180  func EmitGo(fragments []Fragment, w io.Writer) error {
 181  	return EmitGoPackage(fragments, w, "main")
 182  }
 183  
 184  // EmitGoPackage writes reconstructed Go source from harvested fragments
 185  // using the specified package name.
 186  //
 187  // If body elements (assign, return, if, expr, etc.) are present, the emitter
 188  // reconstructs actual function bodies from the rendered source text each
 189  // element carries. Otherwise it falls back to self-logging skeleton code.
 190  func EmitGoPackage(fragments []Fragment, w io.Writer, pkgName string) error {
 191  	// Separate fragments by role.
 192  	var (
 193  		funcDecls   []funcDecl
 194  		structDecls []Fragment // type+struct pairs
 195  		ifaceDecls  []Fragment // type+interface pairs
 196  		typeDecls   []Fragment // standalone types
 197  		fields      []Fragment
 198  		imports     []Fragment
 199  		bodyStmts   []bodyStmt
 200  		literals    []Fragment
 201  		directives  []Fragment
 202  		varDecls    []Fragment // top-level var/const declarations
 203  	)
 204  
 205  	// Track struct and interface names from their dedicated elements.
 206  	structNames := make(map[string]bool)
 207  	ifaceNames := make(map[string]bool)
 208  
 209  	for _, f := range fragments {
 210  		switch f.Type {
 211  		case "func":
 212  			name := parseFuncName(f.Value, false)
 213  			funcDecls = append(funcDecls, funcDecl{
 214  				Name: name, Signature: f.Value, IsMethod: false, NodeID: f.NodeID,
 215  			})
 216  		case "method":
 217  			methodVal := f.Value
 218  			recvVar := ""
 219  			// Method value format: "recvVar\x00RecvType.MethodName(...) returns"
 220  			if idx := strings.IndexByte(methodVal, '\x00'); idx >= 0 {
 221  				recvVar = methodVal[:idx]
 222  				methodVal = methodVal[idx+1:]
 223  			}
 224  			name := parseFuncName(methodVal, true)
 225  			funcDecls = append(funcDecls, funcDecl{
 226  				Name: name, Signature: methodVal, IsMethod: true,
 227  				RecvVar: recvVar, NodeID: f.NodeID,
 228  			})
 229  		case "struct":
 230  			structDecls = append(structDecls, f)
 231  			structNames[f.Value] = true
 232  		case "interface":
 233  			ifaceDecls = append(ifaceDecls, f)
 234  			ifaceNames[f.Value] = true
 235  		case "type":
 236  			typeDecls = append(typeDecls, f)
 237  		case "field":
 238  			fields = append(fields, f)
 239  		case "import":
 240  			imports = append(imports, f)
 241  		case "directive":
 242  			directives = append(directives, f)
 243  		case "var":
 244  			varDecls = append(varDecls, f)
 245  		default:
 246  			if strings.HasPrefix(f.Type, "literal:") {
 247  				literals = append(literals, f)
 248  			} else if strings.HasPrefix(f.Type, "ident:") {
 249  				// Ident subtypes contribute to naming but aren't directly emitted.
 250  			} else if bodyTags[f.Type] {
 251  				parent, lineNum, source := parseBodyStmt(f.Value)
 252  				if source != "" {
 253  					bodyStmts = append(bodyStmts, bodyStmt{
 254  						Parent:  parent,
 255  						Source:  source,
 256  						LineNum: lineNum,
 257  						NodeID:  f.NodeID,
 258  						LockIn:  f.LockIn,
 259  						Tag:     f.Type,
 260  					})
 261  				}
 262  			}
 263  		}
 264  	}
 265  
 266  	// Group body statements by parent function, maintaining node ID order.
 267  	sort.Slice(bodyStmts, func(i, j int) bool {
 268  		return bodyStmts[i].NodeID < bodyStmts[j].NodeID
 269  	})
 270  	funcBodies := make(map[string][]bodyStmt)
 271  	for _, bs := range bodyStmts {
 272  		funcBodies[bs.Parent] = append(funcBodies[bs.Parent], bs)
 273  	}
 274  
 275  	// Determine if we have real body content or need legacy self-logging.
 276  	hasBodyContent := len(bodyStmts) > 0
 277  
 278  	// === Build the source ===
 279  	var b strings.Builder
 280  	// Always use the caller's package name. When ingesting multi-package
 281  	// source (e.g. -self), fragments contain package elements from every
 282  	// file parsed ("axiom", "enzyme", "ed25519", etc). Using those would
 283  	// produce a non-main package that can't compile as a binary.
 284  	fmt.Fprintf(&b, "package %s\n\n", pkgName)
 285  
 286  	// Determine imports (with alias resolution for name collisions).
 287  	// Build a set of known package names for reference validation.
 288  	knownPkgs := make(map[string]bool)
 289  	if hasBodyContent {
 290  		neededImports := inferImports(bodyStmts, imports, funcDecls, varDecls, fields)
 291  		neededImports = aliasCollisions(neededImports)
 292  		for _, imp := range neededImports {
 293  			knownPkgs[extractPkgName(imp)] = true
 294  		}
 295  		if len(neededImports) > 0 {
 296  			b.WriteString("import (\n")
 297  			for _, imp := range neededImports {
 298  				fmt.Fprintf(&b, "\t%s\n", imp)
 299  			}
 300  			b.WriteString(")\n\n")
 301  		}
 302  	} else {
 303  		needsFmt := hasOutputLiterals(literals)
 304  		if needsFmt {
 305  			b.WriteString("import \"fmt\"\n\n")
 306  			knownPkgs["fmt"] = true
 307  		}
 308  	}
 309  
 310  	// Top-level var/const declarations (with associated directives).
 311  	// Validate each declaration: must parse, and must not reference
 312  	// unknown packages (e.g., "hash.Len" when "hash" isn't imported).
 313  	emittedVars := make(map[string]bool)
 314  	emittedNames := make(map[string]bool) // track declared names for duplicate detection
 315  	for _, v := range varDecls {
 316  		if v.Value == "" || emittedVars[v.Value] {
 317  			continue
 318  		}
 319  		if !isValidDecl(v.Value) {
 320  			continue
 321  		}
 322  		name := extractVarName(v.Value)
 323  		if emittedNames[name] {
 324  			continue // duplicate declaration name
 325  		}
 326  		if hasUndefinedRefs(v.Value, knownPkgs) {
 327  			continue
 328  		}
 329  		emittedVars[v.Value] = true
 330  		emittedNames[name] = true
 331  		emitDirectives(&b, directives, name)
 332  		fmt.Fprintf(&b, "%s\n\n", v.Value)
 333  	}
 334  
 335  	// Type declarations.
 336  	emittedTypes := make(map[string]bool)
 337  	ifaceAliases := make(map[string]bool) // types emitted as "= interface{}"
 338  	for _, t := range typeDecls {
 339  		name := t.Value
 340  		if name == "" || emittedTypes[name] || emittedNames[name] {
 341  			continue
 342  		}
 343  		emittedTypes[name] = true
 344  
 345  		// Emit any directives associated with this type.
 346  		emitDirectives(&b, directives, name)
 347  
 348  		if structNames[name] {
 349  			fmt.Fprintf(&b, "type %s struct {\n", name)
 350  			for _, f := range fields {
 351  				parent, fieldDef := parseBodyValue(f.Value)
 352  				if parent != name {
 353  					continue // skip fields from other structs
 354  				}
 355  				if fieldDef == "" {
 356  					continue
 357  				}
 358  				fmt.Fprintf(&b, "\t%s\n", fieldDef)
 359  			}
 360  			b.WriteString("}\n\n")
 361  		} else if ifaceNames[name] {
 362  			fmt.Fprintf(&b, "type %s interface {\n", name)
 363  			// Only include methods whose receiver type matches this
 364  			// interface name (or has no body — interface method stubs).
 365  			seen := make(map[string]bool)
 366  			for _, fd := range funcDecls {
 367  				if !fd.IsMethod {
 368  					continue
 369  				}
 370  				// Extract receiver type from "RecvType.MethodName(...) returns"
 371  				sig := fd.Signature
 372  				recv := ""
 373  				if dot := strings.IndexByte(sig, '.'); dot >= 0 {
 374  					recv = sig[:dot]
 375  					sig = sig[dot+1:]
 376  				}
 377  				// Only include if receiver matches this interface, or
 378  				// there's no body (could be an interface method stub).
 379  				if recv != name && recv != "*"+name {
 380  					continue
 381  				}
 382  				if _, hasBod := funcBodies[fd.Name]; hasBod {
 383  					continue
 384  				}
 385  				if seen[fd.Name] {
 386  					continue
 387  				}
 388  				seen[fd.Name] = true
 389  				fmt.Fprintf(&b, "\t%s\n", sig)
 390  			}
 391  			b.WriteString("}\n\n")
 392  		} else {
 393  			// Type with unknown underlying definition — alias to interface{}.
 394  			// Track these so we can skip methods with this receiver type
 395  			// (interface aliases can't be method receivers).
 396  			ifaceAliases[name] = true
 397  			fmt.Fprintf(&b, "type %s = interface{}\n\n", name)
 398  		}
 399  	}
 400  
 401  	// Functions and methods — with actual bodies when available.
 402  	// Validate signatures before emitting to avoid garbled output.
 403  	emittedFuncs := make(map[string]bool)
 404  	for _, fd := range funcDecls {
 405  		if emittedFuncs[fd.Name] {
 406  			continue
 407  		}
 408  		// Skip non-method functions whose name clashes with a type or var/const.
 409  		// Go doesn't allow a function and type/var with the same name in one package.
 410  		if !fd.IsMethod && (emittedTypes[fd.Name] || emittedNames[fd.Name]) {
 411  			continue
 412  		}
 413  
 414  		var funcLine string
 415  		var returnSig string // portion after ')' for zero-value return generation
 416  
 417  		if fd.IsMethod {
 418  			sig := fd.Signature
 419  			recv := ""
 420  			rest := sig
 421  			if dot := strings.IndexByte(sig, '.'); dot >= 0 {
 422  				recv = sig[:dot]
 423  				rest = sig[dot+1:]
 424  			}
 425  			if !strings.Contains(rest, "(") {
 426  				continue
 427  			}
 428  			if recv != "" && !isValidReceiver(recv) {
 429  				continue
 430  			}
 431  			// Skip methods on interface-aliased types (can't have receivers).
 432  			bareRecv := strings.TrimPrefix(recv, "*")
 433  			if ifaceAliases[bareRecv] {
 434  				continue
 435  			}
 436  			// Skip if signature references undefined packages.
 437  			if hasUndefinedRefs(rest, knownPkgs) {
 438  				continue
 439  			}
 440  			if recv != "" {
 441  				rv := fd.RecvVar
 442  				if rv == "" {
 443  					rv = "x"
 444  				}
 445  				funcLine = fmt.Sprintf("func (%s %s) %s {\n", rv, recv, rest)
 446  			} else {
 447  				funcLine = fmt.Sprintf("func %s {\n", rest)
 448  			}
 449  			returnSig = extractReturnSig(rest)
 450  		} else {
 451  			if !strings.Contains(fd.Signature, "(") {
 452  				continue
 453  			}
 454  			if hasUndefinedRefs(fd.Signature, knownPkgs) {
 455  				continue
 456  			}
 457  			funcLine = fmt.Sprintf("func %s {\n", fd.Signature)
 458  			returnSig = extractReturnSig(fd.Signature)
 459  		}
 460  
 461  		emittedFuncs[fd.Name] = true
 462  		emitDirectives(&b, directives, fd.Name)
 463  		b.WriteString(funcLine)
 464  
 465  		hasBody := false
 466  		if stmts, ok := funcBodies[fd.Name]; ok && hasBodyContent {
 467  			emitBody(&b, stmts)
 468  			hasBody = len(stmts) > 0
 469  		} else if !hasBodyContent && fd.Name == "main" {
 470  			emitLegacyMain(&b, literals, typeDecls, funcDecls)
 471  			hasBody = true
 472  		}
 473  
 474  		// Add zero-value return for functions with return types and no body.
 475  		if !hasBody && returnSig != "" {
 476  			zr := zeroReturn(returnSig)
 477  			if zr != "" {
 478  				fmt.Fprintf(&b, "\t%s\n", zr)
 479  			}
 480  		}
 481  		b.WriteString("}\n\n")
 482  	}
 483  
 484  	// Ensure main exists (only for package main).
 485  	if pkgName == "main" && !emittedFuncs["main"] {
 486  		b.WriteString("func main() {\n")
 487  		if stmts, ok := funcBodies["main"]; ok {
 488  			emitBody(&b, stmts)
 489  		} else if !hasBodyContent {
 490  			emitLegacyMain(&b, literals, typeDecls, funcDecls)
 491  		}
 492  		b.WriteString("}\n\n")
 493  	}
 494  
 495  	// Post-process: try to parse with go/parser and format with go/format.
 496  	// If parsing succeeds, emit the formatted version (fixes import ordering,
 497  	// whitespace). If it fails, emit the raw version — the compiler will
 498  	// report specific errors that feed back into fitness.
 499  	source := b.String()
 500  	if formatted, err := sanitizeGoSource(source); err == nil {
 501  		source = formatted
 502  	}
 503  
 504  	_, err := io.WriteString(w, source)
 505  	return err
 506  }
 507  
 508  // EmitProject reconstructs a multi-file Go module from harvested fragments.
 509  // It emits source files and a go.mod with replace directives for all
 510  // internal packages. Returns filepath → source code.
 511  func EmitProject(files map[string][]Fragment, modPath string) map[string]string {
 512  	result := make(map[string]string)
 513  	internalPkgs := make(map[string]bool)
 514  
 515  	for filename, frags := range files {
 516  		// Determine package name from fragments.
 517  		pkgName := "main"
 518  		for _, f := range frags {
 519  			if f.Type == "package" {
 520  				pkgName = f.Value
 521  				break
 522  			}
 523  		}
 524  
 525  		var buf strings.Builder
 526  		EmitGoPackage(frags, &buf, pkgName)
 527  
 528  		// Use filename if provided, otherwise derive from package name.
 529  		outName := filename
 530  		if outName == "" {
 531  			outName = pkgName + ".go"
 532  		}
 533  		result[outName] = buf.String()
 534  
 535  		// Track subpackage directories for go.mod replace directives.
 536  		if dir := filepath.Dir(outName); dir != "." && dir != "" {
 537  			internalPkgs[dir] = true
 538  		}
 539  	}
 540  
 541  	// Emit go.mod with replace directives.
 542  	result["go.mod"] = emitGoMod(modPath, internalPkgs)
 543  	return result
 544  }
 545  
 546  // emitGoMod generates a go.mod file with replace directives for all
 547  // internal subpackages. All imports resolve locally — no network access.
 548  func emitGoMod(modPath string, internalPkgs map[string]bool) string {
 549  	var b strings.Builder
 550  	fmt.Fprintf(&b, "module %s\n\ngo 1.24\n", modPath)
 551  
 552  	if len(internalPkgs) > 0 {
 553  		var pkgs []string
 554  		for pkg := range internalPkgs {
 555  			pkgs = append(pkgs, pkg)
 556  		}
 557  		sort.Strings(pkgs)
 558  
 559  		b.WriteString("\nreplace (\n")
 560  		for _, pkg := range pkgs {
 561  			fmt.Fprintf(&b, "\t%s/%s => ./%s\n", modPath, pkg, pkg)
 562  		}
 563  		b.WriteString(")\n")
 564  	}
 565  	return b.String()
 566  }
 567  
 568  // emitBody writes the body statements for a function.
 569  // It deduplicates, filters compound sub-statements, orders by
 570  // dependency DAG, and shuffles non-dependent statements for
 571  // anti-fingerprinting.
 572  func emitBody(b *strings.Builder, stmts []bodyStmt) {
 573  	// Deduplicate.
 574  	var unique []bodyStmt
 575  	seen := make(map[string]bool)
 576  	for _, s := range stmts {
 577  		if seen[s.Source] {
 578  			continue
 579  		}
 580  		seen[s.Source] = true
 581  		unique = append(unique, s)
 582  	}
 583  
 584  	// Remove inner statements that are contained within compound statements.
 585  	// Use line numbers when available: a statement is "inner" if its line
 586  	// number falls within the line range of a compound (multi-line) statement.
 587  	// Falls back to substring containment when line numbers are absent.
 588  	// Also filters case/comm clauses that belong inside a switch/select.
 589  	compoundTags := map[string]bool{"if": true, "for": true, "switch": true, "select": true}
 590  	innerTags := map[string]bool{"case": true, "comm": true}
 591  	var filtered []bodyStmt
 592  	for i, s := range unique {
 593  		contained := false
 594  
 595  		// Case/comm clauses are always inner to switch/select — filter them
 596  		// if any enclosing compound statement exists.
 597  		if innerTags[s.Tag] {
 598  			for j, other := range unique {
 599  				if i == j {
 600  					continue
 601  				}
 602  				if (s.Tag == "case" && (other.Tag == "switch")) ||
 603  					(s.Tag == "comm" && other.Tag == "select") {
 604  					// Check containment by line range or substring.
 605  					if s.LineNum > 0 && other.LineNum > 0 {
 606  						otherLines := strings.Count(other.Source, "\n") + 1
 607  						if s.LineNum > other.LineNum && s.LineNum <= other.LineNum+otherLines-1 {
 608  							contained = true
 609  							break
 610  						}
 611  					}
 612  					if strings.Contains(other.Source, s.Source) {
 613  						contained = true
 614  						break
 615  					}
 616  				}
 617  			}
 618  		}
 619  
 620  		// Line-number-based filtering for other inner statements.
 621  		if !contained && s.LineNum > 0 {
 622  			for j, other := range unique {
 623  				if i == j || !compoundTags[other.Tag] || other.LineNum == 0 {
 624  					continue
 625  				}
 626  				otherLines := strings.Count(other.Source, "\n") + 1
 627  				otherEnd := other.LineNum + otherLines - 1
 628  				if s.LineNum > other.LineNum && s.LineNum <= otherEnd {
 629  					contained = true
 630  					break
 631  				}
 632  			}
 633  		}
 634  
 635  		// Fallback: substring containment (original heuristic).
 636  		if !contained {
 637  			for j, other := range unique {
 638  				if i != j && len(other.Source) > len(s.Source) && strings.Contains(other.Source, s.Source) {
 639  					contained = true
 640  					break
 641  				}
 642  			}
 643  		}
 644  
 645  		if !contained {
 646  			filtered = append(filtered, s)
 647  		}
 648  	}
 649  
 650  	// Strip orphan break/continue/fallthrough — these are branch statements
 651  	// from loop/switch bodies that got placed at the top level of a function.
 652  	// They're only valid inside for/switch/select.
 653  	hasLoop := false
 654  	for _, s := range filtered {
 655  		if s.Tag == "for" || s.Tag == "switch" || s.Tag == "select" {
 656  			hasLoop = true
 657  			break
 658  		}
 659  		if strings.HasPrefix(strings.TrimSpace(s.Source), "for ") ||
 660  			strings.HasPrefix(strings.TrimSpace(s.Source), "switch ") ||
 661  			strings.HasPrefix(strings.TrimSpace(s.Source), "select {") {
 662  			hasLoop = true
 663  			break
 664  		}
 665  	}
 666  	if !hasLoop {
 667  		var clean []bodyStmt
 668  		for _, s := range filtered {
 669  			trimmed := strings.TrimSpace(s.Source)
 670  			if trimmed == "break" || trimmed == "continue" || trimmed == "fallthrough" ||
 671  				strings.HasPrefix(trimmed, "break ") || strings.HasPrefix(trimmed, "continue ") ||
 672  				s.Tag == "branch" {
 673  				continue
 674  			}
 675  			clean = append(clean, s)
 676  		}
 677  		filtered = clean
 678  	}
 679  
 680  	// Remove duplicate declarations within the function scope.
 681  	// Go allows re-declaration with := when at least one variable is new,
 682  	// but duplicate definitions are a common source of compile errors in
 683  	// emitted code. Keep the first definition, drop subsequent ones.
 684  	{
 685  		declaredIds := make(map[string]bool)
 686  		var deduped []bodyStmt
 687  		for _, s := range filtered {
 688  			defs := causal.ExtractDefines(s.Source)
 689  			if len(defs) == 0 {
 690  				deduped = append(deduped, s)
 691  				continue
 692  			}
 693  			conflict := false
 694  			for id := range defs {
 695  				if declaredIds[id] {
 696  					conflict = true
 697  					break
 698  				}
 699  			}
 700  			if conflict {
 701  				continue // drop duplicate declaration
 702  			}
 703  			for id := range defs {
 704  				declaredIds[id] = true
 705  			}
 706  			deduped = append(deduped, s)
 707  		}
 708  		filtered = deduped
 709  	}
 710  
 711  	// Order by dependency DAG with non-dependent shuffling.
 712  	ordered := orderBody(filtered)
 713  
 714  	for _, s := range ordered {
 715  		sublines := strings.Split(s.Source, "\n")
 716  		for _, sl := range sublines {
 717  			fmt.Fprintf(b, "\t%s\n", sl)
 718  		}
 719  	}
 720  }
 721  
 722  // orderBody builds a dependency DAG from define-use analysis,
 723  // topologically sorts into levels, and crypto/rand shuffles
 724  // within each level for anti-fingerprinting.
 725  func orderBody(stmts []bodyStmt) []bodyStmt {
 726  	if len(stmts) <= 1 {
 727  		return stmts
 728  	}
 729  
 730  	n := len(stmts)
 731  
 732  	// Extract defines and uses for each statement.
 733  	defines := make([]map[string]bool, n)
 734  	uses := make([]map[string]bool, n)
 735  	for i, s := range stmts {
 736  		defines[i] = causal.ExtractDefines(s.Source)
 737  		uses[i] = causal.ExtractUses(s.Source)
 738  	}
 739  
 740  	// Build dependency graph: deps[j] contains indices that j depends on.
 741  	deps := make([][]int, n)
 742  	for j := range n {
 743  		for i := range n {
 744  			if i == j {
 745  				continue
 746  			}
 747  			// j depends on i if j uses something i defines.
 748  			for id := range uses[j] {
 749  				if defines[i][id] {
 750  					deps[j] = append(deps[j], i)
 751  					break
 752  				}
 753  			}
 754  		}
 755  	}
 756  
 757  	// Topological sort into levels.
 758  	levels := topoLevels(n, deps)
 759  
 760  	// Sort within each level by source line number when available,
 761  	// falling back to crypto/rand shuffle when line numbers are absent.
 762  	for _, level := range levels {
 763  		hasLineNums := false
 764  		for _, idx := range level {
 765  			if stmts[idx].LineNum > 0 {
 766  				hasLineNums = true
 767  				break
 768  			}
 769  		}
 770  		if hasLineNums {
 771  			sort.Slice(level, func(a, b int) bool {
 772  				la, lb := stmts[level[a]].LineNum, stmts[level[b]].LineNum
 773  				if la != lb {
 774  					return la < lb
 775  				}
 776  				return level[a] < level[b]
 777  			})
 778  		} else {
 779  			cryptoShuffle(level)
 780  		}
 781  	}
 782  
 783  	// Flatten levels into ordered result.
 784  	result := make([]bodyStmt, 0, n)
 785  	for _, level := range levels {
 786  		for _, idx := range level {
 787  			result = append(result, stmts[idx])
 788  		}
 789  	}
 790  	return result
 791  }
 792  
 793  // topoLevels performs topological sort and groups nodes into levels.
 794  // Level 0 has no dependencies, level 1 depends only on level 0, etc.
 795  func topoLevels(n int, deps [][]int) [][]int {
 796  	// Compute in-degree.
 797  	inDeg := make([]int, n)
 798  	for j := range n {
 799  		inDeg[j] = len(deps[j])
 800  	}
 801  
 802  	// Collect level 0 (no dependencies).
 803  	var levels [][]int
 804  	remaining := make([]bool, n)
 805  	for i := range n {
 806  		remaining[i] = true
 807  	}
 808  
 809  	for {
 810  		var level []int
 811  		for i := range n {
 812  			if !remaining[i] {
 813  				continue
 814  			}
 815  			// Check if all dependencies are already placed.
 816  			allResolved := true
 817  			for _, dep := range deps[i] {
 818  				if remaining[dep] {
 819  					allResolved = false
 820  					break
 821  				}
 822  			}
 823  			if allResolved {
 824  				level = append(level, i)
 825  			}
 826  		}
 827  		if len(level) == 0 {
 828  			// Remaining nodes have circular dependencies.
 829  			// Add them in original order.
 830  			for i := range n {
 831  				if remaining[i] {
 832  					level = append(level, i)
 833  				}
 834  			}
 835  			levels = append(levels, level)
 836  			break
 837  		}
 838  		levels = append(levels, level)
 839  		for _, idx := range level {
 840  			remaining[idx] = false
 841  		}
 842  	}
 843  	return levels
 844  }
 845  
 846  // cryptoShuffle performs Fisher-Yates shuffle using crypto/rand.
 847  func cryptoShuffle(indices []int) {
 848  	for i := len(indices) - 1; i > 0; i-- {
 849  		var buf [8]byte
 850  		rand.Read(buf[:])
 851  		j := int(binary.LittleEndian.Uint64(buf[:]) % uint64(i+1))
 852  		indices[i], indices[j] = indices[j], indices[i]
 853  	}
 854  }
 855  
 856  // modulePath is the self-import prefix. Imports matching this are trusted.
 857  const modulePath = "git.mleku.dev/mleku/dendrite"
 858  
 859  // moduleRootOnce lazily finds the module root directory on disk.
 860  var (
 861  	moduleRootOnce sync.Once
 862  	moduleRootDir  string          // absolute path to the dendrite module root, or ""
 863  	subPkgCache    map[string]bool // cache: directory name → exists as sub-package
 864  )
 865  
 866  // findModuleRootDir locates the dendrite module root by walking up from cwd
 867  // looking for a go.mod that declares the module.
 868  func findModuleRootDir() string {
 869  	dir, err := os.Getwd()
 870  	if err != nil {
 871  		return ""
 872  	}
 873  	for {
 874  		modFile := filepath.Join(dir, "go.mod")
 875  		data, err := os.ReadFile(modFile)
 876  		if err == nil && strings.Contains(string(data), "module "+modulePath) {
 877  			return dir
 878  		}
 879  		parent := filepath.Dir(dir)
 880  		if parent == dir {
 881  			return "" // reached filesystem root
 882  		}
 883  		dir = parent
 884  	}
 885  }
 886  
 887  // isValidSubPkg checks if w is an actual sub-package directory in the dendrite
 888  // module that contains Go source files (not just sub-directories).
 889  // Caches results after the first filesystem scan.
 890  func isValidSubPkg(w string) bool {
 891  	moduleRootOnce.Do(func() {
 892  		moduleRootDir = findModuleRootDir()
 893  		subPkgCache = make(map[string]bool)
 894  		if moduleRootDir != "" {
 895  			entries, err := os.ReadDir(filepath.Join(moduleRootDir, "pkg"))
 896  			if err == nil {
 897  				for _, e := range entries {
 898  					if !e.IsDir() || strings.HasPrefix(e.Name(), ".") || strings.HasPrefix(e.Name(), "_") {
 899  						continue
 900  					}
 901  					// Only count as a package if it contains .go files.
 902  					subEntries, err := os.ReadDir(filepath.Join(moduleRootDir, "pkg", e.Name()))
 903  					if err != nil {
 904  						continue
 905  					}
 906  					for _, se := range subEntries {
 907  						if !se.IsDir() && strings.HasSuffix(se.Name(), ".go") {
 908  							subPkgCache[e.Name()] = true
 909  							break
 910  						}
 911  					}
 912  				}
 913  			}
 914  		}
 915  	})
 916  	return subPkgCache[w]
 917  }
 918  
 919  // inferImports determines which imports are needed based on body statements,
 920  // function signatures, var declarations, and field types. Three passes:
 921  //  1. Collect candidates (explicit from lattice + inferred from all text)
 922  //  2. Trust filter: reject anything that isn't stdlib or a self-import
 923  //  3. Usage prune: drop imports whose package name doesn't appear in text
 924  func inferImports(stmts []bodyStmt, importFrags []Fragment, funcs []funcDecl, vars []Fragment, fields []Fragment) []string {
 925  	// Pass 1: Collect candidates.
 926  	candidates := make(map[string]bool)
 927  
 928  	// Explicit imports from the lattice.
 929  	for _, imp := range importFrags {
 930  		candidates[imp.Value] = true
 931  	}
 932  
 933  	// Collect ALL text that may reference packages: body statements,
 934  	// function signatures, var declarations, and struct field types.
 935  	allText := &strings.Builder{}
 936  	for _, s := range stmts {
 937  		allText.WriteString(s.Source)
 938  		allText.WriteByte('\n')
 939  	}
 940  	for _, fd := range funcs {
 941  		allText.WriteString(fd.Signature)
 942  		allText.WriteByte('\n')
 943  	}
 944  	for _, v := range vars {
 945  		allText.WriteString(v.Value)
 946  		allText.WriteByte('\n')
 947  	}
 948  	for _, f := range fields {
 949  		allText.WriteString(f.Value)
 950  		allText.WriteByte('\n')
 951  	}
 952  	text := allText.String()
 953  
 954  	// Infer stdlib imports from body text.
 955  	// Only single-segment packages belong here. Multi-segment paths
 956  	// like "path/filepath" and "os/exec" are in multiPkgs below.
 957  	stdPkgs := map[string]string{
 958  		"fmt": "fmt.", "os": "os.", "io": "io.",
 959  		"strings": "strings.", "strconv": "strconv.",
 960  		"log": "log.", "time": "time.", "sync": "sync.",
 961  		"context": "context.", "math": "math.", "sort": "sort.",
 962  		"bytes": "bytes.", "errors": "errors.", "path": "path.",
 963  		"net": "net.", "regexp": "regexp.", "reflect": "reflect.",
 964  		"testing": "testing.", "embed": "embed.",
 965  		"bufio": "bufio.", "unicode": "unicode.",
 966  		"crypto": "crypto.", "hash": "hash.", "encoding": "encoding.",
 967  		"flag": "flag.", "slices": "slices.", "maps": "maps.",
 968  		"unsafe": "unsafe.",
 969  	}
 970  	// Multi-segment stdlib paths — package name differs from import path.
 971  	multiPkgs := map[string]string{
 972  		"net/http":        "http.",
 973  		"encoding/json":   "json.",
 974  		"encoding/hex":    "hex.",
 975  		"encoding/binary": "binary.",
 976  		"os/exec":         "exec.",
 977  		"os/signal":       "signal.",
 978  		"path/filepath":   "filepath.",
 979  		"crypto/rand":     "rand.",
 980  		"crypto/sha256":   "sha256.",
 981  		"crypto/ed25519":  "ed25519.",
 982  		"go/ast":          "ast.",
 983  		"go/parser":       "parser.",
 984  		"go/token":        "token.",
 985  		"go/format":       "format.",
 986  		"go/printer":      "printer.",
 987  		"math/big":        "big.",
 988  		"math/rand":       "rand.",
 989  		"io/fs":           "fs.",
 990  	}
 991  
 992  	for pkg, marker := range stdPkgs {
 993  		if strings.Contains(text, marker) {
 994  			candidates[`"`+pkg+`"`] = true
 995  		}
 996  	}
 997  	for path, marker := range multiPkgs {
 998  		if strings.Contains(text, marker) {
 999  			candidates[`"`+path+`"`] = true
1000  		}
1001  	}
1002  
1003  	// Infer self-module sub-package imports from body text.
1004  	// If the body uses "ratio.New(...)" and "ratio" is an actual sub-package
1005  	// directory, infer "git.mleku.dev/mleku/dendrite/pkg/ratio" as a candidate.
1006  	// Validates against the filesystem to avoid false positives from struct
1007  	// field access (e.g., "score.Behav.Float64()" where Behav is a field).
1008  	knownStdPkg := make(map[string]bool)
1009  	for pkg := range stdPkgs {
1010  		knownStdPkg[pkg] = true
1011  	}
1012  	for _, marker := range multiPkgs {
1013  		knownStdPkg[strings.TrimSuffix(marker, ".")] = true
1014  	}
1015  	words := identifiersInText(text)
1016  	for _, w := range words {
1017  		if knownStdPkg[w] {
1018  			continue
1019  		}
1020  		if !strings.Contains(text, w+".") {
1021  			continue
1022  		}
1023  		// Must be an actual sub-package directory on disk.
1024  		if !isValidSubPkg(w) {
1025  			continue
1026  		}
1027  		candidate := `"` + modulePath + "/pkg/" + w + `"`
1028  		if !candidates[candidate] {
1029  			candidates[candidate] = true
1030  		}
1031  	}
1032  
1033  	// Pass 2+3: Trust filter + usage prune.
1034  	var result []string
1035  	for imp := range candidates {
1036  		bare := strings.Trim(imp, `"`)
1037  
1038  		// Trust check: only stdlib and self-imports allowed.
1039  		if !isStdlib(bare) && !strings.HasPrefix(bare, modulePath) {
1040  			continue // untrusted external — drop
1041  		}
1042  
1043  		// Usage check: package name must appear as "pkg." in body text.
1044  		pkgName := extractPkgName(imp)
1045  		if strings.Contains(text, pkgName+".") {
1046  			result = append(result, imp)
1047  		}
1048  	}
1049  	sort.Strings(result)
1050  	return result
1051  }
1052  
1053  // isStdlib returns true if the import path is a Go standard library package.
1054  // stdlib paths have no dots in the first path segment.
1055  func isStdlib(importPath string) bool {
1056  	first := importPath
1057  	if idx := strings.IndexByte(importPath, '/'); idx >= 0 {
1058  		first = importPath[:idx]
1059  	}
1060  	return !strings.Contains(first, ".")
1061  }
1062  
1063  // extractPkgName returns the package name from an import path.
1064  // "fmt" → "fmt", "net/http" → "http", "git.mleku.dev/mleku/dendrite/pkg/axiom" → "axiom"
1065  func extractPkgName(importPath string) string {
1066  	bare := strings.Trim(importPath, `"`)
1067  	if idx := strings.LastIndex(bare, "/"); idx >= 0 {
1068  		return bare[idx+1:]
1069  	}
1070  	return bare
1071  }
1072  
1073  // hasOutputLiterals checks if any literal fragments look like program output.
1074  func hasOutputLiterals(literals []Fragment) bool {
1075  	for _, lit := range literals {
1076  		cat, _ := classifyLiteral(lit.Value)
1077  		if cat != "" {
1078  			return true
1079  		}
1080  	}
1081  	return false
1082  }
1083  
1084  // emitLegacyMain writes the self-logging main body (legacy mode).
1085  // Used when no body elements are available.
1086  func emitLegacyMain(b *strings.Builder, literals []Fragment, types []Fragment, funcs []funcDecl) {
1087  	typeNames := dedupFragNames(types)
1088  	funcNames := make([]string, 0)
1089  	methodNames := make([]string, 0)
1090  	for _, fd := range funcs {
1091  		if fd.IsMethod {
1092  			methodNames = append(methodNames, fd.Name)
1093  		} else {
1094  			funcNames = append(funcNames, fd.Name)
1095  		}
1096  	}
1097  
1098  	type scoredLiteral struct {
1099  		bare   string
1100  		cat    string
1101  		lockIn lattice.LockInDepth
1102  	}
1103  	var scored []scoredLiteral
1104  	seen := make(map[string]bool)
1105  	for _, f := range literals {
1106  		cat, bare := classifyLiteral(f.Value)
1107  		if cat == "" || seen[bare] {
1108  			continue
1109  		}
1110  		seen[bare] = true
1111  		scored = append(scored, scoredLiteral{bare, cat, f.LockIn})
1112  	}
1113  	sort.Slice(scored, func(i, j int) bool {
1114  		return scored[j].lockIn.Less(scored[i].lockIn)
1115  	})
1116  
1117  	if len(scored) == 0 {
1118  		return
1119  	}
1120  
1121  	b.WriteString("\t// Self-knowledge: the offspring counts its own structure.\n")
1122  	fmt.Fprintf(b, "\tnTypes := %d\n", len(typeNames))
1123  	fmt.Fprintf(b, "\tnFuncs := %d\n", len(funcNames))
1124  	fmt.Fprintf(b, "\tnMethods := %d\n", len(methodNames))
1125  	b.WriteString("\tnTotal := nTypes + nFuncs + nMethods\n")
1126  	b.WriteString("\t_ = nTotal\n")
1127  
1128  	for _, lit := range scored {
1129  		switch lit.cat {
1130  		case "format":
1131  			verbs := parseFormatVerbs(lit.bare)
1132  			if len(verbs) == 0 {
1133  				stripped := stripEscapes(lit.bare)
1134  				if stripped != "" {
1135  					fmt.Fprintf(b, "\tfmt.Println(%q)\n", stripped)
1136  				}
1137  				continue
1138  			}
1139  			args := make([]string, len(verbs))
1140  			intArgIdx := 0
1141  			intArgs := []string{"nTypes", "nFuncs", "nMethods", "nTotal"}
1142  			for i, v := range verbs {
1143  				switch v.verb {
1144  				case 'd':
1145  					args[i] = intArgs[intArgIdx%len(intArgs)]
1146  					intArgIdx++
1147  				case 's':
1148  					if i < len(typeNames) {
1149  						args[i] = fmt.Sprintf("%q", typeNames[i])
1150  					} else if i < len(funcNames) {
1151  						args[i] = fmt.Sprintf("%q", funcNames[i%len(funcNames)])
1152  					} else {
1153  						args[i] = `""`
1154  					}
1155  				case 'f':
1156  					args[i] = "float64(nTypes) / float64(nTotal+1) * 100"
1157  				case 'v':
1158  					args[i] = "nTotal"
1159  				case 'p':
1160  					args[i] = "0"
1161  				default:
1162  					args[i] = "nTotal"
1163  				}
1164  			}
1165  			fmtStr := cleanFormatString(lit.bare)
1166  			fmt.Fprintf(b, "\tfmt.Printf(\"%s\", %s)\n", fmtStr, strings.Join(args, ", "))
1167  		case "output":
1168  			stripped := stripEscapes(lit.bare)
1169  			if stripped != "" {
1170  				fmt.Fprintf(b, "\tfmt.Println(%q)\n", stripped)
1171  			}
1172  		}
1173  	}
1174  }
1175  
1176  // isOutputLiteral returns true if a string literal looks like program output.
1177  func isOutputLiteral(bare string) bool {
1178  	if bare == "" {
1179  		return false
1180  	}
1181  	if strings.Contains(bare, "/") {
1182  		return false
1183  	}
1184  	if len(bare) <= 2 {
1185  		return false
1186  	}
1187  	if !strings.ContainsAny(bare, " :=,.(){}[]!?%") && len(bare) < 20 {
1188  		return false
1189  	}
1190  	if strings.HasPrefix(bare, "json:") || strings.HasPrefix(bare, "yaml:") {
1191  		return false
1192  	}
1193  	return true
1194  }
1195  
1196  // classifyLiteral categorizes a string literal for emission.
1197  func classifyLiteral(raw string) (category string, bare string) {
1198  	if !strings.HasPrefix(raw, `"`) && !strings.HasPrefix(raw, "`") {
1199  		return "", ""
1200  	}
1201  	bare = strings.Trim(raw, `"`+"`")
1202  	if !isOutputLiteral(bare) {
1203  		return "", ""
1204  	}
1205  	if strings.Contains(bare, "%") {
1206  		return "format", bare
1207  	}
1208  	return "output", bare
1209  }
1210  
1211  // verbInfo describes a format verb found in a format string.
1212  type verbInfo struct {
1213  	verb byte
1214  }
1215  
1216  // parseFormatVerbs extracts format verbs from a printf-style format string.
1217  func parseFormatVerbs(s string) []verbInfo {
1218  	var verbs []verbInfo
1219  	i := 0
1220  	for i < len(s) {
1221  		if s[i] == '%' && i+1 < len(s) {
1222  			i++
1223  			if s[i] == '%' {
1224  				i++
1225  				continue
1226  			}
1227  			for i < len(s) && strings.ContainsRune("-+# 0", rune(s[i])) {
1228  				i++
1229  			}
1230  			for i < len(s) && s[i] >= '0' && s[i] <= '9' {
1231  				i++
1232  			}
1233  			if i < len(s) && s[i] == '.' {
1234  				i++
1235  				for i < len(s) && s[i] >= '0' && s[i] <= '9' {
1236  					i++
1237  				}
1238  			}
1239  			if i < len(s) {
1240  				verbs = append(verbs, verbInfo{verb: s[i]})
1241  				i++
1242  			}
1243  		} else {
1244  			i++
1245  		}
1246  	}
1247  	return verbs
1248  }
1249  
1250  // cleanFormatString converts a raw format string into a safe Go string
1251  // literal body for embedding inside double quotes.
1252  func cleanFormatString(bare string) string {
1253  	var b strings.Builder
1254  	b.Grow(len(bare))
1255  	for i := 0; i < len(bare); i++ {
1256  		switch bare[i] {
1257  		case '\\':
1258  			b.WriteString(`\\`)
1259  		case '\n':
1260  			b.WriteString(`\n`)
1261  		case '\r':
1262  			b.WriteString(`\r`)
1263  		case '\t':
1264  			b.WriteString(`\t`)
1265  		case '"':
1266  			b.WriteString(`\"`)
1267  		default:
1268  			b.WriteByte(bare[i])
1269  		}
1270  	}
1271  	return b.String()
1272  }
1273  
1274  // stripEscapes removes Go source escape sequences from a string.
1275  func stripEscapes(s string) string {
1276  	s = strings.ReplaceAll(s, `\n`, "")
1277  	s = strings.ReplaceAll(s, `\t`, "")
1278  	s = strings.ReplaceAll(s, `\r`, "")
1279  	for strings.Contains(s, "  ") {
1280  		s = strings.ReplaceAll(s, "  ", " ")
1281  	}
1282  	return strings.TrimSpace(s)
1283  }
1284  
1285  // dedupFragNames returns unique non-empty names from fragments.
1286  func dedupFragNames(frags []Fragment) []string {
1287  	seen := make(map[string]bool)
1288  	var names []string
1289  	for _, f := range frags {
1290  		if f.Value != "" && !seen[f.Value] {
1291  			seen[f.Value] = true
1292  			names = append(names, f.Value)
1293  		}
1294  	}
1295  	return names
1296  }
1297  
1298  // dedupNames returns unique non-empty names from a slice of fragments.
1299  // Kept for backward compatibility.
1300  func dedupNames(frags []Fragment) []string {
1301  	return dedupFragNames(frags)
1302  }
1303  
1304  // extractVarName pulls the variable name from a rendered var declaration.
1305  // "var ownSources embed.FS" → "ownSources"
1306  // Handles leading comments: "var // comment\nGitRef string" → "GitRef"
1307  func extractVarName(decl string) string {
1308  	// Process each line looking for the var/const name.
1309  	for _, line := range strings.Split(decl, "\n") {
1310  		line = strings.TrimSpace(line)
1311  		// Skip comment lines.
1312  		if strings.HasPrefix(line, "//") || line == "" {
1313  			continue
1314  		}
1315  		// Strip "var " or "const " prefix.
1316  		for _, prefix := range []string{"var ", "const "} {
1317  			if strings.HasPrefix(line, prefix) {
1318  				line = line[len(prefix):]
1319  				break
1320  			}
1321  		}
1322  		// First identifier token is the name (strip trailing comma for multi-var).
1323  		if idx := strings.IndexAny(line, " =,"); idx > 0 {
1324  			return line[:idx]
1325  		}
1326  		if line != "" {
1327  			return line
1328  		}
1329  	}
1330  	return ""
1331  }
1332  
1333  // emitDirectives writes any //go: directives associated with the named
1334  // declaration. Each directive's value is "assocName\x00//go:embed ..."
1335  func emitDirectives(b *strings.Builder, directives []Fragment, name string) {
1336  	for _, d := range directives {
1337  		parent, text := parseBodyValue(d.Value)
1338  		if parent == name && text != "" {
1339  			fmt.Fprintf(b, "%s\n", text)
1340  		}
1341  	}
1342  }
1343  
1344  // isValidDecl checks whether a var/const declaration string is syntactically
1345  // valid Go. It wraps the declaration in a minimal package and tries to parse it.
1346  func isValidDecl(decl string) bool {
1347  	// Quick reject: const/var without a value (iota members outside block).
1348  	trimmed := strings.TrimSpace(decl)
1349  	if strings.HasPrefix(trimmed, "const ") {
1350  		// "const Foo" with no = and no type — iota member, invalid standalone.
1351  		rest := strings.TrimPrefix(trimmed, "const ")
1352  		// Strip trailing comment.
1353  		if ci := strings.Index(rest, "//"); ci >= 0 {
1354  			rest = strings.TrimSpace(rest[:ci])
1355  		}
1356  		// Must have '=' for a standalone const, or be a typed const like "const X Type = val".
1357  		if !strings.Contains(rest, "=") {
1358  			return false
1359  		}
1360  	}
1361  	// Try to parse the declaration.
1362  	src := "package p\n" + decl + "\n"
1363  	fset := token.NewFileSet()
1364  	_, err := parser.ParseFile(fset, "", src, parser.SkipObjectResolution)
1365  	return err == nil
1366  }
1367  
1368  // extractReturnSig extracts the return type portion from a function signature.
1369  // "main()" → "", "Foo() string" → "string", "Bar() (int, error)" → "(int, error)"
1370  func extractReturnSig(sig string) string {
1371  	// Find the FIRST depth-0 closing ')' — this closes the parameter list.
1372  	// Everything after it is the return signature.
1373  	depth := 0
1374  	paramClose := -1
1375  	for i, c := range sig {
1376  		if c == '(' {
1377  			depth++
1378  		} else if c == ')' {
1379  			depth--
1380  			if depth == 0 {
1381  				paramClose = i
1382  				break
1383  			}
1384  		}
1385  	}
1386  	if paramClose < 0 || paramClose >= len(sig)-1 {
1387  		return ""
1388  	}
1389  	ret := strings.TrimSpace(sig[paramClose+1:])
1390  	if ret == "" || ret == "{" {
1391  		return ""
1392  	}
1393  	return ret
1394  }
1395  
1396  // zeroReturn generates a return statement with zero values for the given
1397  // return type signature. Handles single types, named returns, and tuples.
1398  func zeroReturn(retSig string) string {
1399  	retSig = strings.TrimSpace(retSig)
1400  	if retSig == "" {
1401  		return ""
1402  	}
1403  
1404  	// Named returns: "(x int, err error)" — just "return" suffices.
1405  	if strings.HasPrefix(retSig, "(") {
1406  		inner := strings.Trim(retSig, "()")
1407  		parts := strings.Split(inner, ",")
1408  		// Check if these are named (have both name and type).
1409  		for _, p := range parts {
1410  			fields := strings.Fields(strings.TrimSpace(p))
1411  			if len(fields) >= 2 {
1412  				return "return" // named returns — zero-initialized
1413  			}
1414  		}
1415  		// Unnamed tuple: generate zero values for each.
1416  		var zeros []string
1417  		for _, p := range parts {
1418  			zeros = append(zeros, zeroValue(strings.TrimSpace(p)))
1419  		}
1420  		return "return " + strings.Join(zeros, ", ")
1421  	}
1422  
1423  	// Single return type.
1424  	return "return " + zeroValue(retSig)
1425  }
1426  
1427  // zeroValue returns the zero-value literal for a Go type.
1428  func zeroValue(typ string) string {
1429  	typ = strings.TrimSpace(typ)
1430  	switch {
1431  	case typ == "string":
1432  		return `""`
1433  	case typ == "bool":
1434  		return "false"
1435  	case typ == "error":
1436  		return "nil"
1437  	case typ == "int" || typ == "int8" || typ == "int16" || typ == "int32" || typ == "int64" ||
1438  		typ == "uint" || typ == "uint8" || typ == "uint16" || typ == "uint32" || typ == "uint64" ||
1439  		typ == "float32" || typ == "float64" || typ == "byte" || typ == "rune":
1440  		return "0"
1441  	case strings.HasPrefix(typ, "*") || strings.HasPrefix(typ, "[]") ||
1442  		strings.HasPrefix(typ, "map[") || strings.HasPrefix(typ, "chan ") ||
1443  		strings.HasPrefix(typ, "func(") || strings.HasPrefix(typ, "<-chan"):
1444  		return "nil"
1445  	case strings.Contains(typ, "."):
1446  		// Package-qualified type — assume it's a struct or interface.
1447  		return typ + "{}"
1448  	default:
1449  		// Unknown type — use zero value by name.
1450  		return typ + "{}"
1451  	}
1452  }
1453  
1454  // identifiersInText extracts unique identifiers from Go source text
1455  // that appear before a dot (potential package references like "ratio.New").
1456  func identifiersInText(text string) []string {
1457  	seen := make(map[string]bool)
1458  	var result []string
1459  	for i := 0; i < len(text)-1; i++ {
1460  		if text[i] == '.' && i > 0 {
1461  			// Walk back to find the identifier.
1462  			j := i - 1
1463  			for j >= 0 && isIdentChar(rune(text[j])) {
1464  				j--
1465  			}
1466  			word := text[j+1 : i]
1467  			if len(word) >= 2 && !seen[word] {
1468  				// Skip single-char receiver variables and common Go keywords.
1469  				seen[word] = true
1470  				result = append(result, word)
1471  			}
1472  		}
1473  	}
1474  	return result
1475  }
1476  
1477  // hasUndefinedRefs checks whether a var/const declaration references
1478  // package-qualified identifiers (like "hash.Len" or "_l.Get(...)") where
1479  // the package isn't in the known imports. Returns true if there are
1480  // references that can't be resolved.
1481  func hasUndefinedRefs(decl string, knownPkgs map[string]bool) bool {
1482  	// Strip the "var name" / "const name" prefix to get the initializer.
1483  	// Look for patterns like "identifier." that suggest package references.
1484  	for i := 0; i < len(decl)-1; i++ {
1485  		if decl[i] == '.' && i > 0 {
1486  			// Walk back to find the identifier before the dot.
1487  			j := i - 1
1488  			for j >= 0 && isIdentChar(rune(decl[j])) {
1489  				j--
1490  			}
1491  			pkg := decl[j+1 : i]
1492  			if pkg == "" || pkg == "x" {
1493  				continue // receiver variable, not a package
1494  			}
1495  			// Skip if it looks like a method call on a known variable
1496  			// (single lowercase letter or "err", "ctx", etc.)
1497  			if len(pkg) == 1 && pkg[0] >= 'a' && pkg[0] <= 'z' {
1498  				continue
1499  			}
1500  			// Check if this package is in our import set.
1501  			if pkg != "" && !knownPkgs[pkg] {
1502  				// Check if it's a commonly available identifier
1503  				// (builtin types like "reflect", etc.)
1504  				if !isBuiltinIdent(pkg) {
1505  					return true
1506  				}
1507  			}
1508  		}
1509  	}
1510  	return false
1511  }
1512  
1513  // isBuiltinIdent returns true for Go built-in identifiers and common
1514  // receiver variable names that aren't package references.
1515  func isBuiltinIdent(name string) bool {
1516  	switch name {
1517  	case "true", "false", "nil", "iota",
1518  		"int", "int8", "int16", "int32", "int64",
1519  		"uint", "uint8", "uint16", "uint32", "uint64",
1520  		"float32", "float64", "complex64", "complex128",
1521  		"string", "bool", "byte", "rune", "error", "any",
1522  		"make", "new", "len", "cap", "append", "copy", "delete",
1523  		"close", "panic", "recover", "print", "println",
1524  		"err", "ctx", "ok", "self":
1525  		return true
1526  	}
1527  	return false
1528  }
1529  
1530  // isValidReceiver checks that a method receiver type is a simple identifier
1531  // or pointer to identifier (e.g. "Foo" or "*Foo"), not a garbled signature.
1532  func isValidReceiver(recv string) bool {
1533  	r := strings.TrimPrefix(recv, "*")
1534  	if r == "" {
1535  		return false
1536  	}
1537  	for _, c := range r {
1538  		if !isIdentChar(c) {
1539  			return false
1540  		}
1541  	}
1542  	return true
1543  }
1544  
1545  func isIdentChar(c rune) bool {
1546  	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'
1547  }
1548  
1549  // aliasCollisions detects import paths that resolve to the same package name
1550  // and adds aliases to resolve collisions. For example, if both "crypto" and
1551  // "git.mleku.dev/mleku/dendrite/pkg/crypto" are imported, the latter becomes
1552  // "dcrypto" aliased.
1553  func aliasCollisions(imports []string) []string {
1554  	type entry struct {
1555  		path  string
1556  		pkg   string
1557  		index int
1558  	}
1559  	entries := make([]entry, len(imports))
1560  	byPkg := make(map[string][]int)
1561  
1562  	for i, imp := range imports {
1563  		bare := strings.Trim(imp, `"`)
1564  		pkg := extractPkgName(imp)
1565  		entries[i] = entry{path: bare, pkg: pkg, index: i}
1566  		byPkg[pkg] = append(byPkg[pkg], i)
1567  	}
1568  
1569  	result := make([]string, len(imports))
1570  	copy(result, imports)
1571  
1572  	for pkg, indices := range byPkg {
1573  		if len(indices) <= 1 {
1574  			continue
1575  		}
1576  		// Keep the shortest path (likely stdlib) without alias.
1577  		// Alias the others with a prefix.
1578  		sort.Slice(indices, func(a, b int) bool {
1579  			return len(entries[indices[a]].path) < len(entries[indices[b]].path)
1580  		})
1581  		for k := 1; k < len(indices); k++ {
1582  			idx := indices[k]
1583  			alias := fmt.Sprintf("%s%d", pkg, k)
1584  			result[idx] = fmt.Sprintf("%s %q", alias, entries[idx].path)
1585  		}
1586  	}
1587  	return result
1588  }
1589  
1590  // sanitizeGoSource post-processes emitted Go source:
1591  // 1. Always strip orphan break/continue/goto (valid syntax, invalid semantics)
1592  // 2. If parsing still fails, remove invalid top-level declarations
1593  func sanitizeGoSource(source string) (string, error) {
1594  	// Always strip orphan branches — go/parser accepts them as valid syntax,
1595  	// but the Go compiler rejects break/continue outside loops.
1596  	source = stripOrphanBranches(source)
1597  
1598  	fset := token.NewFileSet()
1599  	_, err := parser.ParseFile(fset, "output.go", source, parser.SkipObjectResolution|parser.AllErrors|parser.ParseComments)
1600  	if err == nil {
1601  		return source, nil
1602  	}
1603  
1604  	// Parse failed. Salvage by removing invalid top-level declarations.
1605  	return repairSource(source)
1606  }
1607  
1608  // stripOrphanBranches removes break/continue/goto statements that appear
1609  // outside of for/switch/select blocks. Uses character-level brace counting
1610  // that ignores braces inside string literals and comments to avoid being
1611  // confused by struct literals like `Type{}`.
1612  func stripOrphanBranches(source string) string {
1613  	lines := strings.Split(source, "\n")
1614  	var result []string
1615  
1616  	// Track nesting of for loops (for continue) and all loop-like constructs
1617  	// (for/switch/select, for break). Continue is ONLY valid in for loops.
1618  	forDepth := 0   // for loops only
1619  	breakDepth := 0 // for + switch + select
1620  	braceDepth := 0
1621  	var forBraceStack []int   // brace depths where for loops start
1622  	var breakBraceStack []int // brace depths where any break-accepting block starts
1623  	inBlockComment := false
1624  
1625  	for _, line := range lines {
1626  		trimmed := strings.TrimSpace(line)
1627  
1628  		// Classify block-opening statements.
1629  		isFor := strings.HasPrefix(trimmed, "for ") || trimmed == "for {" ||
1630  			strings.HasPrefix(trimmed, "for range ")
1631  		isBreakable := isFor ||
1632  			strings.HasPrefix(trimmed, "switch ") || trimmed == "switch {" ||
1633  			strings.HasPrefix(trimmed, "select ") || trimmed == "select {"
1634  
1635  		// Count braces at character level, skipping strings and comments.
1636  		lineOpens, lineCloses := countBraces(line, &inBlockComment)
1637  
1638  		if isFor && lineOpens > 0 {
1639  			forBraceStack = append(forBraceStack, braceDepth+1)
1640  			forDepth++
1641  		}
1642  		if isBreakable && lineOpens > 0 {
1643  			breakBraceStack = append(breakBraceStack, braceDepth+1)
1644  			breakDepth++
1645  		}
1646  
1647  		braceDepth += lineOpens - lineCloses
1648  
1649  		// Pop stacks when we close past their level.
1650  		for len(forBraceStack) > 0 && braceDepth < forBraceStack[len(forBraceStack)-1] {
1651  			forBraceStack = forBraceStack[:len(forBraceStack)-1]
1652  			forDepth--
1653  		}
1654  		for len(breakBraceStack) > 0 && braceDepth < breakBraceStack[len(breakBraceStack)-1] {
1655  			breakBraceStack = breakBraceStack[:len(breakBraceStack)-1]
1656  			breakDepth--
1657  		}
1658  
1659  		// Strip orphan branches and goto.
1660  		if strings.HasPrefix(trimmed, "goto ") {
1661  			continue // always strip goto — labels rarely survive emission
1662  		}
1663  		// continue is only valid in for loops
1664  		if forDepth <= 0 && (trimmed == "continue" || strings.HasPrefix(trimmed, "continue ")) {
1665  			continue
1666  		}
1667  		// break is valid in for/switch/select
1668  		if breakDepth <= 0 && (trimmed == "break" || strings.HasPrefix(trimmed, "break ")) {
1669  			continue
1670  		}
1671  		// fallthrough and case clauses only valid in switch
1672  		if breakDepth <= 0 {
1673  			if trimmed == "fallthrough" || strings.HasPrefix(trimmed, "case ") ||
1674  				trimmed == "default:" {
1675  				continue
1676  			}
1677  		}
1678  
1679  		result = append(result, line)
1680  	}
1681  
1682  	return strings.Join(result, "\n")
1683  }
1684  
1685  // countBraces counts `{` and `}` in a line, skipping those inside string
1686  // literals (both "" and ``) and comments. Tracks block comment state
1687  // across lines via the inBlockComment pointer.
1688  func countBraces(line string, inBlockComment *bool) (opens, closes int) {
1689  	inString := false
1690  	inRawString := false
1691  	inLineComment := false
1692  	escaped := false
1693  
1694  	for i := 0; i < len(line); i++ {
1695  		c := line[i]
1696  
1697  		if escaped {
1698  			escaped = false
1699  			continue
1700  		}
1701  
1702  		if *inBlockComment {
1703  			if c == '*' && i+1 < len(line) && line[i+1] == '/' {
1704  				*inBlockComment = false
1705  				i++ // skip '/'
1706  			}
1707  			continue
1708  		}
1709  
1710  		if inLineComment {
1711  			continue
1712  		}
1713  
1714  		if inString {
1715  			if c == '\\' {
1716  				escaped = true
1717  			} else if c == '"' {
1718  				inString = false
1719  			}
1720  			continue
1721  		}
1722  
1723  		if inRawString {
1724  			if c == '`' {
1725  				inRawString = false
1726  			}
1727  			continue
1728  		}
1729  
1730  		// Not inside any string or comment.
1731  		switch c {
1732  		case '"':
1733  			inString = true
1734  		case '`':
1735  			inRawString = true
1736  		case '/':
1737  			if i+1 < len(line) {
1738  				if line[i+1] == '/' {
1739  					inLineComment = true
1740  					i++
1741  				} else if line[i+1] == '*' {
1742  					*inBlockComment = true
1743  					i++
1744  				}
1745  			}
1746  		case '{':
1747  			opens++
1748  		case '}':
1749  			closes++
1750  		}
1751  	}
1752  	return
1753  }
1754  
1755  // repairSource splits Go source into top-level declaration blocks and
1756  // re-assembles only the ones that parse successfully.
1757  func repairSource(source string) (string, error) {
1758  	lines := strings.Split(source, "\n")
1759  
1760  	var header strings.Builder // package + import
1761  	var decls []string         // individual top-level declarations
1762  	var current strings.Builder
1763  
1764  	inImport := false
1765  	headerDone := false
1766  	braceDepth := 0
1767  
1768  	for _, line := range lines {
1769  		trimmed := strings.TrimSpace(line)
1770  
1771  		// Package and import go into the header.
1772  		if !headerDone {
1773  			if strings.HasPrefix(trimmed, "package ") {
1774  				header.WriteString(line + "\n")
1775  				continue
1776  			}
1777  			if strings.HasPrefix(trimmed, "import") {
1778  				inImport = true
1779  				header.WriteString(line + "\n")
1780  				if strings.Contains(trimmed, "(") && !strings.Contains(trimmed, ")") {
1781  					continue
1782  				}
1783  				if strings.Contains(trimmed, ")") || !strings.Contains(trimmed, "(") {
1784  					inImport = false
1785  					headerDone = true
1786  				}
1787  				continue
1788  			}
1789  			if inImport {
1790  				header.WriteString(line + "\n")
1791  				if trimmed == ")" {
1792  					inImport = false
1793  					headerDone = true
1794  				}
1795  				continue
1796  			}
1797  			headerDone = true
1798  		}
1799  
1800  		// Track brace depth to find declaration boundaries.
1801  		for _, c := range line {
1802  			if c == '{' {
1803  				braceDepth++
1804  			} else if c == '}' {
1805  				braceDepth--
1806  			}
1807  		}
1808  
1809  		current.WriteString(line + "\n")
1810  
1811  		// At brace depth 0 and a non-empty line, we've completed a declaration.
1812  		if braceDepth <= 0 && trimmed != "" {
1813  			decl := current.String()
1814  			if strings.TrimSpace(decl) != "" {
1815  				decls = append(decls, decl)
1816  			}
1817  			current.Reset()
1818  			braceDepth = 0
1819  		}
1820  	}
1821  	// Flush remaining.
1822  	if s := current.String(); strings.TrimSpace(s) != "" {
1823  		decls = append(decls, s)
1824  	}
1825  
1826  	// Validate each declaration by attempting to parse it.
1827  	// Track declared names to prevent redeclarations across types, vars, and funcs.
1828  	var validDecls strings.Builder
1829  	hdr := header.String()
1830  	declaredNames := make(map[string]bool)
1831  	for _, decl := range decls {
1832  		test := hdr + "\n" + decl
1833  		fset := token.NewFileSet()
1834  		_, err := parser.ParseFile(fset, "", test, parser.SkipObjectResolution|parser.AllErrors|parser.ParseComments)
1835  		if err != nil {
1836  			continue
1837  		}
1838  		// Extract the declaration name and check for redeclarations.
1839  		name := extractDeclName(strings.TrimSpace(decl))
1840  		if name != "" && declaredNames[name] {
1841  			continue // skip redeclaration
1842  		}
1843  		if name != "" {
1844  			declaredNames[name] = true
1845  		}
1846  		validDecls.WriteString(decl)
1847  		validDecls.WriteString("\n")
1848  	}
1849  
1850  	result := hdr + "\n" + validDecls.String()
1851  
1852  	// Don't use go/format — it strips unused imports which breaks the
1853  	// dependency chain. Return the filtered result directly.
1854  	if validDecls.Len() > 0 {
1855  		return result, nil
1856  	}
1857  
1858  	return "", fmt.Errorf("no valid declarations found")
1859  }
1860  
1861  // extractDeclName extracts the declared name from a top-level declaration.
1862  // "type Foo struct {" → "Foo", "func Bar() {" → "Bar", "var x int" → "x",
1863  // "func (r *T) Method() {" → "" (methods don't conflict with types/vars).
1864  func extractDeclName(decl string) string {
1865  	decl = strings.TrimSpace(decl)
1866  	switch {
1867  	case strings.HasPrefix(decl, "type "):
1868  		rest := decl[5:]
1869  		if idx := strings.IndexAny(rest, " ={"); idx > 0 {
1870  			return rest[:idx]
1871  		}
1872  		return rest
1873  	case strings.HasPrefix(decl, "var "):
1874  		rest := decl[4:]
1875  		if idx := strings.IndexAny(rest, " ="); idx > 0 {
1876  			return rest[:idx]
1877  		}
1878  		return rest
1879  	case strings.HasPrefix(decl, "const "):
1880  		rest := decl[6:]
1881  		if idx := strings.IndexAny(rest, " ="); idx > 0 {
1882  			return rest[:idx]
1883  		}
1884  		return rest
1885  	case strings.HasPrefix(decl, "func "):
1886  		rest := decl[5:]
1887  		// Method: "func (x *T) Name(..." → skip (methods don't conflict)
1888  		if strings.HasPrefix(rest, "(") {
1889  			return ""
1890  		}
1891  		// Plain function: "func Name(..." → extract Name
1892  		if idx := strings.IndexByte(rest, '('); idx > 0 {
1893  			return rest[:idx]
1894  		}
1895  		return ""
1896  	}
1897  	return ""
1898  }
1899