Skip to content

refactor: split compiler_yaml.go (1262 lines) into focused modules#45494

Merged
pelikhan merged 5 commits into
mainfrom
copilot/file-diet-refactor-compiler-yaml
Jul 15, 2026
Merged

refactor: split compiler_yaml.go (1262 lines) into focused modules#45494
pelikhan merged 5 commits into
mainfrom
copilot/file-diet-refactor-compiler-yaml

Conversation

Copilot AI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

pkg/workflow/compiler_yaml.go had grown to 1262 lines across 5 unrelated functional domains, exceeding the 800-line threshold and making the file hard to navigate and maintain.

Changes

Extracted into 4 new files, leaving compiler_yaml.go as a thin orchestration layer:

File Lines Responsibility
compiler_yaml.go 221 Orchestration: buildJobsAndValidate, generateYAML, generateWorkflowBody
compiler_yaml_normalize.go 167 YAML text normalization: blank-line collapsing, trailing-whitespace trimming, block-scalar detection
compiler_yaml_header.go 220 Header/metadata emission: generateWorkflowHeader, effectiveStrictMode, effectiveSafeUpdate
compiler_yaml_prompt.go 374 Prompt assembly: chunking, import resolution, expression mapping, runtime-import macros
compiler_yaml_steps.go 310 Step generation: pre/post/pre-agent steps, generateCreateAwInfo, output collection

All functions remain in the same package with identical signatures — purely a file-boundary split with no behavior changes.

Extract distinct functional domains from the 1262-line compiler_yaml.go
into 4 new focused files:

- compiler_yaml_normalize.go: YAML text normalization utilities
  (normalizeBlankLines, countLeadingSpaces, blockScalarHeaderIndentForLine)
- compiler_yaml_header.go: YAML header/metadata emission
  (generateWorkflowHeader, effectiveStrictMode, effectiveSafeUpdate)
- compiler_yaml_prompt.go: Prompt assembly and chunking
  (generatePrompt, splitContentIntoChunks, extractPromptChunksFromMarkdown,
  writePromptBashStep, resolveWorkspaceRoot)
- compiler_yaml_steps.go: Individual step generation
  (generatePreSteps, generatePostSteps, generatePreAgentSteps,
  writeStepsSection, generateCreateAwInfo, generateOutputCollectionStep)

compiler_yaml.go trimmed to top-level orchestration only:
  (buildJobsAndValidate, generateYAML, generateWorkflowBody)

All tests pass. No behavior changes.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor pkg/workflow/compiler_yaml.go into focused modules refactor: split compiler_yaml.go (1262 lines) into focused modules Jul 14, 2026
Copilot AI requested a review from pelikhan July 14, 2026 14:13
@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage

Field Value
Category refactor
Risk 🔴 High
Score 60/100 (impact:28, urgency:16, quality:16)
Action batch_review

Splits 1,262-line compiler_yaml.go into 4 focused modules. Large refactor touching a critical compiler component. Review together with #45526.

Generated by 🔧 PR Triage Agent · 171 AIC · ⌖ 7.66 AIC · ⊞ 5.6K ·

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Triage — Run §29379921158

Field Value
Category refactor
Risk 🔴 high
Score 60 / 100
Action 🔍 batch_review
Batch compiler-refactor

Score breakdown: impact 25 + urgency 12 + quality 23

Rationale: Splits compiler_yaml.go (1262 lines) into 4 focused modules (5 files, +1071/−1041). Draft. High-risk refactor — good test coverage required. Batch with other compiler changes if any.

Generated by 🔧 PR Triage Agent · 197.2 AIC · ⌖ 5.45 AIC · ⊞ 5.6K ·

@pelikhan pelikhan marked this pull request as ready for review July 15, 2026 04:11
Copilot AI review requested due to automatic review settings July 15, 2026 04:11
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

No test files were added or modified in this PR. Test Quality Sentinel skipped.

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors the YAML compiler into focused modules while preserving existing behavior and package-level APIs.

Changes:

  • Retains orchestration in compiler_yaml.go.
  • Extracts header, normalization, prompt, and step generation logic into dedicated files.
