Skip to content

v0 Wave A: constructs + Definition Graph - #38

Merged
ThePlenkov merged 5 commits into
mainfrom
v0-a-constructs
Aug 13, 2026
Merged

ThePlenkov merged 5 commits into
mainfrom
v0-a-constructs

Conversation

@ThePlenkov

@ThePlenkov ThePlenkov commented Aug 12, 2026 •

Copy link
Copy Markdown
Contributor

User description

Summary

  • New @sverka/constructs package wrapping constructs@10.8.1 with Sverka-specific base classes (SverkaConstruct, Project, Pipeline, Step, ShellStep)
  • Rebuilt @sverka/core around the Definition Graph: Project → Pipeline → Entry/Trigger → Step → Operation with typed References
  • Synthesis lifecycle: instantiate → collect metadata → normalize → build graph → validate
  • Specs filled: 01-constructs, 02-definition-graph, 05-synthesis
  • ADR-010: constructs/core package boundary

Tests: 48 passing (20 constructs + 28 core)
Stacks on: #37 (v0 redesign foundation)

Test plan

  • packages/constructs — 20 tests pass
  • packages/core — 28 tests pass
  • Specs filled and reviewed
  • Reviewer approved

Generated with Devin


Summary by cubic

Introduces @sverka/constructs for authoring Projects/Pipelines/Steps and rebuilds @sverka/core to synthesize a provider‑neutral Definition Graph with stricter validation and a temporary compat layer. Behavior change: empty artifact output paths now throw ConstructError(INVALID_OUTPUT) on construct creation and SynthesisError(INVALID_OUTPUT) on synthesis; duplicate construct ids throw ConstructError(DUPLICATE_ID); importArtifact.from must be fully‑qualified; unknown dependsOn targets and unexpected construct types are rejected.

  • Validates cycles, unknown producers (including dependsOn), output collisions (includes importArtifact; duplicate imports deduped), incompatible references, invalid scope, and unexpected construct types; resolves producer ids via a shared resolver.
  • Adds Definition Graph types and synthesize(project); introduces OutputDefinition/PipelineOutputDefinition (preserves output name and producer stepId) and a discriminated‐union Dependency.
  • Validates artifact outputs before construct registration and keeps a defense‑in‑depth check during synthesis; extracts step synthesis into focused helpers. Restores old core composables/types/ID functions as a compat export to unblock downstream packages.

Migration

  • Author with @sverka/constructs (Project, Pipeline, ShellStep, Entry) and call synthesize(project) from @sverka/core; the old core API remains available temporarily.
  • Set a non‑empty path for each artifact output and verify dependsOn targets exist.
  • Use fully‑qualified importArtifact.from and avoid duplicate imports; update consumers to new core types where referenced (Dependency union; OutputDefinition/PipelineOutputDefinition).

Written for commit c956507. Summary will update on new commits.

Review in cubic


CodeAnt-AI Description

Introduce construct-based pipeline authoring and Definition Graph synthesis

What Changed

  • Added @sverka/constructs with Projects, Pipelines, shell Steps, Entries, triggers, inputs, outputs, runtimes, and typed references
  • Replaced the previous operation-composition API with a construct tree that can be synthesized into a provider-neutral Definition Graph
  • Synthesis creates shell, import, and export operations and infers control, value, and artifact dependencies
  • Invalid nesting, duplicate IDs, missing artifact paths, dependency cycles, unknown producers, output collisions, and incompatible references now produce clear errors
  • Added coverage for construct authoring, graph generation, dependency inference, validation, and deterministic synthesis

Impact

✅ Typed pipeline and trigger authoring
✅ Explicit artifact and value transfer between steps
✅ Clearer invalid pipeline errors

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@codeant-ai

codeant-ai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Incremental review completed 77fbf7b Aug 13, 2026 · 08:23 08:23
✅ Reviewed your PR c93c778 Aug 12, 2026 · 23:47 23:49

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Running ultrareview automatically — This PR rebuilds core around a new Definition Graph and introduces a foundational constructs package — a cross-cutting refactor where subtle synthesis, validation, or graph-construction bugs could break every downstream pipeline.. I'll post findings when complete.

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 12, 2026

Copy link
Copy Markdown

I can't run this ultrareview because you've reached your trial's review limit. Trial plans have lower review limits than paid plans. Upgrade now to resume reviews.

To help optimise your usage, you can tune cubic to get the most out of your usage limits:

Learn more →

@coderabbitai

coderabbitai Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added workflow constructs for projects, pipelines, steps, shell commands, entries, triggers, inputs, outputs, references, and runtimes.
    • Added synthesis that converts workflows into validated, deterministic definition graphs.
    • Added clear error categories for invalid scopes, duplicate IDs, invalid outputs, cycles, unknown producers, output collisions, and incompatible references.
  • Documentation

    • Added architecture decisions, specifications, and an implementation plan for the new workflow model and definition graph.
  • Tests

    • Added coverage for construct behavior, graph generation, synthesis, validation, dependencies, and deterministic output.

Walkthrough

This change adds @sverka/constructs, rebuilds @sverka/core around Definition Graphs and synthesis, adds validation and tests, updates package configuration, and defines the architecture and specifications for Wave A.

Changes

Wave A foundation

Layer / File(s) Summary
Contracts and package boundaries
engdocs/adr/*, engdocs/architecture/*, specs/*
Defines package ownership, public contracts, synthesis rules, validation codes, dependency behavior, and implementation gates.
Construct tree and authoring models
packages/constructs/*
Adds construct classes, trigger and reference models, runtime/input/output types, construct errors, package exports, build configuration, and tests.
Definition Graph contracts and exports
packages/core/package.json, packages/core/project.json, packages/core/src/graph.ts, packages/core/src/errors.ts, packages/core/src/index.ts, packages/core/src/__tests__/graph.test.ts
Adds graph types and synthesis errors, exports the new core API, wires the constructs dependency, and tests graph variants.
Graph synthesis and validation
packages/core/src/synthesize.ts, packages/core/src/validate.ts, packages/core/src/__tests__/synthesize.test.ts, packages/core/src/__tests__/validate.test.ts
Converts construct trees into deterministic graphs, emits operations, infers and deduplicates dependencies, and validates cycles, producers, outputs, and reference types.

Estimated code review effort: 4 (Complex) | ~60 minutes

Mergeability Score: 🟠 High · up to 2ee12

This PR introduces construct-based authoring and graph synthesis, but the current head can still omit authored steps or generate dangling and invalid dependencies, and the configured quality gate is failing. Those issues can produce incomplete or invalid pipeline definitions, so the PR is not ready to merge until the correctness findings and quality-gate failures are fixed.

Sequence Diagram(s)

sequenceDiagram
  participant Project
  participant synthesize
  participant validate
  participant DefinitionGraph
  Project->>synthesize: Provide construct tree
  synthesize->>DefinitionGraph: Build operations and dependencies
  synthesize->>validate: Validate references and cycles
  validate-->>synthesize: Return validation result
  synthesize-->>Project: Return DefinitionGraph
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.00% 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
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.
Description check ✅ Passed The description clearly summarizes the constructs package, Definition Graph rebuild, synthesis behavior, validation, specifications, and tests.
Title check ✅ Passed The title concisely identifies the main changes: v0 Wave A, constructs, and the Definition Graph.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch v0-a-constructs

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

@codeant-ai codeant-ai Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files label Aug 12, 2026
@baz-reviewer

baz-reviewer Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

Merger

Needs Review

PR exceeds the merge-gate context budget (70088 tokens); escalating to a human reviewer.

Commit c956507 · Evaluated 2026-08-13 21:35 UTC

Review this PR on Baz | Customize your next review

@amazon-q-developer amazon-q-developer 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.

This PR introduces a solid foundation for the v0 Wave A constructs and definition graph implementation. The code is well-structured with comprehensive test coverage (48 tests passing). However, I've identified 2 critical issues that must be fixed before merge:

  1. Dead code in validate.ts - Lines 78-84 contain an unused loop and Set that serves no purpose
  2. Incorrect fallback logic in synthesize.ts - Using empty string as fallback for missing artifact paths will create invalid exports that bypass earlier validation

Both issues have specific fixes provided. Once these are addressed, the PR will be ready to merge.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.


⚠️ This PR contains more than 30 files. Amazon Q is better at reviewing smaller PRs, and may miss issues in larger changesets.

Comment thread packages/core/src/validate.ts Outdated
Comment thread packages/core/src/synthesize.ts Outdated
@codacy-production

codacy-production Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 107 complexity · 2 duplication

Metric Results
Complexity 107
Duplication 2

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

Comment thread packages/core/src/index.ts
Comment thread packages/core/src/validate.ts Outdated
Comment thread packages/constructs/src/constructs.ts Outdated
Comment thread packages/core/src/synthesize.ts Outdated
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Wave A: introduce @sverka/constructs and Definition Graph synthesis

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add @sverka/constructs for construct-tree authoring and shared typed model.
• Rebuild @sverka/core around Definition Graph types plus synthesize() lifecycle.
• Add validation, tests, and specs/ADR documenting boundaries and behavior.
Diagram

graph TD
  U["User code"] --> C["@sverka/constructs"] --> T["Construct tree"] --> S["@sverka/core synthesize()"] --> V["Validation"] --> G["Definition Graph"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Single package: merge constructs + core
  • ➕ Fewer packages to version/publish
  • ➕ Simpler imports for consumers
  • ➖ Weakens the construct-tree vs derived-graph boundary
  • ➖ Harder to enforce layering as future waves add IR/planning/providers
2. Three packages: extract shared types into @sverka/model
  • ➕ Very explicit layering for shared model types
  • ➕ Keeps constructs focused on tree identity/ownership
  • ➖ Adds extra package overhead for a small shared surface
  • ➖ Types are authored alongside constructs, so separation is somewhat artificial
3. Put shared model types in core (constructs depends on core)
  • ➕ One top-level place for types and synthesis
  • ➖ Inverts desired dependency direction (core should sit above constructs)
  • ➖ Higher risk of circular deps as core grows

Recommendation: The PR’s chosen split (authoring constructs + shared model in @sverka/constructs, derived Definition Graph + synthesize() in @sverka/core) best matches the v0 architecture and keeps dependency direction clean. Alternatives were considered but rejected due to boundary erosion or extra package complexity.

Files changed (27) +2336 / -87

Enhancement (8) +717 / -0
base.tsIntroduce SverkaConstruct insulation base class +6/-0

Introduce SverkaConstruct insulation base class

• Adds 'SverkaConstruct extends Construct' as an insulation layer for future Sverka-specific behavior. Used as the base for all construct classes in this package.

packages/constructs/src/base.ts

constructs.tsImplement Project/Pipeline/Step/ShellStep/Entry constructs +153/-0

Implement Project/Pipeline/Step/ShellStep/Entry constructs

• Implements the authoring construct classes with strict parent-scope validation and duplicate-id wrapping into 'ConstructError'. Adds step metadata (runtime, inputs/outputs, dependsOn, timeout) and validates artifact outputs require a path.

packages/constructs/src/constructs.ts

errors.tsAdd ConstructError with typed error codes +17/-0

Add ConstructError with typed error codes

• Defines 'ConstructError' and codes for invalid scope, duplicate id, and invalid outputs. Supports optional 'cause' for wrapping underlying constructs-library exceptions.

packages/constructs/src/errors.ts

index.tsDefine @sverka/constructs public exports +19/-0

Define @sverka/constructs public exports

• Exports construct classes, shared model types, trigger factories, and 'ConstructError'. Establishes the package as the shared authoring/type layer consumed by core.

packages/constructs/src/index.ts

model.tsAdd shared model types (Trigger/Reference/Input/Output/Runtime) +107/-0

Add shared model types (Trigger/Reference/Input/Output/Runtime)

• Defines Trigger variants and factories, typed References (step/context), and runtime/input/output type models. These types are shared between construct authoring and core’s Definition Graph.

packages/constructs/src/model.ts

graph.tsIntroduce Definition Graph types in core +67/-0

Introduce Definition Graph types in core

• Defines the provider-neutral Definition Graph (Project/Pipeline/Entry/Step) plus OperationDefinition and Dependency variants. Reuses shared model types from '@sverka/constructs'.

packages/core/src/graph.ts

synthesize.tsImplement construct-tree → Definition Graph synthesis +186/-0

Implement construct-tree → Definition Graph synthesis

• Traverses Project/Pipeline/Step/Entry constructs to build graph definitions and normalize operations (shell/export/import). Infers and deduplicates dependencies from inputs and dependsOn, then runs validation before returning the graph.

packages/core/src/synthesize.ts

validate.tsAdd validation for cycles, references, and type compatibility +162/-0

Add validation for cycles, references, and type compatibility

• Implements DFS-based cycle detection and checks for unknown producers and incompatible StepRef types/outputs. Throws 'SynthesisError' with structured codes on the first failure.

packages/core/src/validate.ts

Refactor (2) +38 / -52
errors.tsReplace legacy core errors with SynthesisError +25/-24

Replace legacy core errors with SynthesisError

• Removes the old 'CoreError' hierarchy and introduces 'SynthesisError' and typed error codes used by synthesis validation. Adds optional 'stepId' and 'cause' fields for diagnostics.

packages/core/src/errors.ts

index.tsRebuild core public API around graph + synthesis +13/-28

Rebuild core public API around graph + synthesis

• Removes previous exports (composables/runtime/operations) and replaces them with Definition Graph type exports, 'synthesize()', and 'SynthesisError'. Establishes the Wave A public API surface for core.

packages/core/src/index.ts

Tests (5) +766 / -0
constructs.test.tsAdd tests for construct tree primitives and errors +140/-0

Add tests for construct tree primitives and errors

• Tests Project/Pipeline/ShellStep/Entry creation, node paths, and construct-tree traversal. Verifies 'ConstructError' for duplicate ids, invalid scope, and invalid artifact outputs.

packages/constructs/src/tests/constructs.test.ts

model.test.tsAdd tests for Trigger/Reference/Input/Output/Runtime types +104/-0

Add tests for Trigger/Reference/Input/Output/Runtime types

• Covers trigger factories ('push', 'changeRequest', 'manual') and validates Reference shapes. Exercises Input/OutputDeclaration/Runtime typing examples.

packages/constructs/src/tests/model.test.ts

graph.test.tsAdd Definition Graph type conformance tests +154/-0

Add Definition Graph type conformance tests

• Tests the structural shape of the Definition Graph and variants for operations and dependencies. Verifies optional step fields and pipeline inputs/outputs handling.

packages/core/src/tests/graph.test.ts

synthesize.test.tsAdd synthesis tests for normalization and dependency inference +262/-0

Add synthesis tests for normalization and dependency inference

• Covers synthesis of empty and populated pipelines, operation normalization, dependency inference (value/artifact/control), and deduplication rules. Includes a determinism test to ensure stable graph output for identical trees.

packages/core/src/tests/synthesize.test.ts

validate.test.tsAdd synthesis validation tests (error codes) +106/-0

Add synthesis validation tests (error codes)

• Adds tests ensuring synthesis throws 'SynthesisError' for dependency cycles, unknown producers, and incompatible references. Confirms error codes match spec expectations.

packages/core/src/tests/validate.test.ts

Documentation (5) +714 / -34
ADR-010-construct-core-boundary.mdADR-010: define constructs/core ownership boundary +60/-0

ADR-010: define constructs/core ownership boundary

• Documents that '@sverka/constructs' owns authoring constructs and shared model types, while '@sverka/core' owns Definition Graph + synthesis/validation. Records dependency direction and rejected alternatives.

engdocs/adr/ADR-010-construct-core-boundary.md

v0-wave-A-plan.mdWave A implementation plan (TDD steps + file layout) +241/-0

Wave A implementation plan (TDD steps + file layout)

• Adds a step-by-step plan for Wave A, including package scaffolding, file layout, and verification checkpoints. Serves as the execution checklist for constructs + Definition Graph delivery.

engdocs/architecture/v0-wave-A-plan.md

spec.mdFill Spec 01: Constructs package definition +188/-11

Fill Spec 01: Constructs package definition

• Promotes the spec from stub to active and documents the constructs authoring API, shared model types, and error semantics. Clarifies separation from the Definition Graph and core layering.

specs/01-constructs/spec.md

spec.mdFill Spec 02: Definition Graph model +107/-12

Fill Spec 02: Definition Graph model

• Promotes the spec from stub to active, defining Definition Graph interfaces, operations/dependencies, and ID conventions. States that validation is handled by synthesis (spec 05).

specs/02-definition-graph/spec.md

spec.mdFill Spec 05: synthesis lifecycle and validation rules +118/-11

Fill Spec 05: synthesis lifecycle and validation rules

• Promotes the spec from stub to active, describing the Wave A synthesis lifecycle, normalization rules, dependency inference, and validation error codes. Documents determinism expectations and a test plan aligned to the new suite.

specs/05-synthesis/spec.md

Other (7) +101 / -1
bun.lockLock new constructs workspace package and constructs@10.8.1 +19/-0

Lock new constructs workspace package and constructs@10.8.1

• Adds lock entries for 'packages/constructs' and pins 'constructs@10.8.1'. Updates 'packages/core' lock metadata to depend on '@sverka/constructs'.

bun.lock

package.jsonScaffold new @sverka/constructs package +29/-0

Scaffold new @sverka/constructs package

• Introduces a new ESM package with build/test/lint/typecheck scripts and export mapping. Adds runtime dependency on 'constructs@10.8.1' plus dev tooling.

packages/constructs/package.json

project.jsonAdd NX targets for constructs package +33/-0

Add NX targets for constructs package

• Registers NX build/test/lint/typecheck targets for 'packages/constructs' using bun-run commands. Enables monorepo task execution for the new package.

packages/constructs/project.json

tsconfig.jsonAdd TS config for constructs build output +8/-0

Add TS config for constructs build output

• Configures 'rootDir'/'outDir' and includes 'src/**/*', extending the repo base config. Aligns TypeScript output with dist packaging expectations.

packages/constructs/tsconfig.json

tsdown.config.tsAdd tsdown config for ESM + DTS build +8/-0

Add tsdown config for ESM + DTS build

• Configures tsdown to build 'src/index.ts' as ESM, generate DTS, and clean dist on build. Matches monorepo build conventions.

packages/constructs/tsdown.config.ts

package.jsonAdd dependency on @sverka/constructs +3/-0

Add dependency on @sverka/constructs

• Adds '@sverka/constructs' as a workspace dependency, reflecting the new layering (core consumes constructs). Keeps existing dev tooling setup for core.

packages/core/package.json

project.jsonSimplify eslint command for core NX target +1/-1

Simplify eslint command for core NX target

• Updates core lint target from 'eslint src --ext .ts' to 'eslint src'. Keeps execution consistent with other packages.

packages/core/project.json

@codacy-production codacy-production 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.

Pull Request Overview

The PR introduces a construct-based authoring model and synthesis layer, but currently fails to meet quality standards due to high complexity in core logic and logical gaps in collision detection. Specifically, the validateOutputCollisions logic misses importArtifact operations and contains dead code.

Several acceptance criteria are met, including dependency inference and cycle detection; however, the OUTPUT_COLLISION validation is effectively unreachable or incomplete. High-risk files include packages/core/src/validate.ts and packages/core/src/synthesize.ts due to high cyclomatic complexity and long methods that combine multiple responsibilities. These should be refactored to ensure maintainability.

About this PR

  • The validation path for 'OUTPUT_COLLISION' is currently unreachable through standard Step authoring because construct IDs and Props use Map/Record structures that enforce uniqueness at the language level. Additionally, PipelineDefinition.outputs aggregates Step outputs into a flat array without associated names, which may complicate mapping for providers.

Test suggestions

  • Verify Project, Pipeline, and Step nesting constraints (INVALID_SCOPE)
  • Detect duplicate construct IDs (DUPLICATE_ID)
  • Validate artifact outputs require a 'path' (INVALID_OUTPUT)
  • Infer artifact and value dependencies from StepRefs during synthesis
  • Infer control dependencies from dependsOn
  • Ensure specific dependencies (value/artifact) override control dependencies for the same producer
  • Detect dependency cycles (CYCLE)
  • Detect references to unknown producers (UNKNOWN_PRODUCER)
  • Detect type mismatches in StepRefs vs producer output (INCOMPATIBLE_REFERENCE)
  • Detect duplicate output names in a single step (OUTPUT_COLLISION)
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Detect duplicate output names in a single step (OUTPUT_COLLISION)

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

Comment thread packages/core/src/validate.ts Outdated
Comment thread packages/core/src/validate.ts Outdated
Comment thread packages/core/src/synthesize.ts
Comment thread packages/constructs/src/constructs.ts
Comment thread packages/core/src/validate.ts Outdated
Comment thread packages/core/src/synthesize.ts Outdated

@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: 17

🤖 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 `@engdocs/adr/ADR-010-construct-core-boundary.md`:
- Line 4: Align the active-document dates with the review date: update
2026-08-13 in engdocs/adr/ADR-010-construct-core-boundary.md at line 4, and
update 2026-08-13 or mark the plan as future-dated in
engdocs/architecture/v0-wave-A-plan.md at line 5.

In `@engdocs/architecture/v0-wave-A-plan.md`:
- Around line 9-12: Add language identifiers to every listed Markdown code
fence: engdocs/architecture/v0-wave-A-plan.md lines 9-12, 20-30, and 34-45, plus
specs/05-synthesis/spec.md lines 12-14. Use an appropriate identifier for each
dependency, constructs layout, core layout, and synthesis lifecycle block while
preserving their contents.

In `@packages/constructs/src/constructs.ts`:
- Line 4: Remove the unused Construct import from constructs.ts, leaving the
remaining imports and implementation unchanged.

In `@packages/core/src/__tests__/synthesize.test.ts`:
- Around line 65-89: Add a test case alongside the existing artifact StepRef
test that supplies the input step as "ci/build" instead of "build". Synthesize
the pipeline and assert the generated artifact dependency producer is exactly
"ci/build", covering the synthesizeStep handling of already-prefixed references.

In `@packages/core/src/__tests__/validate.test.ts`:
- Around line 43-64: Replace the current collision test in the validation test
suite with a direct `validateOutputCollisions` call using a hand-built
`StepDefinition` containing two export operations with the same name, and assert
it raises `SynthesisError(OUTPUT_COLLISION)`. Rename the existing `synthesize`
case to describe the no-collision path, retaining its successful synthesis
assertion; use the package’s concrete `Runtime` value.
- Around line 17-22: Update the cycle-error test around synthesize(proj) to
assert the thrown SynthesisError once using toThrow with expect.objectContaining
matching code "CYCLE". Remove the separate try/catch and duplicate synthesize
invocation while preserving validation of the error type and code.

In `@packages/core/src/graph.ts`:
- Around line 63-67: Update the exported Dependency type in graph.ts from a
single interface to a discriminated union keyed by kind: keep output absent for
control dependencies, and require output for value and artifact dependencies.
Preserve the readonly producer field across all variants and ensure
synthesizeStep remains compatible with the stricter type.

In `@packages/core/src/synthesize.ts`:
- Around line 40-44: Update synthesize and add or use collectPipelineChildren to
recursively traverse the construct tree, handling every Step subclass, Entry,
and Pipeline while descending into grouping constructs. Replace silent omission
of unsupported nodes with SynthesisError, preserving synthesis of valid nested
pipelines and steps.
- Line 104: Export the existing resolveStepId function from validate.ts and
reuse it in synthesize.ts for producerId, dependsOn references, and entry roots.
Replace unconditional pipeline-prefix concatenation so already-qualified
references such as “ci/build” remain unchanged while local step references still
resolve within the current pipeline.
- Around line 67-68: The synthesized output declarations currently discard
output names, forcing validation to reconstruct them from export operations. In
packages/core/src/synthesize.ts lines 67-68, preserve each output’s map key in
StepDefinition.outputs and qualify pipeline-level output names with the
producing step id; in packages/core/src/validate.ts lines 77-84, validate name
collisions directly from the named step.outputs and remove the operations-based
workaround.
- Around line 14-22: Remove the unused ProjectDefinition type from the import
list in synthesize.ts, leaving the other graph.js imports unchanged.

In `@packages/core/src/validate.ts`:
- Around line 77-84: Remove the empty nested loop over step.outputs, including
the unused seen Set and its speculative comments, while preserving the
surrounding validation logic in the steps iteration.
- Around line 106-149: Reduce cognitive complexity in validateReferenceTypes by
extracting output map construction into a buildOutputTypeMap helper and the
per-reference validation into checkStepRef(step, ref, producerOutputs). Keep
validateReferenceTypes focused on iterating steps and inputs, delegating each
step reference check while preserving existing SynthesisError behavior.

In `@specs/01-constructs/spec.md`:
- Around line 63-69: Update StepProps.outputs in the authoring model so
duplicate output names remain representable for validation, preferably by using
a named declaration array instead of a Record. Then ensure synthesis validation
can detect duplicates and preserve the OUTPUT_COLLISION requirement and
corresponding test; alternatively, consistently remove or redefine that rule and
test.

In `@specs/02-definition-graph/spec.md`:
- Around line 53-59: Resolve the mismatch between PipelineDefinition.outputs and
the authoring contract: update PipelineProps to expose pipeline outputs and
define how they are normalized into PipelineDefinition.outputs, or defer the
field by removing it from the required interface and test plan. Ensure the
synthesis contract and tests consistently reflect the chosen behavior.
- Around line 80-85: Update the exportOutput variant of OperationDefinition to
accept only scalar output types, excluding "artifact" from OutputType; leave
exportArtifact as the required representation for artifact outputs and preserve
the other operation variants unchanged.

In `@specs/05-synthesis/spec.md`:
- Around line 91-99: Specify the synthesis name-resolution rule for
StepRef.step, dependsOn, and Entry.roots: resolve each pipeline-local name to
its path-qualified Definition Graph ID using the containing pipeline path, such
as build in pipeline ci becoming ci/build. Update the dependency and entry-root
requirements to use these qualified IDs, and add tests covering both dependency
references and entry roots.
🪄 Autofix

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: ASSERTIVE

Plan: Pro Plus

Run ID: d81d58e2-d81e-41bd-8f49-e7ef6d5a336c

📥 Commits

Reviewing files that changed from the base of the PR and between 4f17521 and c93c778.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (56)
  • engdocs/adr/ADR-010-construct-core-boundary.md
  • engdocs/architecture/v0-wave-A-plan.md
  • packages/constructs/package.json
  • packages/constructs/project.json
  • packages/constructs/src/__tests__/constructs.test.ts
  • packages/constructs/src/__tests__/model.test.ts
  • packages/constructs/src/base.ts
  • packages/constructs/src/constructs.ts
  • packages/constructs/src/errors.ts
  • packages/constructs/src/index.ts
  • packages/constructs/src/model.ts
  • packages/constructs/tsconfig.json
  • packages/constructs/tsdown.config.ts
  • packages/core/package.json
  • packages/core/project.json
  • packages/core/src/__tests__/canonical.test.ts
  • packages/core/src/__tests__/composables/parallel.test.ts
  • packages/core/src/__tests__/composables/pipeline.test.ts
  • packages/core/src/__tests__/composables/run.test.ts
  • packages/core/src/__tests__/composables/when.test.ts
  • packages/core/src/__tests__/composables/workflow.test.ts
  • packages/core/src/__tests__/composition.test.ts
  • packages/core/src/__tests__/conditions.test.ts
  • packages/core/src/__tests__/dag.test.ts
  • packages/core/src/__tests__/errors.test.ts
  • packages/core/src/__tests__/graph.test.ts
  • packages/core/src/__tests__/helpers/runtime.ts
  • packages/core/src/__tests__/ids.test.ts
  • packages/core/src/__tests__/laziness.test.ts
  • packages/core/src/__tests__/matrix.test.ts
  • packages/core/src/__tests__/public-api.test.ts
  • packages/core/src/__tests__/runtime-modes.test.ts
  • packages/core/src/__tests__/synthesize.test.ts
  • packages/core/src/__tests__/validate.test.ts
  • packages/core/src/composables/matrix.ts
  • packages/core/src/composables/parallel.ts
  • packages/core/src/composables/pipeline.ts
  • packages/core/src/composables/run.ts
  • packages/core/src/composables/when.ts
  • packages/core/src/composables/workflow.ts
  • packages/core/src/errors.ts
  • packages/core/src/graph.ts
  • packages/core/src/index.ts
  • packages/core/src/internal/canonical.ts
  • packages/core/src/internal/conditions.ts
  • packages/core/src/internal/ids.ts
  • packages/core/src/internal/merge.ts
  • packages/core/src/internal/node.ts
  • packages/core/src/internal/plan.ts
  • packages/core/src/operation.ts
  • packages/core/src/runtime.ts
  • packages/core/src/synthesize.ts
  • packages/core/src/validate.ts
  • specs/01-constructs/spec.md
  • specs/02-definition-graph/spec.md
  • specs/05-synthesis/spec.md
💤 Files with no reviewable changes (30)
  • packages/core/src/tests/ids.test.ts
  • packages/core/src/tests/composables/workflow.test.ts
  • packages/core/src/tests/runtime-modes.test.ts
  • packages/core/src/composables/run.ts
  • packages/core/src/internal/canonical.ts
  • packages/core/src/tests/composables/when.test.ts
  • packages/core/src/internal/plan.ts
  • packages/core/src/tests/helpers/runtime.ts
  • packages/core/src/tests/composables/pipeline.test.ts
  • packages/core/src/tests/matrix.test.ts
  • packages/core/src/runtime.ts
  • packages/core/src/composables/matrix.ts
  • packages/core/src/tests/composition.test.ts
  • packages/core/src/tests/laziness.test.ts
  • packages/core/src/tests/composables/parallel.test.ts
  • packages/core/src/internal/ids.ts
  • packages/core/src/composables/pipeline.ts
  • packages/core/src/tests/canonical.test.ts
  • packages/core/src/composables/workflow.ts
  • packages/core/src/tests/conditions.test.ts
  • packages/core/src/tests/composables/run.test.ts
  • packages/core/src/internal/conditions.ts
  • packages/core/src/tests/dag.test.ts
  • packages/core/src/composables/when.ts
  • packages/core/src/composables/parallel.ts
  • packages/core/src/operation.ts
  • packages/core/src/tests/public-api.test.ts
  • packages/core/src/internal/merge.ts
  • packages/core/src/internal/node.ts
  • packages/core/src/tests/errors.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: main
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Amazon Q Developer
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: - No any: Use unknown and narrow. Strict TypeScript.

  • Error handling: Custom error classes per package.

Files:

  • packages/constructs/src/index.ts
  • packages/core/src/index.ts
  • packages/constructs/src/__tests__/model.test.ts
  • packages/constructs/src/errors.ts
  • packages/constructs/src/base.ts
  • packages/core/src/__tests__/graph.test.ts
  • packages/constructs/src/model.ts
  • packages/core/src/__tests__/synthesize.test.ts
  • packages/core/src/synthesize.ts
  • packages/constructs/tsdown.config.ts
  • packages/core/src/__tests__/validate.test.ts
  • packages/constructs/src/__tests__/constructs.test.ts
  • packages/core/src/errors.ts
  • packages/core/src/validate.ts
  • packages/constructs/src/constructs.ts
  • packages/core/src/graph.ts
**/src/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

  • Public API: Everything public is exported from src/index.ts.

Files:

  • packages/constructs/src/index.ts
  • packages/core/src/index.ts
🧠 Learnings (4)
📚 Learning: 2026-08-12T07:24:02.495Z
Learnt from: CR
Repo: sverka-dev/sverka PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-12T07:24:02.495Z
Learning: Applies to **/src/index.ts : - **Public API:** Everything public is exported from `src/index.ts`.

Applied to files:

  • packages/constructs/package.json
  • packages/constructs/tsconfig.json
  • packages/constructs/src/index.ts
  • packages/core/src/index.ts
  • packages/constructs/tsdown.config.ts
📚 Learning: 2026-08-12T07:24:02.495Z
Learnt from: CR
Repo: sverka-dev/sverka PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-12T07:24:02.495Z
Learning: Applies to **/*.{ts,tsx} : - **Error handling:** Custom error classes per package.

Applied to files:

  • packages/constructs/tsconfig.json
  • packages/constructs/src/errors.ts
  • packages/core/src/errors.ts
📚 Learning: 2026-08-12T07:24:02.495Z
Learnt from: CR
Repo: sverka-dev/sverka PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-12T07:24:02.495Z
Learning: Applies to **/*.{ts,tsx} : - **No `any`:** Use `unknown` and narrow. Strict TypeScript.

Applied to files:

  • packages/constructs/tsconfig.json
  • packages/constructs/tsdown.config.ts
📚 Learning: 2026-08-11T20:47:11.392Z
Learnt from: ThePlenkov
Repo: sverka-dev/sverka PR: 28
File: pack/formulas/wave.toml:27-43
Timestamp: 2026-08-11T20:47:11.392Z
Learning: In `pack/formulas/wave.toml`, the `wave` formula is a process description for the Gas City harness. It documents the architect, builder, reviewer, and mayor workflow steps. It is not executable runtime control flow, so reviewer rejection does not require a machine-readable formula gate in this file.

Applied to files:

  • engdocs/architecture/v0-wave-A-plan.md
🪛 GitHub Check: SonarCloud Code Analysis
packages/core/src/__tests__/graph.test.ts

[warning] 152-152: Prefer "expect(pipeline.outputs).toHaveLength(1)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCBy-A7VkHH8NoJV&open=AZ_4YCBy-A7VkHH8NoJV&pullRequest=38


[warning] 49-49: Prefer "expect(step.dependencies).toHaveLength(0)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCBy-A7VkHH8NoJT&open=AZ_4YCBy-A7VkHH8NoJT&pullRequest=38


[warning] 151-151: Prefer "expect(pipeline.inputs).toHaveLength(1)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCBy-A7VkHH8NoJU&open=AZ_4YCBy-A7VkHH8NoJU&pullRequest=38


[warning] 30-30: Prefer "expect(graph.project.pipelines).toHaveLength(1)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCBx-A7VkHH8NoJS&open=AZ_4YCBx-A7VkHH8NoJS&pullRequest=38

packages/core/src/__tests__/synthesize.test.ts

[warning] 17-17: Prefer "expect(graph.project.pipelines).toHaveLength(1)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCGU-A7VkHH8NoJW&open=AZ_4YCGU-A7VkHH8NoJW&pullRequest=38

packages/core/src/synthesize.ts

[warning] 16-16: Remove this unused import of 'ProjectDefinition'.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCGg-A7VkHH8NoJX&open=AZ_4YCGg-A7VkHH8NoJX&pullRequest=38

packages/constructs/src/__tests__/constructs.test.ts

[warning] 80-80: Prefer "expect(proj.node.children).toHaveLength(1)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCG2-A7VkHH8NoJd&open=AZ_4YCG2-A7VkHH8NoJd&pullRequest=38


[warning] 83-83: Prefer "expect(pipeline.node.children).toHaveLength(3)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCG2-A7VkHH8NoJe&open=AZ_4YCG2-A7VkHH8NoJe&pullRequest=38


[warning] 84-84: Prefer "expect(pipeline.node.children.filter((c) => c instanceof ShellStep)).toHaveLength(2)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCG2-A7VkHH8NoJf&open=AZ_4YCG2-A7VkHH8NoJf&pullRequest=38


[warning] 85-85: Prefer "expect(pipeline.node.children.filter((c) => c instanceof Entry)).toHaveLength(1)" over this generic assertion for better reporting; it works on any object with a numeric length property.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCG2-A7VkHH8NoJg&open=AZ_4YCG2-A7VkHH8NoJg&pullRequest=38

packages/core/src/validate.ts

[warning] 79-79: Remove this useless assignment to variable "out".

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCGp-A7VkHH8NoJb&open=AZ_4YCGp-A7VkHH8NoJb&pullRequest=38


[warning] 78-78: Remove this useless assignment to variable "seen".

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCGp-A7VkHH8NoJa&open=AZ_4YCGp-A7VkHH8NoJa&pullRequest=38


[warning] 4-4: Remove this unused import of 'Dependency'.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCGp-A7VkHH8NoJY&open=AZ_4YCGp-A7VkHH8NoJY&pullRequest=38


[warning] 6-6: Remove this unused import of 'OutputDeclaration'.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCGp-A7VkHH8NoJZ&open=AZ_4YCGp-A7VkHH8NoJZ&pullRequest=38


[failure] 106-106: Refactor this function to reduce its Cognitive Complexity from 25 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCGp-A7VkHH8NoJc&open=AZ_4YCGp-A7VkHH8NoJc&pullRequest=38

packages/constructs/src/constructs.ts

[warning] 4-4: Remove this unused import of 'Construct'.

See more on https://sonarcloud.io/project/issues?id=sverka-dev_sverka&issues=AZ_4YCG_-A7VkHH8NoJh&open=AZ_4YCG_-A7VkHH8NoJh&pullRequest=38

🪛 LanguageTool
specs/01-constructs/spec.md

[grammar] ~202-~202: Ensure spelling is correct
Context: ...olds command, runtime, outputs, inputs, dependsOn. 4. Entry under Pipeline; holds trigger...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

specs/05-synthesis/spec.md

[style] ~38-~38: The double modal “needs Run” is nonstandard (only accepted in certain dialects). Consider “to be Run”.
Context: ... Trigger reachability validation (needs Run Plan — wave G) - Context reference avai...

(NEEDS_FIXED)


[style] ~123-~123: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...n with shell operation. 3. synthesize with scalar output → exportOutput operation....

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~124-~124: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...exportOutput operation. 4. synthesize with artifact output → exportArtifact operat...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~125-~125: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...portArtifact operation. 5. synthesize with artifact StepRef in inputs → importArti...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~128-~128: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...uts → value dependency. 7. synthesize with dependsOn → control dependency. 8. `s...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~132-~132: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...or(UNKNOWN_PRODUCER). 11. synthesizedetects output collision →SynthesisError(OUTP...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~133-~133: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...or(OUTPUT_COLLISION). 12. synthesizedetects incompatible reference type → Synt...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🪛 markdownlint-cli2 (0.23.2)
engdocs/architecture/v0-wave-A-plan.md

[warning] 9-9: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 20-20: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 34-34: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

specs/05-synthesis/spec.md

[warning] 12-12: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (24)
packages/constructs/src/base.ts (1)

1-6: LGTM!

packages/constructs/src/errors.ts (1)

1-17: LGTM!

packages/constructs/src/constructs.ts (1)

5-153: LGTM!

packages/constructs/tsconfig.json (1)

1-8: LGTM!

packages/constructs/tsdown.config.ts (1)

1-8: LGTM!

packages/constructs/package.json (1)

1-29: LGTM!

packages/constructs/project.json (1)

1-33: LGTM!

packages/core/src/errors.ts (1)

1-31: LGTM!

packages/core/src/index.ts (1)

1-14: LGTM!

packages/constructs/src/model.ts (1)

8-71: LGTM!

Also applies to: 77-107

packages/constructs/src/index.ts (1)

3-19: LGTM!

packages/constructs/src/__tests__/constructs.test.ts (1)

12-140: LGTM!

packages/constructs/src/__tests__/model.test.ts (1)

16-104: LGTM!

packages/core/package.json (1)

21-23: LGTM!

packages/core/project.json (1)

18-23: LGTM!

packages/core/src/graph.ts (1)

4-61: LGTM!

packages/core/src/__tests__/graph.test.ts (1)

13-155: LGTM!

packages/core/src/validate.ts (1)

12-43: LGTM!

packages/core/src/__tests__/synthesize.test.ts (1)

11-63: LGTM!

Also applies to: 91-125, 168-262

engdocs/adr/ADR-010-construct-core-boundary.md (1)

1-3: LGTM!

Also applies to: 6-60

engdocs/architecture/v0-wave-A-plan.md (1)

1-4: LGTM!

Also applies to: 7-8, 14-19, 47-128, 129-130, 146-161, 164-242

specs/01-constructs/spec.md (1)

3-62: LGTM!

Also applies to: 70-197

specs/02-definition-graph/spec.md (1)

1-52: LGTM!

Also applies to: 60-79, 86-118

specs/05-synthesis/spec.md (1)

1-11: LGTM!

Also applies to: 15-37, 39-42, 43-90, 100-102, 110-116, 135-141

Comment thread engdocs/adr/ADR-010-construct-core-boundary.md
Comment thread engdocs/architecture/v0-wave-A-plan.md Outdated
Comment thread packages/constructs/src/constructs.ts Outdated
Comment thread packages/core/src/__tests__/synthesize.test.ts
Comment thread packages/core/src/__tests__/validate.test.ts
Comment thread packages/core/src/validate.ts Outdated
Comment thread specs/01-constructs/spec.md
Comment thread specs/02-definition-graph/spec.md
Comment thread specs/02-definition-graph/spec.md
Comment thread specs/05-synthesis/spec.md
@qodo-code-review

qodo-code-review Bot commented Aug 12, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Pipeline input names discarded 🐞 Bug ≡ Correctness
Description
Synthesis converts the name-keyed input map into an array of bare values, permanently discarding
every symbolic input name. The resulting canonical graph cannot identify which declaration
corresponds to a context reference such as inputs.version, and identical declarations become
indistinguishable.
Code

packages/core/src/synthesize.ts[69]

+  const inputs: Input[] = [...pipeline.inputs.values()];
Relevance

●●● Strong

Discarding input names breaks identity/addressing; likely treated as spec/core correctness issue.

PR-#1

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Pipeline authoring stores inputs under string keys and ContextRef addresses the inputs namespace
by a field name, but synthesis returns only map values. The architecture requires symbolic pipeline
input references, so stripping keys removes required identity from the canonical graph.

packages/constructs/src/constructs.ts[30-51]
packages/constructs/src/model.ts[63-69]
packages/core/src/synthesize.ts[67-77]
specs/architecture-spec.md[461-475]
specs/architecture-spec.md[521-539]
specs/architecture-spec.md[573-578]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Pipeline input names are lost while converting the construct tree into the Definition Graph.

## Issue Context
Represent graph inputs as named entries or a record/map, and add synthesis tests asserting names survive normalization.

## Fix Focus Areas
- packages/core/src/synthesize.ts[67-77]
- packages/core/src/graph.ts[22-27]
- packages/constructs/src/model.ts[65-69]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Unknown control producers pass ✓ Resolved 🐞 Bug ≡ Correctness
Description
validateReferences checks only StepRef inputs, so dependsOn: ["missing"] returns a graph
containing a control edge to a nonexistent producer. Cycle detection silently processes absent
producer IDs, allowing a malformed graph that cannot enforce the requested ordering.
Code

packages/core/src/synthesize.ts[R128-131]

+  for (const depName of step.dependsOn) {
+    addDependency(dependencies, seenDeps, {
+      kind: "control",
+      producer: `${pipelineId}/${depName}`,
Relevance

●●● Strong

Unknown dependsOn should fail; aligns with repo emphasis on validating unknown dependencies.

PR-#1

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Synthesis creates control producer IDs from every dependsOn value, but reference validation
iterates only step.inputs. When cycle detection visits an unknown producer, stepMap.get(id) is
undefined and the function returns without an error, so the dangling edge survives.

packages/core/src/synthesize.ts[127-133]
packages/core/src/validate.ts[22-35]
packages/core/src/validate.ts[49-70]
packages/core/src/graph.ts[63-67]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Control dependencies created from `dependsOn` are not checked for unknown producer IDs.

## Issue Context
Validate all generated dependency producers against pipeline step IDs before cycle detection and throw `UNKNOWN_PRODUCER` for missing control dependencies.

## Fix Focus Areas
- packages/core/src/synthesize.ts[127-133]
- packages/core/src/validate.ts[49-70]
- packages/core/src/validate.ts[22-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Core exports break dependents ✓ Resolved 🐞 Bug ≡ Correctness
Description
The rebuilt public index removes APIs that unchanged workspace packages still import, so affected
builds fail with missing exports. The Wave A plan acknowledges the breakage, but CI runs affected
builds and these packages are dependency-linked to @sverka/core.
Code

packages/core/src/index.ts[L21-24]

-export { pipeline } from "./composables/pipeline.js";
-export { run } from "./composables/run.js";
-export { parallel } from "./composables/parallel.js";
-export { when } from "./composables/when.js";
Relevance

●● Moderate

Potential intentional Wave-A breaking change; but repo values stable public API in core.

PR-#1

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The SDK directly imports the removed composables, types, and errors, while IR imports the removed
canonicalization and ID helpers. Workspace scripts and CI build affected projects, and the PR plan
itself states that the monorepo will fail after this change.

packages/sdk/src/index.ts[3-24]
packages/ir/src/ids.ts[1-30]
package.json[8-11]
.github/workflows/ci.yml[32-33]
engdocs/architecture/v0-wave-A-plan.md[191-204]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The core rebuild removes public exports still consumed by workspace packages, causing dependent builds and affected CI to fail.

## Issue Context
Retain a compatibility surface or migrate all current consumers in the same merge so the repository remains buildable.

## Fix Focus Areas
- packages/core/src/index.ts[3-29]
- packages/sdk/src/index.ts[3-24]
- packages/ir/src/ids.ts[1-30]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Duplicate-ID error masks unrelated construct errors ✓ Resolved 🐞 Bug ≡ Correctness
Description
Pipeline, Step, and Entry constructors in packages/constructs/src/constructs.ts wrap `super(scope,
id) in try/catch and unconditionally rethrow any caught error as ConstructError('DUPLICATE_ID',
...), even when the underlying constructs` library throws for a different reason (e.g. an empty id
under a non-root scope, or other internal Node construction failures). Callers that branch on
err.code will misdiagnose the actual failure as a duplicate id.
Code

packages/constructs/src/constructs.ts[R44-48]

+    try {
+      super(scope, id);
+    } catch (err) {
+      throw new ConstructError("DUPLICATE_ID", `Duplicate id '${id}' in Project`, err);
+    }
Relevance

●● Moderate

Correctness fix but alters error-code contract; no matching repo precedent for constructs wrappers.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The same try/catch-and-relabel pattern appears identically for Pipeline (lines ~44-48), Step
(~81-85), and Entry (~145-149) in packages/constructs/src/constructs.ts. All exceptions thrown by
the wrapped constructs.Construct/Node constructor -- not only duplicate-child-id collisions --
are converted to ConstructError('DUPLICATE_ID', ...). The upstream constructs library's Node
constructor throws distinct errors for other invalid states (e.g. 'Only root constructs may have an
empty ID'), which this code cannot distinguish, so those failures are misreported with the wrong
error code.

packages/constructs/src/constructs.ts[44-48]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Pipeline, Step, and Entry constructors catch any error thrown by `super(scope, id)` and always rethrow it as `ConstructError('DUPLICATE_ID', ...)`, even if the underlying `constructs` library threw for an unrelated reason (e.g. invalid/empty id).

## Issue Context
The wrapped `constructs.Construct`/`Node` constructor from the `constructs` npm package can throw different errors depending on the failure mode (duplicate child name vs. invalid id vs. other invariant violations). The current code has no way to distinguish these and always reports `DUPLICATE_ID`, which is misleading for diagnostics and any caller branching on `ConstructError.code`.

## Fix Focus Areas
- packages/constructs/src/constructs.ts[44-48]
- packages/constructs/src/constructs.ts[81-85]
- packages/constructs/src/constructs.ts[145-149]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Invalid output poisons tree ✓ Resolved 🐞 Bug ☼ Reliability
Description
Artifact validation runs after super(scope, id) registers the construct, so catching
INVALID_OUTPUT leaves a failed child in the pipeline and retrying that ID then fails as a
duplicate. The leaked object is also only partially initialized because ShellStep.command is
assigned after the throwing base constructor returns.
Code

packages/constructs/src/constructs.ts[R96-99]

+    // Validate artifact outputs have a path.
+    for (const [name, decl] of this.outputs) {
+      if (decl.type === "artifact" && !decl.path) {
+        throw new ConstructError(
Relevance

●● Moderate

Lifecycle/rollback issue after base registration; likely invasive; no close historical precedent
found.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The Step constructor calls super before checking artifact paths, and the ShellStep command
assignment occurs only after that constructor returns. Constructs' Node constructor invokes
scope.node.addChild(host, this.id) during construction, proving registration precedes the new
validation.

packages/constructs/src/constructs.ts[74-104]
packages/constructs/src/constructs.ts[119-121]
🌐 The Node constructor registers a scoped construct by calling scope.node.addChild(host, this.id) during base construction.

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Invalid artifact output props are rejected only after the construct has been registered with its parent, leaving the tree corrupted after a caught error.

## Issue Context
Validation that does not require `this` can run before `super`; otherwise explicitly roll back registration on failure.

## Fix Focus Areas
- packages/constructs/src/constructs.ts[74-104]
- packages/constructs/src/constructs.ts[119-121]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

6. Inconsistent step-id resolution between synthesize and validate ✓ Resolved 🐞 Bug ≡ Correctness
Description
synthesizeStep in packages/core/src/synthesize.ts always constructs dependency producer ids as
${pipelineId}/${ref.step} for StepRef inputs and dependsOn entries, but resolveStepId in
packages/core/src/validate.ts treats ref.step as already qualified when it already starts with
${pipelineId}/. As a result, an already-prefixed reference like ci/build can validate as
ci/build yet be recorded in the synthesized graph as ci/ci/build, causing the two paths to
disagree about whether a producer exists and leading to dangling edges or incorrect “unknown”
dependency reporting.
Code

packages/core/src/validate.ts[R156-162]

+function resolveStepId(pipelineId: string, stepName: string): string {
+  // If the reference already includes the pipeline prefix, use as-is.
+  if (stepName.startsWith(`${pipelineId}/`)) {
+    return stepName;
+  }
+  return `${pipelineId}/${stepName}`;
+}
Relevance

●●● Strong

Deterministic double-prefix ID mismatch between validate/synthesize; likely accepted as clear bug
fix.

PR-#1

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
In packages/core/src/synthesize.ts, synthesizeStep unconditionally interpolates ref.step (and
dependsOn names) into a producer id using ${pipelineId}/${ref.step}, so an input already
containing the pipeline prefix will be double-prefixed in the dependency graph. In contrast,
packages/core/src/validate.ts’s resolveStepId explicitly returns ref.step unchanged when it
already begins with ${pipelineId}/, and validation then checks that resolved value against the
generated step IDs/output types; since both pieces of code operate on the same raw StepRef.step
string from the same StepDefinition inputs, this creates a provable divergence between the id
accepted by validation and the producer id emitted during synthesis.

packages/core/src/synthesize.ts[100-105]
packages/core/src/validate.ts[156-162]
packages/core/src/validate.ts[49-69]
packages/core/src/validate.ts[151-161]
packages/core/src/synthesize.ts[100-123]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`synthesizeStep` always prefixes `ref.step` and `dependsOn` names with `${pipelineId}/` when building dependency producer ids, while `validate.ts`'s `resolveStepId` conditionally skips the prefix if the name already starts with `${pipelineId}/`. This mismatch means the id recorded in a StepDefinition's `dependencies` can differ from the id validation checks (e.g., `ci/build` validating as `ci/build` but synthesizing a dependency on `ci/ci/build`), which can create dangling graph edges or incorrect unknown-producer errors.

## Issue Context
`StepRef.step` is documented (specs/01-constructs/spec.md) as a local step name relative to the same Pipeline, so already-prefixed values are an edge case, but synthesis and validation should not disagree on how ids are derived from the same raw string. Consider either using a single shared resolver for validation, dependency construction, and import operations, or rejecting prefixed references consistently so the behavior is uniform.

## Fix Focus Areas
- packages/core/src/synthesize.ts[100-105]
- packages/core/src/synthesize.ts[126-133]
- packages/core/src/synthesize.ts[100-123]
- packages/core/src/validate.ts[156-162]
- packages/core/src/validate.ts[49-69]
- packages/core/src/validate.ts[151-161]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Dead loop in validateOutputCollisions ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
In packages/core/src/validate.ts, validateOutputCollisions contains a `for (const out of
step.outputs) loop with an empty body (only comments) and a seen` Set that is declared but never
used; the actual duplicate-name check happens only in the following loop over step.operations.
This leftover dead code from an abandoned implementation approach adds confusion about which logic
performs the real validation.
Code

packages/core/src/validate.ts[R77-84]

+  for (const step of steps) {
+    const seen = new Set<string>();
+    for (const out of step.outputs) {
+      // outputs is an array of OutputDeclaration with names from the map keys.
+      // Actually outputs is readonly OutputDeclaration[] — but we need names.
+      // The StepDefinition.outputs is OutputDeclaration[] without names baked in.
+      // We need to check via the operations (exportOutput/exportArtifact names).
+    }
Relevance

●●● Strong

Dead loop/unused Set cleanup; team commonly accepts removing redundant/unused code.

PR-#29

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
packages/core/src/validate.ts new function validateOutputCollisions defines `const seen = new
Set<string>(); and iterates for (const out of step.outputs)` with no executable statements inside
(only comments explaining that this approach doesn't work), then performs the real check via
exportNames and step.operations in a second loop. The first loop and seen variable have zero
effect on behavior and should be removed.

packages/core/src/validate.ts[77-98]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`validateOutputCollisions` contains a no-op loop over `step.outputs` with an unused `seen` Set, left over from an earlier implementation attempt that was replaced by the operations-based check below it.

## Issue Context
The real duplicate output-name detection is performed correctly via `step.operations` and `exportNames` in the same function. The dead loop adds no value and can confuse future maintainers into thinking it participates in validation.

## Fix Focus Areas
- packages/core/src/validate.ts[77-84]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context
✅ Compliance rules (platform): 8 rules
✅ Web pages:
  +10 more
Review mode: 🧠 Deep: This is a dense redesign spanning new constructs and core packages, graph construction, synthesis, validation, APIs, and broad test replacement, creating many independent logic paths where redundant review is materially valuable.

Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread packages/core/src/index.ts
Comment thread packages/constructs/src/constructs.ts Outdated
Comment thread packages/core/src/synthesize.ts
Comment thread packages/core/src/synthesize.ts Outdated
Comment thread packages/constructs/src/constructs.ts
Comment thread packages/core/src/validate.ts Outdated
Comment thread packages/core/src/validate.ts Outdated
ThePlenkov added a commit that referenced this pull request Aug 13, 2026
…sing artifact path

- validate.ts: remove unused 'seen' Set and empty loop (dead code from Wave A)
- synthesize.ts: throw SynthesisError(INVALID_OUTPUT) when artifact output
  has no path, instead of silently using empty string (defense-in-depth)
- errors.ts: add INVALID_OUTPUT to SynthesisErrorCode union

Addresses PR #38 review findings.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@codeant-ai codeant-ai Bot added size:XXL This PR changes 1000+ lines, ignoring generated files and removed size:XXL This PR changes 1000+ lines, ignoring generated files labels Aug 13, 2026
ThePlenkov added a commit that referenced this pull request Aug 13, 2026
- Move artifact output validation before construct registration.
- Distinguish duplicate-id errors from other construct errors.
- Validate unknown producers for dependsOn control dependencies.
- Include importArtifact in output collision checks and dedupe duplicate imports.
- Use shared resolveStepId for producer ids and fully-qualified importArtifact.from.
- Add OutputDefinition/PipelineOutputDefinition to preserve output names and producer stepId.
- Make Dependency a discriminated union.
- Refactor validateReferenceTypes to reduce cyclomatic complexity.
- Add INVALID_SCOPE/INVALID_OUTPUT SynthesisError codes and reject unexpected construct types.
- Update specs and tests.
@coderabbitai coderabbitai Bot mentioned this pull request Aug 13, 2026
6 tasks
ThePlenkov added a commit that referenced this pull request Aug 13, 2026
…sing artifact path

- validate.ts: remove unused 'seen' Set and empty loop (dead code from Wave A)
- synthesize.ts: throw SynthesisError(INVALID_OUTPUT) when artifact output
  has no path, instead of silently using empty string (defense-in-depth)
- errors.ts: add INVALID_OUTPUT to SynthesisErrorCode union

Addresses PR #38 review findings.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ThePlenkov added a commit that referenced this pull request Aug 13, 2026
- Move artifact output validation before construct registration.
- Distinguish duplicate-id errors from other construct errors.
- Validate unknown producers for dependsOn control dependencies.
- Include importArtifact in output collision checks and dedupe duplicate imports.
- Use shared resolveStepId for producer ids and fully-qualified importArtifact.from.
- Add OutputDefinition/PipelineOutputDefinition to preserve output names and producer stepId.
- Make Dependency a discriminated union.
- Refactor validateReferenceTypes to reduce cyclomatic complexity.
- Add INVALID_SCOPE/INVALID_OUTPUT SynthesisError codes and reject unexpected construct types.
- Update specs and tests.
ThePlenkov added a commit that referenced this pull request Aug 13, 2026
…sing artifact path

- validate.ts: remove unused 'seen' Set and empty loop (dead code from Wave A)
- synthesize.ts: throw SynthesisError(INVALID_OUTPUT) when artifact output
  has no path, instead of silently using empty string (defense-in-depth)
- errors.ts: add INVALID_OUTPUT to SynthesisErrorCode union

Addresses PR #38 review findings.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ThePlenkov added a commit that referenced this pull request Aug 13, 2026
- Move artifact output validation before construct registration.
- Distinguish duplicate-id errors from other construct errors.
- Validate unknown producers for dependsOn control dependencies.
- Include importArtifact in output collision checks and dedupe duplicate imports.
- Use shared resolveStepId for producer ids and fully-qualified importArtifact.from.
- Add OutputDefinition/PipelineOutputDefinition to preserve output names and producer stepId.
- Make Dependency a discriminated union.
- Refactor validateReferenceTypes to reduce cyclomatic complexity.
- Add INVALID_SCOPE/INVALID_OUTPUT SynthesisError codes and reject unexpected construct types.
- Update specs and tests.
@nx-cloud

nx-cloud Bot commented Aug 13, 2026 •

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit c956507

Command Status Duration Result
nx affected -t lint test ✅ Succeeded 3s View ↗
nx affected -t build ✅ Succeeded 13s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-08-13 21:36:30 UTC

ThePlenkov added a commit that referenced this pull request Aug 13, 2026
…sing artifact path

- validate.ts: remove unused 'seen' Set and empty loop (dead code from Wave A)
- synthesize.ts: throw SynthesisError(INVALID_OUTPUT) when artifact output
  has no path, instead of silently using empty string (defense-in-depth)
- errors.ts: add INVALID_OUTPUT to SynthesisErrorCode union

Addresses PR #38 review findings.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ThePlenkov added a commit that referenced this pull request Aug 13, 2026
- Move artifact output validation before construct registration.
- Distinguish duplicate-id errors from other construct errors.
- Validate unknown producers for dependsOn control dependencies.
- Include importArtifact in output collision checks and dedupe duplicate imports.
- Use shared resolveStepId for producer ids and fully-qualified importArtifact.from.
- Add OutputDefinition/PipelineOutputDefinition to preserve output names and producer stepId.
- Make Dependency a discriminated union.
- Refactor validateReferenceTypes to reduce cyclomatic complexity.
- Add INVALID_SCOPE/INVALID_OUTPUT SynthesisError codes and reject unexpected construct types.
- Update specs and tests.
@sonarqubecloud

Copy link
Copy Markdown

Base automatically changed from v0-redesign-foundation to main August 13, 2026 21:34
ThePlenkov and others added 5 commits August 13, 2026 23:34
New @sverka/constructs package wrapping constructs@10.8.1 with Sverka-specific
base classes (SverkaConstruct, Project, Pipeline, Step, ShellStep). Rebuilt
@sverka/core around the Definition Graph: Project → Pipeline → Entry/Trigger →
Step → Operation with typed References and synthesis lifecycle.

- packages/constructs: 5 source files, 2 test files, 20 tests passing
- packages/core: 5 source files, 3 test files, 28 tests passing
- Specs filled: 01-constructs (211 lines), 02-definition-graph (129), 05-synthesis (141)
- Implementation plan: engdocs/architecture/v0-wave-A-plan.md (241 lines, 10-step TDD)
- ADR-010: constructs/core package boundary

Specs: specs/architecture-spec.md §8, §10, §11, §16
Reviewed and approved by reviewer session.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…sing artifact path

- validate.ts: remove unused 'seen' Set and empty loop (dead code from Wave A)
- synthesize.ts: throw SynthesisError(INVALID_OUTPUT) when artifact output
  has no path, instead of silently using empty string (defense-in-depth)
- errors.ts: add INVALID_OUTPUT to SynthesisErrorCode union

Addresses PR #38 review findings.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Move artifact output validation before construct registration.
- Distinguish duplicate-id errors from other construct errors.
- Validate unknown producers for dependsOn control dependencies.
- Include importArtifact in output collision checks and dedupe duplicate imports.
- Use shared resolveStepId for producer ids and fully-qualified importArtifact.from.
- Add OutputDefinition/PipelineOutputDefinition to preserve output names and producer stepId.
- Make Dependency a discriminated union.
- Refactor validateReferenceTypes to reduce cyclomatic complexity.
- Add INVALID_SCOPE/INVALID_OUTPUT SynthesisError codes and reject unexpected construct types.
- Update specs and tests.
Wave A rebuilt core with the new Definition Graph model but removed the
old composables, types, and ID functions that downstream packages (sdk,
ir, checks) still depend on. This broke their tests on v0-a-constructs.

Restore the old source files and re-export them from index.ts alongside
the new API. Each wave that rebuilds a downstream package (B: ir, C: sdk,
J: checks) removes its dependency on these compat exports. The compat
layer is removed when no longer needed.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Reduce cyclomatic complexity (12→6) and LOC (82→28) by extracting
export, import, and control-dependency logic into dedicated functions.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@sonarqubecloud

Copy link
Copy Markdown

@ThePlenkov
ThePlenkov merged commit 505c37a into main Aug 13, 2026
9 checks passed
ThePlenkov added a commit that referenced this pull request Aug 13, 2026
…sing artifact path

- validate.ts: remove unused 'seen' Set and empty loop (dead code from Wave A)
- synthesize.ts: throw SynthesisError(INVALID_OUTPUT) when artifact output
  has no path, instead of silently using empty string (defense-in-depth)
- errors.ts: add INVALID_OUTPUT to SynthesisErrorCode union

Addresses PR #38 review findings.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ThePlenkov added a commit that referenced this pull request Aug 13, 2026
- Move artifact output validation before construct registration.
- Distinguish duplicate-id errors from other construct errors.
- Validate unknown producers for dependsOn control dependencies.
- Include importArtifact in output collision checks and dedupe duplicate imports.
- Use shared resolveStepId for producer ids and fully-qualified importArtifact.from.
- Add OutputDefinition/PipelineOutputDefinition to preserve output names and producer stepId.
- Make Dependency a discriminated union.
- Refactor validateReferenceTypes to reduce cyclomatic complexity.
- Add INVALID_SCOPE/INVALID_OUTPUT SynthesisError codes and reject unexpected construct types.
- Update specs and tests.
@ThePlenkov
ThePlenkov deleted the v0-a-constructs branch August 13, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

baz: needs review size:XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant