Skip to content

refactor: stage DAG spec compiler - #2186

Merged
yohamta0 merged 6 commits into
mainfrom
refactor/spec-compiler-stages
May 21, 2026
Merged

yohamta0 merged 6 commits into
mainfrom
refactor/spec-compiler-stages

Conversation

@yohamta0

@yohamta0 yohamta0 commented May 20, 2026 •

Copy link
Copy Markdown
Member

Summary

Refactor the DAG spec compiler internals into explicit stages while preserving the public spec.Load interface and existing base-config inheritance behavior.

Changes

  • Split DAG field compilation into named metadata, params/env/defaults, execution placement, full-output/interaction/retention, action graph, and validation stages.
  • Split step compilation into staged transformer, action expansion, and validation phases.
  • Preserve inherited base DAG fields, handlers, steps, and warnings during staged action graph construction.
  • Add regression tests for base-config step inheritance, partial handler overrides, and inherited warning deduplication.
  • Stabilize the queued-abort preservation test by asserting through the run-specific lookup path.

Related Issues

N/A

Checklist

  • Code follows the project style guidelines
  • Self-review of the code has been performed
  • Tests have been added or updated as needed
  • Documentation has been updated as needed
  • Changes have been tested locally

Testing

  • go test ./internal/core/spec
  • go test ./internal/core/exec -run 'TestAbortQueuedDAGRun' -count=20
  • go test ./internal/intg -run 'Test(BaseDAGSpecialEnvVarsInHandler|SkipBaseHandlers)' -count=1
  • go test ./internal/core/...
  • go test ./internal/cmd ./internal/service/scheduler ./internal/service/frontend/api/v1
  • make lint
  • git diff --check -- internal/core/spec/dag.go internal/core/spec/loader_test.go internal/core/exec/queue_abort_test.go

Summary by CodeRabbit

  • Refactor

    • Reorganized internal build processes for DAG and step configurations into structured transformer stages.
  • Tests

    • Enhanced test coverage for base-config inheritance in child DAGs.
    • Corrected queue abort test to verify behavior for specific run attempts.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 20, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 445fc50c-6310-4172-ba65-16901c6e2c41

📥 Commits

Reviewing files that changed from the base of the PR and between e1a79bb and 46df40b.

📒 Files selected for processing (3)
  • internal/core/exec/queue_abort_test.go
  • internal/core/spec/dag.go
  • internal/core/spec/loader_test.go

📝 Walkthrough

Walkthrough

Refactors DAG and step build flows into ordered staged pipelines. Transformers, action builders, and validators are grouped into ordered stages. dag.build becomes a dagBuildState workflow with discrete state methods. Loader now applies base/history/location data directly to the built DAG.

Changes

Staged Build Pipeline Architecture