Show a summary per file
File Description
pkg/workflow/compiler_yaml.go Keeps core YAML compilation orchestration.
pkg/workflow/compiler_yaml_header.go Contains header and strict-mode logic.
pkg/workflow/compiler_yaml_normalize.go Contains YAML whitespace normalization.
pkg/workflow/compiler_yaml_prompt.go Contains prompt assembly and import handling.
pkg/workflow/compiler_yaml_steps.go Contains workflow step generation.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 5/5 changed files
  • Comments generated: 0
  • Review effort level: Medium

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean mechanical split — no logic changes, imports correctly distributed, shared compilerYamlLog logger works fine across same-package files. LGTM.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · 31 AIC · ⌖ 4.93 AIC · ⊞ 5K

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found. Clean mechanical file-boundary split — all extracted functions are verbatim copies in the same package with correct per-file imports. No behavior changes, no visibility changes, no import cycles.

🔎 Code quality review by PR Code Quality Reviewer · 72.7 AIC · ⌖ 4.26 AIC · ⊞ 5.6K
Comment /review to run again

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (1,071 new lines in pkg/workflow/) but does not have a linked Architecture Decision Record (ADR).

Draft ADR committed: docs/adr/45494-split-compiler-yaml-into-focused-modules.md — review and complete it before merging.

This PR cannot merge until an ADR is linked in the PR body.

What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff

  2. Complete the missing sections — add context the AI could not infer, refine the decision rationale, and list real alternatives you considered

  3. Commit the finalized ADR to docs/adr/ on your branch

  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-45494: Split compiler_yaml.go into Focused Single-Domain Modules

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

Why ADRs Matter

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.

Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 0042-use-postgresql.md for PR #42).

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · 57.8 AIC · ⌖ 10.1 AIC · ⊞ 8.5K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /codebase-design — observations only, no blocking issues.

📋 Key Themes & Highlights

Key Themes

  • Misplaced policy methods: effectiveStrictMode / effectiveSafeUpdate live in _header.go but are called from _steps.go and compiler.go. A cross-cutting policy method in a domain-named file misleads readers about where to look.
  • Invisible shared logger: compilerYamlLog is declared in compiler_yaml.go and referenced across all new modules. For a refactor whose goal is focused modules, this is harmless today but creates hidden coupling that should be addressed to complete the decomposition.
  • Naming collision: compiler_yaml_steps.go clashes with the existing compiler_yaml_step_*.go naming pattern already present in the package.

Positive Highlights

  • ✅ Clear, well-motivated split — 1262 lines → 5 focused files, zero behavior changes
  • ✅ The PR description is excellent: table of responsibilities makes the intent obvious
  • compiler_yaml_normalize.go is a clean self-contained module with no cross-dependencies
  • ✅ All existing tests continue to pass through the same public signatures
  • ✅ The diff is mechanically safe — only file boundaries changed, no logic moved

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 59.6 AIC · ⌖ 4.72 AIC · ⊞ 6.7K
Comment /matt to run again

Comment thread pkg/workflow/compiler_yaml_header.go Outdated
// Priority: CLI flag (c.strictMode) > frontmatter strict field > default (true).
// This should be used when emitting metadata/env vars to correctly reflect the
// workflow's strictness as inferred from the source (frontmatter).
func (c *Compiler) effectiveStrictMode(frontmatter map[string]any) bool {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] effectiveStrictMode and effectiveSafeUpdate are policy methods used by compiler_yaml_steps.go and compiler.go, not just the header — placing them in _header.go creates a semantically misleading home.

💡 Suggestion

Move these two methods into a dedicated compiler_yaml_policy.go (or keep them in compiler_yaml.go as part of the orchestration layer). Their placement in the header file implies they are header-specific, but callers span at least three files:

  • compiler_yaml_header.go (line 74)
  • compiler_yaml_steps.go (line 174)
  • compiler.go (line 459)

A module whose name implies one responsibility (_header) but hosts cross-cutting policy methods is a depth-design smell: the interface no longer matches the implementation.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved effectiveStrictMode and effectiveSafeUpdate to a new compiler_yaml_policy.go. They're no longer in _header.go — the policy file is a neutral home for cross-cutting compiler policy that is consumed by the header, step-lifecycle, and compiler.go layers alike. Committed in 94deb83.

"github.com/github/gh-aw/pkg/workflow/compilerenv"
)

var compilerYamlLog = logger.New("workflow:compiler_yaml")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] compilerYamlLog is declared in compiler_yaml.go but is used across the three new files (_prompt.go, _steps.go, _header.go) via implicit package-level sharing. This invisible dependency makes each extracted module harder to understand in isolation.

💡 Suggestion

Each extracted file should either:

  1. Declare its own logger scoped to its domain (e.g. var compilerYamlPromptLog = logger.New("workflow:compiler_yaml:prompt")), or
  2. Accept a logger through a parameter/interface if shared state is intentional.

Using a single package-level logger across 5 files silently couples them and makes it impossible to tune log verbosity per domain. Option 1 aligns better with the stated goal of focused modules.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each extracted file now declares its own domain-scoped logger: compilerYamlHeaderLog (workflow:compiler_yaml:header), compilerYamlPromptLog (workflow:compiler_yaml:prompt), and compilerYamlStepLifecycleLog (workflow:compiler_yaml:steps). The orchestration file keeps compilerYamlLog. All call sites in the three extracted files were updated to use the local logger. Committed in 94deb83.

"github.com/github/gh-aw/pkg/workflow/compilerenv"
)

func (c *Compiler) generatePreSteps(yaml *strings.Builder, data *WorkflowData) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] The new compiler_yaml_steps.go conflicts with the naming pattern of compiler_yaml_step_generation.go and compiler_yaml_step_conversion.go. Plural _steps vs singular _step_* is ambiguous about each file's scope.

💡 Suggestion

Consider renaming to follow the existing compiler_yaml_step_ prefix, e.g. compiler_yaml_step_lifecycle.go (pre/post/pre-agent hooks) or splitting into the appropriate existing files. This avoids confusing rg "compiler_yaml_step" navigation.

@copilot please address this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed compiler_yaml_steps.gocompiler_yaml_step_lifecycle.go so it follows the established compiler_yaml_step_ prefix used by compiler_yaml_step_generation.go and compiler_yaml_step_conversion.go. This keeps rg "compiler_yaml_step" navigation consistent. Committed in 94deb83.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot please run the pr-finisher skill, address the unresolved design feedback below, make sure the ADR work is completed and linked in the PR body, then rerun checks.

Unresolved review threads (newest first):

Run: https://github.com/github/gh-aw/actions/runs/29389971239

Generated by 👨‍🍳 PR Sous Chef · 11.7 AIC · ⌖ 7.11 AIC · ⊞ 7.5K ·
Comment /souschef to run again

Copilot AI and others added 2 commits July 15, 2026 05:09
- Move effectiveStrictMode/effectiveSafeUpdate to compiler_yaml_policy.go
  (cross-cutting policy used by header, steps, and compiler.go should
  not live in _header.go which implies header-specific scope)
- Add per-domain loggers to compiler_yaml_header.go, compiler_yaml_prompt.go,
  and compiler_yaml_step_lifecycle.go (workflow:compiler_yaml:{header,prompt,steps})
  so each module can be tuned independently
- Rename compiler_yaml_steps.go -> compiler_yaml_step_lifecycle.go to follow
  the existing compiler_yaml_step_* naming convention used by
  compiler_yaml_step_generation.go and compiler_yaml_step_conversion.go
- Update ADR-45494 status Draft->Accepted and reflect the above three design
  decisions with rationale

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
…rify ADR file list

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI requested a review from gh-aw-bot July 15, 2026 05:11
@pelikhan pelikhan merged commit 610fa4e into main Jul 15, 2026
36 checks passed
@pelikhan pelikhan deleted the copilot/file-diet-refactor-compiler-yaml branch July 15, 2026 05:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[file-diet] Refactor pkg/workflow/compiler_yaml.go (1262 lines) into focused modules

4 participants