Layer / File(s) Summary
DAG Transformer Stages
internal/core/spec/dag.go
Introduces transformStage and groups metadata and full DAG transformers into ordered stages. runTransformers now dispatches metadata-only vs metadata+full stage execution via runTransformerStages.
DAG Build State Machine
internal/core/spec/dag.go
Replaces monolithic dag.build with dagBuildState and ordered state methods: retention validation, env/param eval scope setup, transformer stages execution, inherited context composition, warning collection, handler/step graph building (skipped for metadata-only), final validation, presolved env capture, and error finalization.
Composition helpers
internal/core/spec/dag.go
Adds composeSteps, composeHandlerOn, cloneHandlerOn, and cloneStepPointer to merge and clone partially-built handler/step structures during composition.
Loader: document assembly changes
internal/core/spec/loader.go
processDAGDocument no longer merges into a destination returned by prepareDocumentContext; after build it sets BaseConfigData, applies history retention overrides, and assigns Location, SourceFile, and YamlData directly on the built dag.
Step Transformer Stages
internal/core/spec/step.go
Introduces stepTransformStage and reorganizes step transformers into ordered stages (identity, script/log output, structured output, execution placement, env/preconditions). runStepTransformers iterates stage-by-stage.
Step Action and Validation Stages
internal/core/spec/step.go
Adds staged action builders (stepActionStage) for execution-target and interaction/command concerns with optional early-stop on executor-type validation; adds staged final validation (stepValidationStage) and updates (*step).build to run action stages then validation stages.
Loader tests for inheritance
internal/core/spec/loader_test.go
Adds tests validating that base-config steps are inherited when child omits steps, and that partial overrides to handler_on.failure preserve inherited fields while overriding the run command.
Queue abort test fix
internal/core/exec/queue_abort_test.go
Adjusts attempt lookup to use store.FindAttempt(ctx, runRef) to assert the specific run attempt after abort.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'refactor: stage DAG spec compiler' clearly and concisely describes the main change: refactoring the DAG spec compiler internals into explicit stages.
Description check ✅ Passed The description covers all required template sections: Summary explains the refactoring scope, Changes lists key modifications, Related Issues is marked N/A, and Checklist confirms completion. Testing section provides comprehensive verification evidence.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/spec-compiler-stages

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/core/spec/dag.go`:
- Around line 700-710: composeInheritedContext currently computes merged via
composeBuildDAGContext and stores it in s.effective but subsequent build steps
keep mutating and returning s.result, so inherited DAG fields never make it into
the final DAG; fix by applying the merged context back into the result used by
the rest of the pipeline (e.g. assign merged into s.result or merge merged
fields into s.result) so that subsequent code paths that read/modify s.result
(and functions that later return s.result) include inherited fields; update
composeInheritedContext and the analogous places noted (the other compose/merge
points) to ensure the merged context from composeBuildDAGContext is propagated
into the final s.result before further mutations and returns.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6204fa34-8b37-4853-b772-3f7180aa0580

📥 Commits

Reviewing files that changed from the base of the PR and between ab32145 and 05ca406.

📒 Files selected for processing (2)
  • internal/core/spec/dag.go
  • internal/core/spec/step.go

Comment thread internal/core/spec/dag.go Outdated

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 397a577fb2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/core/spec/dag.go Outdated
Comment thread internal/core/spec/dag.go Outdated
@yohamta0

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal/core/spec/dag.go (1)

2950-2956: ⚡ Quick win

Consider deep cloning handler steps in cloneStepPointer to avoid unpredictable mutations during merge.

cloneStepPointer creates a shallow copy (cloned := *step), which shares references to all slice and map fields (Depends, Env, Commands, Preconditions, etc.) with the original Step. When merge subsequently calls mergo.Merge, mergo appends to destination slices, and depending on slice capacity, this may modify the shared underlying arrays. While the current code works, this pattern is fragile and violates the intent of cloning—to create an independent copy before merging. A deep clone would eliminate the ambiguity and ensure handler steps can be safely composed without unexpected mutations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/core/spec/dag.go` around lines 2950 - 2956, cloneStepPointer
currently does a shallow copy which leaves slice and map fields shared and
allows mergo.Merge to mutate original data; change cloneStepPointer to perform a
deep clone by copying all slice and map fields of core.Step (e.g., Depends, Env,
Commands, Preconditions and any other [] or map fields on core.Step) into newly
allocated slices/maps and also deep-copy any nested *core.Step pointers or
handler-related structs before returning, so the returned *core.Step is
independent and safe to merge with mergo.Merge.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/core/spec/dag.go`:
- Around line 2950-2956: cloneStepPointer currently does a shallow copy which
leaves slice and map fields shared and allows mergo.Merge to mutate original
data; change cloneStepPointer to perform a deep clone by copying all slice and
map fields of core.Step (e.g., Depends, Env, Commands, Preconditions and any
other [] or map fields on core.Step) into newly allocated slices/maps and also
deep-copy any nested *core.Step pointers or handler-related structs before
returning, so the returned *core.Step is independent and safe to merge with
mergo.Merge.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0bf0c8e5-dc2a-476c-96df-c774cf88395d

📥 Commits

Reviewing files that changed from the base of the PR and between 304bb8e and e1a79bb.

📒 Files selected for processing (2)
  • internal/core/spec/dag.go
  • internal/core/spec/loader_test.go

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1a79bbf20

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/core/spec/dag.go
@yohamta0

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@yohamta0
yohamta0 merged commit a678fac into main May 21, 2026
10 checks passed
@yohamta0
yohamta0 deleted the refactor/spec-compiler-stages branch May 21, 2026 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant