Skip to content

Conversation

@osterman
Copy link
Member

@osterman osterman commented Oct 3, 2025

what

  • Add --provenance flag to atmos describe component command
  • Create new pkg/ui/provenance package for rendering configuration provenance
  • Implement two-column TTY display showing configuration values alongside their source files
  • Support both YAML and JSON output formats with embedded provenance metadata
  • Achieve 90.9% test coverage with comprehensive test suite (18 tests)
image

why

  • Users need to understand where configuration values come from in complex inheritance chains
  • Debugging configuration issues requires knowing which file set each value
  • The existing sources data structure was already tracked but not displayed in a user-friendly way
  • Provenance tracking improves auditability and troubleshooting of stack configurations

references

  • Implements the feature request discussed in-session
  • Leverages existing ConfigSources infrastructure from Atmos
  • Uses Charm Bracelet lipgloss for consistent terminal UI styling
  • Gracefully degrades for non-TTY environments (pipes/redirects)

Summary by CodeRabbit

  • New Features

    • Added --provenance to describe component: inline file/line/column annotations, optional file output, stack-aware inline/tree/side‑by‑side rendering, and pruning of generated computed fields when provenance is active.
  • Documentation

    • CLI docs updated for --provenance; added comprehensive Import Provenance design doc and usage guidance.
  • UI

    • Improved terminal highlighting, YAML rendering (folded scalars respected), and two new theme colors.
  • Tests

    • Extensive unit, integration, and benchmark coverage for provenance, YAML positions, rendering, and JSONPath utilities.

…tacks

Add provenance tracking display that shows the source file and line number
for each configuration value in component and stack descriptions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@osterman osterman requested a review from a team as a code owner October 3, 2025 04:15
@github-actions github-actions bot added the size/xl Extra large size PR label Oct 3, 2025
@mergify
Copy link

mergify bot commented Oct 3, 2025

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

@osterman osterman added the no-release Do not create a new release (wait for additional code changes) label Oct 3, 2025
@codecov
Copy link

codecov bot commented Oct 3, 2025

Codecov Report

❌ Patch coverage is 81.81818% with 338 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.08%. Comparing base (96a7852) to head (9753e52).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/provenance/tree_renderer.go 45.71% 183 Missing and 7 partials ⚠️
internal/exec/describe_component.go 79.66% 43 Missing and 6 partials ⚠️
pkg/provenance/text_utils.go 83.24% 28 Missing and 2 partials ⚠️
pkg/merge/merge_with_provenance.go 84.50% 18 Missing and 4 partials ⚠️
internal/exec/stack_processor_utils.go 90.69% 9 Missing and 3 partials ⚠️
pkg/utils/yaml_position.go 87.17% 8 Missing and 2 partials ⚠️
pkg/utils/yaml_utils.go 85.24% 6 Missing and 3 partials ⚠️
pkg/utils/jsonpath.go 93.33% 5 Missing and 2 partials ⚠️
pkg/provenance/data_transform.go 90.76% 4 Missing and 2 partials ⚠️
cmd/describe_component.go 50.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1584      +/-   ##
==========================================
+ Coverage   62.11%   63.08%   +0.97%     
==========================================
  Files         316      325       +9     
  Lines       35541    37354    +1813     
==========================================
+ Hits        22077    23566    +1489     
- Misses      11513    11803     +290     
- Partials     1951     1985      +34     
Flag Coverage Δ
unittests 63.08% <81.81%> (+0.97%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
errors/errors.go 0.00% <ø> (ø)
internal/exec/describe_stacks.go 70.46% <100.00%> (-0.10%) ⬇️
internal/tui/templates/templater.go 25.38% <ø> (ø)
internal/tui/utils/utils.go 50.00% <ø> (ø)
pkg/hooks/store_cmd.go 100.00% <ø> (ø)
pkg/merge/merge.go 87.59% <100.00%> (+1.27%) ⬆️
pkg/merge/merge_context.go 97.24% <100.00%> (+1.54%) ⬆️
pkg/merge/provenance_entry.go 100.00% <100.00%> (ø)
pkg/merge/provenance_storage.go 100.00% <100.00%> (ø)
pkg/provenance/yaml_parser.go 100.00% <100.00%> (ø)
... and 14 more

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 3, 2025

📝 Walkthrough

Walkthrough

Adds end-to-end import provenance: CLI flag and exec branching, per-stack MergeContext provenance storage, provenance-aware YAML unmarshal/merge, provenance model & storage, inline/side-by-side/tree renderers, YAML position tracking, many tests/benchmarks, docs, and misc dependency/UI/import updates.

Changes

Cohort / File(s) Summary
CLI / Exec
cmd/describe_component.go, internal/exec/describe_component.go, internal/exec/describe_stacks.go, internal/exec/describe_component_provenance_test.go, cmd/describe_component_test.go
Add --provenance flag; propagate Provenance into DescribeComponentParams; add provenance-enabled exec path (ExecuteDescribeComponentWithContext / DescribeComponentResult); branch rendering/output for provenance; add CLI tests.
Stack processing / Exec utils
internal/exec/stack_processor_utils.go, internal/exec/describe_affected_test.go
Per-stack MergeContext storage (Set/Get/Clear, lastMergeContext); create per-goroutine merge contexts; record import provenance during YAML processing; small test helper refactor.
Merge core & API
pkg/merge/merge.go, pkg/merge/merge_context.go, pkg/merge/merge_with_provenance.go, pkg/merge/provenance_tracker.go, pkg/merge/*_test.go, pkg/merge/provenance_benchmark_test.go
Introduce provenance-aware merge (MergeWithProvenance); extend MergeContext with Provenance & Positions and import-depth tracking; add ProvenanceTracker interface and related tests/benchmarks.
Provenance model & storage
pkg/merge/provenance_entry.go, pkg/merge/provenance_storage.go, pkg/merge/provenance_entry_test.go, pkg/merge/provenance_storage_test.go
New ProvenanceEntry, ProvenanceType constants, deterministic hashing; thread-safe ProvenanceStorage with record/get/clone/remove APIs and tests.
Provenance rendering & transforms
pkg/provenance/tree_renderer.go, pkg/provenance/data_transform.go, pkg/provenance/yaml_parser.go, pkg/provenance/text_utils.go, pkg/provenance/*_test.go, pkg/provenance/data_transform_test.go
Add rendering subsystem (inline / side-by-side / tree), YAML line→path mapping, import→import renaming & provenance transfer, filtering empty sections by provenance, ANSI-aware wrapping and side-by-side utilities, and extensive tests.
YAML & utils
pkg/utils/yaml_utils.go, pkg/utils/yaml_position.go, pkg/utils/jsonpath.go, pkg/utils/*_test.go, pkg/utils/yaml_include_by_extension.go, pkg/utils/yq_utils.go
Add Position/PositionMap extraction, LongString folded-scalar helper, UnmarshalYAMLFromFileWithPositions, JSONPath helpers; update YAML import aliases; add tests.
Provenance tests & integration
pkg/provenance/*, pkg/merge/*, internal/exec/* tests
Large additions of unit/integration tests and benchmarks covering provenance recording, merges, rendering, YAML positions, JSONPath, and stack-level provenance behaviors.
Docs
docs/prd/import-provenance.md, website/docs/cli/commands/describe/*.mdx
New PRD and CLI docs describing --provenance flag, output formats, and usage notes.
UI / deps / misc
pkg/ui/theme/colors.go, pkg/utils/highlight_utils.go, internal/tui/utils/utils.go, go.mod, errors/errors.go, internal/tui/templates/templater.go, pkg/hooks/store_cmd.go
Add ColorYellow/ColorOrange; upgrade chroma to v2 and adapt imports; adjust terminal detection; update YAML import aliases; move ErrCommandNil sentinel; minor import/comment reorder changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant CLI
  participant Exec as Exec/Describe
  participant SP as StackProcessor
  participant YAML as YAML Unmarshal
  participant Merge as Merge (provenance)
  participant Prov as ProvenanceStorage
  participant Renderer
  participant IO

  User->>CLI: atmos describe component --provenance
  CLI->>Exec: ExecuteDescribeComponent(params{Provenance:true,...})
  Exec->>SP: process stacks (per-stack MergeContext)
  SP->>YAML: Unmarshal files -> data + PositionMap
  YAML-->>SP: data + positions
  SP->>Merge: MergeWithProvenance(inputs, ctx, positions)
  Merge->>Prov: Record provenance entries (path → ProvenanceEntry)
  Merge-->>SP: mergedData
  Exec->>Renderer: RenderInlineProvenance(mergedData, ctx, stackFile)
  Renderer-->>Exec: renderedText
  Exec->>IO: writeOutputToFile / stdout
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested labels

minor

Suggested reviewers

  • osterman

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.17% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly describes the primary change by stating the addition of the --provenance flag to the atmos describe component command, directly reflecting the PR’s main enhancement with no extraneous details.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch osterman/component-provenance

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7a726b2 and a307fab.

📒 Files selected for processing (8)
  • cmd/describe_component.go (3 hunks)
  • cmd/describe_stacks.go (2 hunks)
  • internal/exec/describe_component.go (5 hunks)
  • internal/exec/describe_stacks.go (4 hunks)
  • pkg/ui/provenance/renderer.go (1 hunks)
  • pkg/ui/provenance/renderer_test.go (1 hunks)
  • website/docs/cli/commands/describe/describe-component.mdx (3 hunks)
  • website/docs/cli/commands/describe/describe-stacks.mdx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
website/**

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

website/**: Update website documentation in website/ when adding features
Ensure consistency between CLI help text and website documentation
Follow the website's documentation structure and style
Keep website code in website/ and follow its architecture/style; test changes locally
Keep CLI and website documentation in sync; document new features with examples and use cases

Files:

  • website/docs/cli/commands/describe/describe-component.mdx
  • website/docs/cli/commands/describe/describe-stacks.mdx
website/docs/cli/commands/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

website/docs/cli/commands/**/*.mdx: All new commands/flags/parameters must have Docusaurus documentation under website/docs/cli/commands//.mdx using definition lists for arguments and flags.
Follow Docusaurus conventions (front matter, Purpose note, usage, examples; consistent section ordering: Usage → Examples → Arguments → Flags).

Files:

  • website/docs/cli/commands/describe/describe-component.mdx
  • website/docs/cli/commands/describe/describe-stacks.mdx
website/docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CLAUDE.md)

website/docs/**/*.{md,mdx}: Build the website after modifying any docs under website/docs/ to verify no broken links or formatting issues.
Document user-facing template functions in the website documentation.

Files:

  • website/docs/cli/commands/describe/describe-component.mdx
  • website/docs/cli/commands/describe/describe-stacks.mdx
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/ui/provenance/renderer_test.go
  • pkg/ui/provenance/renderer.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Use table-driven tests for unit tests.
Always use t.Skipf(...) with a clear reason when skipping tests; do not use t.Skip().
TestMain must call os.Exit(m.Run()) to propagate the test exit code for CLI tests.
Co-locate test files with implementation (use _test.go alongside .go files) and maintain naming symmetry with implementation files.

Files:

  • pkg/ui/provenance/renderer_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All Go comments must end with periods. Enforced by golangci-lint's godot.
Organize imports into three groups (stdlib, third-party, Atmos) separated by blank lines; sort alphabetically within each group; maintain existing aliases.
Add defer perf.Track(...) to all public functions and critical private functions, with a blank line after the call and package-prefixed name (e.g., "exec.ProcessComponent"). Use atmosConfig if available, otherwise nil.
Wrap all errors using static errors defined in errors/errors.go; never return dynamic errors directly.
Use the error wrapping pattern: fmt.Errorf("%w: details", errUtils.ErrStaticError, ...) with %w to preserve error chains and add context after the static error.
Bind environment variables with viper.BindEnv() and provide ATMOS_ alternatives for every env var (e.g., viper.BindEnv("ATMOS_GITHUB_TOKEN", "GITHUB_TOKEN")).
Ensure cross-platform compatibility: prefer SDKs over invoking binaries, use filepath.Join, os.PathSeparator/PathListSeparator, and runtime.GOOS when necessary.

Files:

  • pkg/ui/provenance/renderer_test.go
  • internal/exec/describe_stacks.go
  • pkg/ui/provenance/renderer.go
  • internal/exec/describe_component.go
  • cmd/describe_stacks.go
  • cmd/describe_component.go
{cmd,internal,pkg}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

{cmd,internal,pkg}/**/*.go: Do not use logging for UI output. Send prompts/status/progress and actionable errors to stderr; send data/results to stdout; keep logging for system/debug with structured fields.
Most text UI must go to stderr; only data/results go to stdout. Prefer utils.PrintfMessageToTUI for UI messages.
For non-standard execution paths, capture telemetry using telemetry.CaptureCmd(...) or telemetry.CaptureCmdString(...); never capture user data.

Files:

  • pkg/ui/provenance/renderer_test.go
  • internal/exec/describe_stacks.go
  • pkg/ui/provenance/renderer.go
  • internal/exec/describe_component.go
  • cmd/describe_stacks.go
  • cmd/describe_component.go
{internal/**/tui/**/*.go,pkg/ui/**/*.go}

📄 CodeRabbit inference engine (CLAUDE.md)

Use theme.Styles and theme.Colors with consistent Atmos theme colors from pkg/ui/theme/colors.go for TUI formatting.

Files:

  • pkg/ui/provenance/renderer_test.go
  • pkg/ui/provenance/renderer.go
{internal/exec,pkg}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

All new configs must support Go templating using FuncMap() from internal/exec/template_funcs.go.

Files:

  • pkg/ui/provenance/renderer_test.go
  • internal/exec/describe_stacks.go
  • pkg/ui/provenance/renderer.go
  • internal/exec/describe_component.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Files:

  • internal/exec/describe_stacks.go
  • pkg/ui/provenance/renderer.go
  • internal/exec/describe_component.go
  • cmd/describe_stacks.go
  • cmd/describe_component.go
cmd/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands
Implement each CLI command in a separate file under cmd/
Use Viper for managing configuration, environment variables, and flags in the CLI
Keep separation of concerns between CLI interface (cmd) and business logic
Use kebab-case for command-line flags
Provide comprehensive help text for all commands and flags
Include examples in Cobra command help
Use Viper for configuration management; support files, env vars, and flags with precedence flags > env > config > defaults
Follow single responsibility; separate command interface from business logic
Provide meaningful user feedback and include progress indicators for long-running operations
Provide clear error messages to users and troubleshooting hints where appropriate

cmd/**/*.go: Render markdown examples using utils.PrintfMarkdown() in Cobra commands that embed example usage.
One Cobra command per file in cmd/.

Files:

  • cmd/describe_stacks.go
  • cmd/describe_component.go
🧠 Learnings (3)
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
PR: cloudposse/atmos#1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.

Applied to files:

  • internal/exec/describe_stacks.go
  • internal/exec/describe_component.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
PR: cloudposse/atmos#1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • cmd/describe_component.go
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
PR: cloudposse/atmos#955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.

Applied to files:

  • website/docs/cli/commands/describe/describe-stacks.mdx
🧬 Code graph analysis (4)
pkg/ui/provenance/renderer_test.go (2)
pkg/schema/schema.go (7)
  • AtmosConfiguration (27-63)
  • ConfigSourcesStackDependencies (693-693)
  • ConfigSources (701-701)
  • ConfigSourcesItem (695-699)
  • Settings (679-683)
  • AtmosSettings (249-269)
  • Terminal (206-214)
pkg/ui/provenance/renderer.go (1)
  • NewProvenanceRenderer (27-33)
internal/exec/describe_stacks.go (6)
pkg/schema/schema.go (2)
  • AtmosConfiguration (27-63)
  • ConfigSources (701-701)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/ui/provenance/renderer.go (1)
  • NewProvenanceRenderer (27-33)
internal/exec/terraform_generate_planfile.go (1)
  • ErrInvalidFormat (21-21)
pkg/utils/yaml_utils.go (1)
  • WriteToFileAsYAML (124-137)
pkg/utils/log_utils.go (1)
  • PrintMessage (19-21)
pkg/ui/provenance/renderer.go (6)
pkg/schema/schema.go (6)
  • AtmosConfiguration (27-63)
  • ConfigSources (701-701)
  • Settings (679-683)
  • Terminal (206-214)
  • ConfigSourcesStackDependencies (693-693)
  • ConfigSourcesItem (695-699)
pkg/perf/perf.go (1)
  • Track (58-86)
internal/tui/templates/term/term_writer.go (1)
  • IsTTYSupportForStdout (83-87)
pkg/utils/yaml_utils.go (2)
  • GetHighlightedYAML (91-103)
  • ConvertToYAML (165-181)
pkg/ui/theme/colors.go (1)
  • ColorBorder (21-21)
pkg/utils/json_utils.go (1)
  • GetHighlightedJSON (28-46)
internal/exec/describe_component.go (6)
pkg/schema/schema.go (2)
  • AtmosConfiguration (27-63)
  • ConfigSources (701-701)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/ui/provenance/renderer.go (2)
  • NewProvenanceRenderer (27-33)
  • ProvenanceRenderer (22-24)
internal/exec/describe_config.go (1)
  • DescribeConfigFormatError (16-18)
pkg/utils/yaml_utils.go (1)
  • WriteToFileAsYAML (124-137)
pkg/utils/log_utils.go (1)
  • PrintMessage (19-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: website-deploy-preview
  • GitHub Check: Run pre-commit hooks
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Summary
🔇 Additional comments (25)
website/docs/cli/commands/describe/describe-component.mdx (3)

62-62: LGTM - Example follows established pattern.

The new example demonstrates the flag usage clearly and aligns with the existing command examples.


99-100: LGTM - Flag documentation is clear.

The flag description effectively communicates the purpose and behavior of --show-provenance.


880-956: LGTM - Comprehensive provenance documentation.

The documentation thoroughly covers:

  • Terminal vs non-terminal output behavior
  • JSON format with embedded provenance
  • Practical use cases
  • Connection to existing sources section

The examples and explanations provide clear guidance for users.

website/docs/cli/commands/describe/describe-stacks.mdx (2)

53-54: LGTM - Examples are consistent.

The new examples demonstrate the flag usage clearly and follow the established pattern for the stacks command.


94-95: LGTM - Flag documentation is consistent.

The flag description aligns with the component documentation and clearly explains the feature for the stacks context.

cmd/describe_component.go (2)

64-80: LGTM - Standard flag handling.

The flag retrieval and parameter passing follow the established Cobra pattern and are consistent with the other flags in this command.


95-95: LGTM - Flag registration is correct.

The flag registration follows the established pattern with an appropriate default value and clear description.

pkg/ui/provenance/renderer.go (6)

1-19: LGTM - Package structure is clean.

The package declaration, imports, and constants are well-organized. The default terminal width of 120 is a reasonable fallback.


21-33: LGTM - Constructor is clean.

The ProvenanceRenderer struct and constructor follow good practices with minimal state and proper performance tracking.


35-47: LGTM - Smart TTY-aware routing.

The RenderYAMLWithProvenance method appropriately routes to two-column or inline rendering based on TTY support, providing a good user experience in different contexts.


49-111: LGTM - Two-column rendering is well-implemented.

The two-column layout correctly:

  • Equalizes line counts with padding
  • Calculates column widths based on terminal configuration
  • Uses theme styles for consistent appearance
  • Applies proper separators

The implementation provides a clean visual experience for TTY output.


113-144: LGTM - Inline comment rendering is appropriate for non-TTY.

The inline comment approach works well for piped output, appending provenance information as YAML comments. The key matching via extractKeyFromLine is intentionally simple and works for the common cases.


146-278: LGTM - Helper functions are well-structured.

The helper functions are:

  • Focused and single-purpose
  • Properly instrumented with performance tracking
  • Handle edge cases (empty deps, non-map data)
  • Use appropriate data structures

The extractKeyFromLine implementation is intentionally simple, extracting keys up to the first colon, which works for the common YAML structure cases.

internal/exec/describe_component.go (4)

12-12: LGTM - Import is correct.

The provenance package import follows the established import organization pattern.


25-25: LGTM - Field addition is clean.

The ShowProvenance field is appropriately added to the DescribeComponentParams struct.


96-103: LGTM - Clean opt-in flow.

The early return when showProvenance is true cleanly separates the provenance rendering path from the existing pager flow, preventing double output.


153-169: LGTM - Provenance rendering is well-structured.

The renderWithProvenance function:

  • Gracefully falls back to regular rendering when no sources exist
  • Delegates format-specific rendering to a helper
  • Separates output writing concerns
  • Includes proper performance tracking
pkg/ui/provenance/renderer_test.go (1)

1-627: LGTM - Comprehensive test coverage.

The test suite provides excellent coverage with 18 test cases covering:

  • Public API (constructor, render methods)
  • Internal helpers (formatting, building, embedding)
  • Edge cases (empty deps, non-matching sources, non-map data)
  • Different rendering modes (TTY vs non-TTY, two-column vs inline)
  • Width calculations and line padding

The table-driven tests for formatStackDependencies and extractKeyFromLine follow best practices.

cmd/describe_stacks.go (2)

93-93: LGTM - Flag binding is correct.

The flag is properly mapped to the ShowProvenance field in the DescribeStacksArgs struct.


155-155: LGTM - Flag registration is consistent.

The flag registration follows the established pattern with appropriate default and description, consistent with the component command.

internal/exec/describe_stacks.go (5)

16-16: LGTM - Import is correct.

The provenance package import follows the established pattern.


33-33: LGTM - Field addition is clean.

The ShowProvenance field is appropriately added to DescribeStacksArgs, matching the component implementation.


99-102: LGTM - Clean provenance opt-in.

The early return when ShowProvenance is true cleanly separates the provenance path from the normal scroll view, consistent with the component implementation.


116-162: Rendering implementation is well-structured, but verify WriteToFileAsYAML usage.

The renderStacksWithProvenance function follows the same solid pattern as the component implementation:

  • Graceful fallback when no sources exist
  • Format-specific rendering via switch
  • Proper error handling

However, verify that u.WriteToFileAsYAML on line 153 correctly handles the output string parameter from the renderer.

This is the same verification concern as in describe_component.go - the script above will check both usages.


164-234: Source extraction is clean but returns first found sources.

The extraction helpers correctly navigate the nested stack structure (stack → components → componentType → component → sources) with proper type checking.

The implementation returns the first found ConfigSources, which is appropriate for display purposes since provenance structure is consistent across components. If multiple components have different provenance that needs merging, this would need adjustment, but for the current use case of showing "a provenance view," this is sensible.

## what
- Reverted incomplete provenance implementation from pkg/ui/provenance/
- Removed --show-provenance flags from describe component and describe stacks commands
- Created comprehensive PRD for proper line-level provenance system at docs/prd/line-level-provenance.md

## why
The initial provenance implementation had fundamental limitations:
- Only tracked top-level section keys (vars.*, settings.*), not nested values
- Two-column rendering was broken and couldn't align with complex YAML structures
- No line number tracking, only file paths
- Not reusable across different Atmos config types (stacks, atmos.yaml, vendor, workflows)
- Output polluted with 750+ lines of raw sources data
- Tests didn't catch critical bugs

## references
- PRD: docs/prd/line-level-provenance.md
- Extends existing MergeContext system (pkg/merge/merge_context.go)
- Uses gopkg.in/yaml.v3 Node API for line tracking
- Estimated 3-4 weeks for proper implementation
- Backward compatible deprecation of current sources system

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@github-actions github-actions bot added size/l Large size PR and removed size/xl Extra large size PR labels Oct 3, 2025
Renamed PRD to better reflect that we're tracking import/inheritance chains
rather than just line-level granularity. 'Import provenance' more accurately
describes tracking where values come from through the import system.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/prd/import-provenance.md (1)

100-130: Consider adding language identifier to fenced code block.

The ASCII diagram is in a fenced code block without a language specifier. While ASCII art doesn't strictly need one, adding text or ascii silences the linter.

Apply this diff:

-```
+```text
 ┌─────────────────────────────────────────────────────────────┐
 │ YAML Parser (gopkg.in/yaml.v3 Node API)                    │
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a307fab and e10d28e.

📒 Files selected for processing (3)
  • docs/prd/import-provenance.md (1 hunks)
  • internal/exec/describe_component.go (1 hunks)
  • internal/exec/describe_stacks.go (0 hunks)
💤 Files with no reviewable changes (1)
  • internal/exec/describe_stacks.go
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All Go comments must end with periods. Enforced by golangci-lint's godot.
Organize imports into three groups (stdlib, third-party, Atmos) separated by blank lines; sort alphabetically within each group; maintain existing aliases.
Add defer perf.Track(...) to all public functions and critical private functions, with a blank line after the call and package-prefixed name (e.g., "exec.ProcessComponent"). Use atmosConfig if available, otherwise nil.
Wrap all errors using static errors defined in errors/errors.go; never return dynamic errors directly.
Use the error wrapping pattern: fmt.Errorf("%w: details", errUtils.ErrStaticError, ...) with %w to preserve error chains and add context after the static error.
Bind environment variables with viper.BindEnv() and provide ATMOS_ alternatives for every env var (e.g., viper.BindEnv("ATMOS_GITHUB_TOKEN", "GITHUB_TOKEN")).
Ensure cross-platform compatibility: prefer SDKs over invoking binaries, use filepath.Join, os.PathSeparator/PathListSeparator, and runtime.GOOS when necessary.

Files:

  • internal/exec/describe_component.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Files:

  • internal/exec/describe_component.go
{cmd,internal,pkg}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

{cmd,internal,pkg}/**/*.go: Do not use logging for UI output. Send prompts/status/progress and actionable errors to stderr; send data/results to stdout; keep logging for system/debug with structured fields.
Most text UI must go to stderr; only data/results go to stdout. Prefer utils.PrintfMessageToTUI for UI messages.
For non-standard execution paths, capture telemetry using telemetry.CaptureCmd(...) or telemetry.CaptureCmdString(...); never capture user data.

Files:

  • internal/exec/describe_component.go
{internal/exec,pkg}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

All new configs must support Go templating using FuncMap() from internal/exec/template_funcs.go.

Files:

  • internal/exec/describe_component.go
🧠 Learnings (2)
📚 Learning: 2025-10-02T20:13:55.539Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-02T20:13:55.539Z
Learning: Applies to **/*.go : Add defer perf.Track(...) to all public functions and critical private functions, with a blank line after the call and package-prefixed name (e.g., "exec.ProcessComponent"). Use atmosConfig if available, otherwise nil.

Applied to files:

  • internal/exec/describe_component.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
PR: cloudposse/atmos#1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.

Applied to files:

  • internal/exec/describe_component.go
🪛 markdownlint-cli2 (0.18.1)
docs/prd/import-provenance.md

100-100: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Run pre-commit hooks
  • GitHub Check: Summary

- Implement MergeWithProvenance function to track provenance during YAML merging
- Add provenance storage and entry management with thread-safe operations
- Create tree renderer for inline provenance visualization with depth indicators
- Add YAML position extraction utilities for accurate line/column tracking
- Fix nested import provenance tracking in stack processor
- Record provenance metadata using merge context's current file
- Handle []any type for imports array in describe component output
- Add comprehensive test suite for provenance tracking functionality
- Support JSONPath addressing for nested configuration values
- Add benchmarks for provenance operations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@github-actions github-actions bot added size/xl Extra large size PR and removed size/l Large size PR labels Oct 3, 2025
@mergify
Copy link

mergify bot commented Oct 3, 2025

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
cmd/describe_component.go (1)

64-96: Use the documented --show-provenance flag name.
Docs, tests, and the PR synopsis all promise describe component --show-provenance, but the code registers --provenance. Users following the spec will hit “unknown flag” and lose the new feature. Please align the flag key (definition and lookup) with the published name.

-		provenance, err := flags.GetBool("provenance")
+		provenance, err := flags.GetBool("show-provenance")
@@
-	describeComponentCmd.PersistentFlags().Bool("provenance", false, "Enable provenance tracking to show where configuration values originated")
+	describeComponentCmd.PersistentFlags().Bool("show-provenance", false, "Enable provenance tracking to show where configuration values originated")
internal/exec/stack_processor_utils.go (1)

101-198: Data race on errorResult.

errorResult is written by multiple goroutines without synchronization; writes can race and lose earlier errors.

Apply locking to first-write and reuse it for all error assignments:

@@
-	var errorResult error
+	var errorResult error
+	var errorMu sync.Mutex
@@
-			if err != nil {
-				errorResult = err
-				return
-			}
+			if err != nil {
+				errorMu.Lock()
+				if errorResult == nil {
+					errorResult = err
+				}
+				errorMu.Unlock()
+				return
+			}
@@
-			if err != nil {
-				errorResult = err
-				return
-			}
+			if err != nil {
+				errorMu.Lock()
+				if errorResult == nil {
+					errorResult = err
+				}
+				errorMu.Unlock()
+				return
+			}
@@
-			if err != nil {
-				errorResult = err
-				return
-			}
+			if err != nil {
+				errorMu.Lock()
+				if errorResult == nil {
+					errorResult = err
+				}
+				errorMu.Unlock()
+				return
+			}

Repeat similarly for other goroutine error assignments in this function.

🧹 Nitpick comments (6)
pkg/provenance/inline_test.go (1)

26-50: Test doesn't verify provenance comments are added.

TestRenderInline_WithProvenance only asserts that YAML content is present, but doesn't verify that provenance comments are actually appended. Since RenderInline has placeholder logic (as noted in inline.go review), this test passes despite the incomplete implementation.

Add an assertion to verify provenance comments appear in the output:

 	result, err := RenderInline(data, ctx)
 
 	require.NoError(t, err)
-	// Should contain valid YAML.
 	assert.Contains(t, result, "name: test")
 	assert.Contains(t, result, "value: 42")
+	// Should contain provenance comment.
+	assert.Contains(t, result, "# from: config.yaml:10:5")

This will fail until the RenderInline implementation is completed.

pkg/merge/merge_with_provenance_test.go (1)

4-11: Optional: run tests in parallel.

Consider t.Parallel() in each test to speed up the suite; tests don’t share state.

pkg/provenance/import_provenance_test.go (2)

83-91: Stabilize output by disabling colors/highlighting in tests.

RenderInlineProvenanceWithStackFile may emit ANSI. Set atmosConfig.Settings.Terminal.Color = false and disable syntax highlighting to avoid flaky Contains checks.

As per coding guidelines

Also applies to: 151-159, 244-252


166-177: Simplify symbol counting.

Use strings.Count(output, "● [0]") instead of a manual search loop.

internal/exec/stack_processor_utils.go (1)

206-211: Avoid storing a shared context after wg (stale/incomplete).

With per-goroutine contexts, this SetLastMergeContext(sharedMergeContext) is misleading. Remove it or aggregate provenance then set once.

-	if sharedMergeContext != nil && sharedMergeContext.IsProvenanceEnabled() {
-		SetLastMergeContext(sharedMergeContext)
-	}
+	// Intentionally left empty. Use an aggregated context if needed.

As per coding guidelines

pkg/utils/jsonpath.go (1)

9-28: Optional: avoid fmt in hot paths.

AppendJSONPathIndex can use strings.Builder or strconv.AppendInt to avoid fmt overhead if on hot paths.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e10d28e and 71d98a5.

📒 Files selected for processing (28)
  • cmd/describe_component.go (3 hunks)
  • internal/exec/describe_component.go (8 hunks)
  • internal/exec/describe_component_provenance_test.go (1 hunks)
  • internal/exec/describe_component_test.go (2 hunks)
  • internal/exec/stack_processor_utils.go (11 hunks)
  • pkg/merge/integration_test.go (1 hunks)
  • pkg/merge/merge.go (1 hunks)
  • pkg/merge/merge_context.go (5 hunks)
  • pkg/merge/merge_context_test.go (1 hunks)
  • pkg/merge/merge_with_provenance.go (1 hunks)
  • pkg/merge/merge_with_provenance_test.go (1 hunks)
  • pkg/merge/provenance_benchmark_test.go (1 hunks)
  • pkg/merge/provenance_entry.go (1 hunks)
  • pkg/merge/provenance_entry_test.go (1 hunks)
  • pkg/merge/provenance_storage.go (1 hunks)
  • pkg/merge/provenance_storage_test.go (1 hunks)
  • pkg/provenance/import_provenance_test.go (1 hunks)
  • pkg/provenance/inline.go (1 hunks)
  • pkg/provenance/inline_test.go (1 hunks)
  • pkg/provenance/tree_renderer.go (1 hunks)
  • pkg/provenance/tree_renderer_test.go (1 hunks)
  • pkg/schema/schema.go (1 hunks)
  • pkg/ui/theme/colors.go (1 hunks)
  • pkg/utils/jsonpath.go (1 hunks)
  • pkg/utils/jsonpath_test.go (1 hunks)
  • pkg/utils/yaml_position.go (1 hunks)
  • pkg/utils/yaml_position_test.go (1 hunks)
  • pkg/utils/yaml_utils.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/ui/theme/colors.go
  • pkg/merge/merge.go
  • pkg/utils/yaml_utils.go
  • pkg/merge/provenance_storage_test.go
  • pkg/provenance/tree_renderer_test.go
  • pkg/merge/merge_with_provenance.go
  • pkg/provenance/inline_test.go
  • pkg/merge/integration_test.go
  • pkg/provenance/import_provenance_test.go
  • pkg/merge/merge_context_test.go
  • pkg/merge/provenance_entry.go
  • pkg/merge/provenance_benchmark_test.go
  • pkg/merge/merge_context.go
  • pkg/utils/jsonpath_test.go
  • pkg/merge/provenance_storage.go
  • pkg/schema/schema.go
  • pkg/merge/merge_with_provenance_test.go
  • pkg/merge/provenance_entry_test.go
  • pkg/provenance/inline.go
  • pkg/utils/jsonpath.go
  • pkg/utils/yaml_position.go
  • pkg/utils/yaml_position_test.go
  • pkg/provenance/tree_renderer.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All Go comments must end with periods. Enforced by golangci-lint's godot.
Organize imports into three groups (stdlib, third-party, Atmos) separated by blank lines; sort alphabetically within each group; maintain existing aliases.
Add defer perf.Track(...) to all public functions and critical private functions, with a blank line after the call and package-prefixed name (e.g., "exec.ProcessComponent"). Use atmosConfig if available, otherwise nil.
Wrap all errors using static errors defined in errors/errors.go; never return dynamic errors directly.
Use the error wrapping pattern: fmt.Errorf("%w: details", errUtils.ErrStaticError, ...) with %w to preserve error chains and add context after the static error.
Bind environment variables with viper.BindEnv() and provide ATMOS_ alternatives for every env var (e.g., viper.BindEnv("ATMOS_GITHUB_TOKEN", "GITHUB_TOKEN")).
Ensure cross-platform compatibility: prefer SDKs over invoking binaries, use filepath.Join, os.PathSeparator/PathListSeparator, and runtime.GOOS when necessary.

Files:

  • pkg/ui/theme/colors.go
  • pkg/merge/merge.go
  • pkg/utils/yaml_utils.go
  • pkg/merge/provenance_storage_test.go
  • pkg/provenance/tree_renderer_test.go
  • pkg/merge/merge_with_provenance.go
  • pkg/provenance/inline_test.go
  • pkg/merge/integration_test.go
  • cmd/describe_component.go
  • pkg/provenance/import_provenance_test.go
  • pkg/merge/merge_context_test.go
  • pkg/merge/provenance_entry.go
  • pkg/merge/provenance_benchmark_test.go
  • pkg/merge/merge_context.go
  • pkg/utils/jsonpath_test.go
  • pkg/merge/provenance_storage.go
  • pkg/schema/schema.go
  • pkg/merge/merge_with_provenance_test.go
  • internal/exec/stack_processor_utils.go
  • internal/exec/describe_component_provenance_test.go
  • pkg/merge/provenance_entry_test.go
  • internal/exec/describe_component_test.go
  • pkg/provenance/inline.go
  • pkg/utils/jsonpath.go
  • pkg/utils/yaml_position.go
  • pkg/utils/yaml_position_test.go
  • pkg/provenance/tree_renderer.go
  • internal/exec/describe_component.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Files:

  • pkg/ui/theme/colors.go
  • pkg/merge/merge.go
  • pkg/utils/yaml_utils.go
  • pkg/merge/merge_with_provenance.go
  • cmd/describe_component.go
  • pkg/merge/provenance_entry.go
  • pkg/merge/merge_context.go
  • pkg/merge/provenance_storage.go
  • pkg/schema/schema.go
  • internal/exec/stack_processor_utils.go
  • pkg/provenance/inline.go
  • pkg/utils/jsonpath.go
  • pkg/utils/yaml_position.go
  • pkg/provenance/tree_renderer.go
  • internal/exec/describe_component.go
{cmd,internal,pkg}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

{cmd,internal,pkg}/**/*.go: Do not use logging for UI output. Send prompts/status/progress and actionable errors to stderr; send data/results to stdout; keep logging for system/debug with structured fields.
Most text UI must go to stderr; only data/results go to stdout. Prefer utils.PrintfMessageToTUI for UI messages.
For non-standard execution paths, capture telemetry using telemetry.CaptureCmd(...) or telemetry.CaptureCmdString(...); never capture user data.

Files:

  • pkg/ui/theme/colors.go
  • pkg/merge/merge.go
  • pkg/utils/yaml_utils.go
  • pkg/merge/provenance_storage_test.go
  • pkg/provenance/tree_renderer_test.go
  • pkg/merge/merge_with_provenance.go
  • pkg/provenance/inline_test.go
  • pkg/merge/integration_test.go
  • cmd/describe_component.go
  • pkg/provenance/import_provenance_test.go
  • pkg/merge/merge_context_test.go
  • pkg/merge/provenance_entry.go
  • pkg/merge/provenance_benchmark_test.go
  • pkg/merge/merge_context.go
  • pkg/utils/jsonpath_test.go
  • pkg/merge/provenance_storage.go
  • pkg/schema/schema.go
  • pkg/merge/merge_with_provenance_test.go
  • internal/exec/stack_processor_utils.go
  • internal/exec/describe_component_provenance_test.go
  • pkg/merge/provenance_entry_test.go
  • internal/exec/describe_component_test.go
  • pkg/provenance/inline.go
  • pkg/utils/jsonpath.go
  • pkg/utils/yaml_position.go
  • pkg/utils/yaml_position_test.go
  • pkg/provenance/tree_renderer.go
  • internal/exec/describe_component.go
{internal/**/tui/**/*.go,pkg/ui/**/*.go}

📄 CodeRabbit inference engine (CLAUDE.md)

Use theme.Styles and theme.Colors with consistent Atmos theme colors from pkg/ui/theme/colors.go for TUI formatting.

Files:

  • pkg/ui/theme/colors.go
{internal/exec,pkg}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

All new configs must support Go templating using FuncMap() from internal/exec/template_funcs.go.

Files:

  • pkg/ui/theme/colors.go
  • pkg/merge/merge.go
  • pkg/utils/yaml_utils.go
  • pkg/merge/provenance_storage_test.go
  • pkg/provenance/tree_renderer_test.go
  • pkg/merge/merge_with_provenance.go
  • pkg/provenance/inline_test.go
  • pkg/merge/integration_test.go
  • pkg/provenance/import_provenance_test.go
  • pkg/merge/merge_context_test.go
  • pkg/merge/provenance_entry.go
  • pkg/merge/provenance_benchmark_test.go
  • pkg/merge/merge_context.go
  • pkg/utils/jsonpath_test.go
  • pkg/merge/provenance_storage.go
  • pkg/schema/schema.go
  • pkg/merge/merge_with_provenance_test.go
  • internal/exec/stack_processor_utils.go
  • internal/exec/describe_component_provenance_test.go
  • pkg/merge/provenance_entry_test.go
  • internal/exec/describe_component_test.go
  • pkg/provenance/inline.go
  • pkg/utils/jsonpath.go
  • pkg/utils/yaml_position.go
  • pkg/utils/yaml_position_test.go
  • pkg/provenance/tree_renderer.go
  • internal/exec/describe_component.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Use table-driven tests for unit tests.
Always use t.Skipf(...) with a clear reason when skipping tests; do not use t.Skip().
TestMain must call os.Exit(m.Run()) to propagate the test exit code for CLI tests.
Co-locate test files with implementation (use _test.go alongside .go files) and maintain naming symmetry with implementation files.

Files:

  • pkg/merge/provenance_storage_test.go
  • pkg/provenance/tree_renderer_test.go
  • pkg/provenance/inline_test.go
  • pkg/merge/integration_test.go
  • pkg/provenance/import_provenance_test.go
  • pkg/merge/merge_context_test.go
  • pkg/merge/provenance_benchmark_test.go
  • pkg/utils/jsonpath_test.go
  • pkg/merge/merge_with_provenance_test.go
  • internal/exec/describe_component_provenance_test.go
  • pkg/merge/provenance_entry_test.go
  • internal/exec/describe_component_test.go
  • pkg/utils/yaml_position_test.go
cmd/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands
Implement each CLI command in a separate file under cmd/
Use Viper for managing configuration, environment variables, and flags in the CLI
Keep separation of concerns between CLI interface (cmd) and business logic
Use kebab-case for command-line flags
Provide comprehensive help text for all commands and flags
Include examples in Cobra command help
Use Viper for configuration management; support files, env vars, and flags with precedence flags > env > config > defaults
Follow single responsibility; separate command interface from business logic
Provide meaningful user feedback and include progress indicators for long-running operations
Provide clear error messages to users and troubleshooting hints where appropriate

cmd/**/*.go: Render markdown examples using utils.PrintfMarkdown() in Cobra commands that embed example usage.
One Cobra command per file in cmd/.

Files:

  • cmd/describe_component.go
internal/exec/stack_processor_utils.go

📄 CodeRabbit inference engine (CLAUDE.md)

For stack processing utilities, change internal/exec/stack_processor_utils.go and ensure template rendering still works.

Files:

  • internal/exec/stack_processor_utils.go
internal/exec/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

Add comprehensive tests for new template functions in internal/exec/.

Files:

  • internal/exec/describe_component_provenance_test.go
  • internal/exec/describe_component_test.go
🧠 Learnings (5)
📚 Learning: 2025-09-23T02:30:42.362Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests

Applied to files:

  • pkg/utils/jsonpath_test.go
📚 Learning: 2025-10-02T20:13:55.579Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-02T20:13:55.579Z
Learning: Applies to **/*_test.go : Use table-driven tests for unit tests.

Applied to files:

  • pkg/utils/jsonpath_test.go
📚 Learning: 2025-10-02T20:13:55.579Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-02T20:13:55.579Z
Learning: Applies to internal/exec/**/*_test.go : Add comprehensive tests for new template functions in internal/exec/.

Applied to files:

  • internal/exec/describe_component_provenance_test.go
  • internal/exec/describe_component_test.go
📚 Learning: 2025-10-02T20:13:55.579Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-02T20:13:55.579Z
Learning: Applies to **/*.go : Add defer perf.Track(...) to all public functions and critical private functions, with a blank line after the call and package-prefixed name (e.g., "exec.ProcessComponent"). Use atmosConfig if available, otherwise nil.

Applied to files:

  • internal/exec/describe_component.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
PR: cloudposse/atmos#1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.

Applied to files:

  • internal/exec/describe_component.go
🧬 Code graph analysis (24)
pkg/merge/merge.go (1)
pkg/merge/merge_with_provenance.go (1)
  • MergeWithProvenance (19-43)
pkg/utils/yaml_utils.go (3)
pkg/schema/schema.go (1)
  • AtmosConfiguration (27-64)
pkg/utils/yaml_position.go (2)
  • PositionMap (14-14)
  • ExtractYAMLPositions (19-27)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/merge/provenance_storage_test.go (2)
pkg/merge/provenance_storage.go (2)
  • NewProvenanceStorage (22-26)
  • ProvenanceStorage (11-19)
pkg/merge/provenance_entry.go (4)
  • ProvenanceEntry (30-49)
  • ProvenanceTypeInline (16-16)
  • ProvenanceTypeImport (13-13)
  • ProvenanceTypeOverride (19-19)
pkg/provenance/tree_renderer_test.go (1)
pkg/provenance/tree_renderer.go (1)
  • YAMLLineInfo (42-46)
pkg/merge/merge_with_provenance.go (6)
pkg/schema/schema.go (1)
  • AtmosConfiguration (27-64)
pkg/merge/merge_context.go (1)
  • MergeContext (13-33)
pkg/utils/yaml_position.go (2)
  • PositionMap (14-14)
  • GetYAMLPosition (105-116)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/merge/provenance_entry.go (4)
  • ProvenanceTypeInline (16-16)
  • ProvenanceType (9-9)
  • ProvenanceTypeImport (13-13)
  • ProvenanceEntry (30-49)
pkg/utils/jsonpath.go (2)
  • AppendJSONPathKey (35-43)
  • AppendJSONPathIndex (50-56)
pkg/provenance/inline_test.go (3)
pkg/provenance/inline.go (2)
  • RenderInline (17-56)
  • FormatProvenanceComment (59-64)
pkg/merge/merge_context.go (1)
  • NewMergeContext (36-40)
pkg/merge/provenance_entry.go (2)
  • ProvenanceEntry (30-49)
  • ProvenanceTypeInline (16-16)
pkg/merge/integration_test.go (5)
pkg/utils/yaml_utils.go (1)
  • UnmarshalYAML (234-236)
pkg/utils/yaml_position.go (1)
  • PositionMap (14-14)
pkg/merge/merge_context.go (1)
  • NewMergeContext (36-40)
pkg/schema/schema.go (1)
  • AtmosConfiguration (27-64)
pkg/merge/merge_with_provenance.go (1)
  • MergeWithProvenance (19-43)
pkg/provenance/import_provenance_test.go (4)
pkg/merge/merge_context.go (1)
  • NewMergeContext (36-40)
pkg/merge/provenance_entry.go (3)
  • ProvenanceEntry (30-49)
  • ProvenanceTypeInline (16-16)
  • ProvenanceTypeImport (13-13)
pkg/schema/schema.go (4)
  • AtmosConfiguration (27-64)
  • Settings (680-684)
  • AtmosSettings (250-270)
  • Terminal (207-215)
pkg/provenance/tree_renderer.go (1)
  • RenderInlineProvenanceWithStackFile (612-711)
pkg/merge/merge_context_test.go (2)
pkg/merge/merge_context.go (2)
  • MergeContext (13-33)
  • NewMergeContext (36-40)
pkg/merge/provenance_entry.go (5)
  • ProvenanceEntry (30-49)
  • ProvenanceTypeInline (16-16)
  • ProvenanceTypeImport (13-13)
  • ProvenanceTypeOverride (19-19)
  • ProvenanceType (9-9)
pkg/merge/provenance_benchmark_test.go (3)
pkg/merge/merge_context.go (1)
  • NewMergeContext (36-40)
pkg/merge/provenance_entry.go (2)
  • ProvenanceEntry (30-49)
  • ProvenanceTypeInline (16-16)
pkg/merge/provenance_storage.go (1)
  • NewProvenanceStorage (22-26)
pkg/merge/merge_context.go (3)
pkg/merge/provenance_storage.go (2)
  • ProvenanceStorage (11-19)
  • NewProvenanceStorage (22-26)
pkg/utils/yaml_position.go (1)
  • PositionMap (14-14)
pkg/merge/provenance_entry.go (4)
  • ProvenanceEntry (30-49)
  • ProvenanceType (9-9)
  • ProvenanceTypeInline (16-16)
  • ProvenanceTypeImport (13-13)
pkg/utils/jsonpath_test.go (1)
pkg/utils/jsonpath.go (8)
  • BuildJSONPath (14-28)
  • AppendJSONPathKey (35-43)
  • AppendJSONPathIndex (50-56)
  • SplitJSONPath (64-106)
  • ParseJSONPathIndex (114-126)
  • IsJSONPathIndex (133-136)
  • GetJSONPathParent (144-165)
  • GetJSONPathLeaf (173-184)
pkg/merge/provenance_storage.go (1)
pkg/merge/provenance_entry.go (1)
  • ProvenanceEntry (30-49)
pkg/schema/schema.go (2)
pkg/store/registry.go (1)
  • StoreRegistry (7-7)
pkg/profiler/profiler.go (1)
  • Config (60-66)
pkg/merge/merge_with_provenance_test.go (5)
pkg/schema/schema.go (1)
  • AtmosConfiguration (27-64)
pkg/merge/merge_context.go (2)
  • NewMergeContext (36-40)
  • MergeContext (13-33)
pkg/merge/merge_with_provenance.go (1)
  • MergeWithProvenance (19-43)
pkg/utils/yaml_position.go (1)
  • PositionMap (14-14)
pkg/merge/provenance_entry.go (2)
  • ProvenanceTypeInline (16-16)
  • ProvenanceTypeImport (13-13)
internal/exec/stack_processor_utils.go (4)
pkg/merge/merge_context.go (2)
  • MergeContext (13-33)
  • NewMergeContext (36-40)
pkg/utils/yaml_utils.go (1)
  • UnmarshalYAMLFromFileWithPositions (269-302)
pkg/schema/schema.go (1)
  • AtmosSectionMapType (14-14)
pkg/merge/provenance_entry.go (1)
  • ProvenanceEntry (30-49)
internal/exec/describe_component_provenance_test.go (4)
pkg/schema/schema.go (1)
  • ConfigAndStacksInfo (458-535)
internal/exec/stack_processor_utils.go (1)
  • ClearLastMergeContext (57-61)
internal/exec/describe_component.go (1)
  • ExecuteDescribeComponentWithContext (205-351)
pkg/merge/merge_context.go (1)
  • MergeContext (13-33)
pkg/merge/provenance_entry_test.go (1)
pkg/merge/provenance_entry.go (8)
  • ProvenanceType (9-9)
  • ProvenanceEntry (30-49)
  • ProvenanceTypeInline (16-16)
  • ProvenanceTypeImport (13-13)
  • ProvenanceTypeOverride (19-19)
  • ProvenanceTypeComputed (22-22)
  • NewProvenanceEntry (52-61)
  • ProvenanceTypeDefault (25-25)
internal/exec/describe_component_test.go (5)
pkg/logger/log.go (3)
  • SetLevel (84-86)
  • SetOutput (94-96)
  • Logf (79-81)
internal/exec/describe_component.go (5)
  • ExecuteDescribeComponent (190-202)
  • NewDescribeComponentExec (41-50)
  • DescribeComponentParams (20-30)
  • DescribeComponentResult (183-187)
  • FilterComputedFields (355-380)
internal/exec/stack_processor_utils.go (1)
  • GetLastMergeContext (50-54)
pkg/merge/merge_context.go (1)
  • MergeContext (13-33)
pkg/utils/yaml_utils.go (1)
  • ConvertToYAML (165-181)
pkg/provenance/inline.go (2)
pkg/merge/merge_context.go (1)
  • MergeContext (13-33)
pkg/merge/provenance_entry.go (1)
  • ProvenanceEntry (30-49)
pkg/utils/yaml_position.go (1)
pkg/utils/jsonpath.go (2)
  • AppendJSONPathKey (35-43)
  • AppendJSONPathIndex (50-56)
pkg/utils/yaml_position_test.go (1)
pkg/utils/yaml_position.go (5)
  • ExtractYAMLPositions (19-27)
  • HasYAMLPosition (119-126)
  • PositionMap (14-14)
  • Position (8-11)
  • GetYAMLPosition (105-116)
pkg/provenance/tree_renderer.go (6)
pkg/merge/merge_context.go (1)
  • MergeContext (13-33)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/merge/provenance_entry.go (6)
  • ProvenanceTypeComputed (22-22)
  • ProvenanceEntry (30-49)
  • ProvenanceTypeInline (16-16)
  • ProvenanceTypeOverride (19-19)
  • ProvenanceTypeImport (13-13)
  • ProvenanceTypeDefault (25-25)
pkg/ui/theme/colors.go (7)
  • ColorSelectedItem (22-22)
  • ColorCyan (12-12)
  • ColorDarkGray (15-15)
  • ColorGreen (11-11)
  • ColorYellow (17-17)
  • ColorOrange (18-18)
  • ColorRed (16-16)
pkg/utils/yaml_utils.go (1)
  • ConvertToYAML (165-181)
pkg/utils/highlight_utils.go (1)
  • HighlightCodeWithConfig (81-122)
internal/exec/describe_component.go (10)
pkg/merge/merge_context.go (1)
  • MergeContext (13-33)
pkg/provenance/tree_renderer.go (1)
  • RenderInlineProvenanceWithStackFile (612-711)
pkg/utils/log_utils.go (1)
  • PrintfMessageToTUI (29-31)
pkg/schema/schema.go (2)
  • AtmosConfiguration (27-64)
  • ConfigAndStacksInfo (458-535)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/config/config.go (1)
  • InitCliConfig (25-62)
internal/exec/stack_processor_utils.go (2)
  • ClearLastMergeContext (57-61)
  • GetLastMergeContext (50-54)
internal/exec/utils.go (1)
  • ProcessStacks (185-573)
pkg/merge/provenance_entry.go (1)
  • ProvenanceEntry (30-49)
internal/exec/filter_utils.go (2)
  • GetIncludeEmptySetting (60-67)
  • FilterEmptySections (51-58)
🪛 GitHub Check: Build (macos-latest, macos)
pkg/utils/yaml_utils.go

[failure] 288-288:
cannot use &node (value of type *"go.yaml.in/yaml/v3".Node) as *"gopkg.in/yaml.v3".Node value in argument to ExtractYAMLPositions

🪛 GitHub Check: Build (ubuntu-latest, linux)
pkg/utils/yaml_utils.go

[failure] 288-288:
cannot use &node (value of type *"go.yaml.in/yaml/v3".Node) as *"gopkg.in/yaml.v3".Node value in argument to ExtractYAMLPositions

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: Run pre-commit hooks
  • GitHub Check: Summary
🔇 Additional comments (9)
pkg/merge/merge_context_test.go (1)

280-585: Solid provenance test coverage.

The test suite comprehensively validates provenance handling across edge cases including nil contexts, idempotency, cloning semantics, and type determination. Well done.

pkg/provenance/tree_renderer_test.go (1)

10-179: Thorough multiline YAML and path normalization tests.

The test suite covers complex YAML structures including literal/folded scalars, nested maps, and edge cases. The path normalization tests validate component prefix stripping correctly.

pkg/merge/provenance_entry_test.go (1)

10-526: Excellent provenance entry test coverage.

The test suite is comprehensive, covering all ProvenanceEntry operations with proper nil handling, equality checks, and hash validation. The constant verification is particularly thorough.

pkg/utils/yaml_position_test.go (1)

11-384: Comprehensive YAML position extraction tests.

The test suite thoroughly covers position extraction across diverse YAML structures including nested maps, arrays, multiline content, and real-world Atmos configurations. Edge cases like nil nodes and disabled extraction are properly tested.

pkg/merge/provenance_storage_test.go (1)

11-566: Robust provenance storage tests with concurrency validation.

The test suite comprehensively validates all storage operations including the critical concurrent access scenario. The concurrent test with 10 goroutines and 100 operations each properly validates thread safety.

pkg/utils/yaml_utils.go (1)

269-302: No action needed for nil positions
Go’s built-in len on a nil map returns 0, and callers only use positions when TrackProvenance is true and len(positions)>0, so returning nil poses no risk.

Likely an incorrect or invalid review comment.

pkg/merge/merge_with_provenance_test.go (1)

13-82: Solid coverage and assertions.

Nice spread across scenarios; positions, depth, arrays, and multi-inputs are well exercised.

Also applies to: 84-141, 161-196, 198-235, 236-262, 264-316

pkg/merge/merge_with_provenance.go (1)

19-43: Looks good.

Provenance recording is clear, depth-aware, and guarded behind the flag/context. perf.Track included.

Also applies to: 45-89, 91-124, 125-141

pkg/utils/jsonpath.go (1)

9-28: LGTM.

Handy helpers with clear docs.

Also applies to: 30-56, 58-106, 108-136, 138-166, 167-184

@osterman osterman changed the title feat: add --show-provenance flag to describe component and describe stacks feat: add --provenance flag to describe component and describe stacks Oct 3, 2025
@osterman osterman changed the title feat: add --provenance flag to describe component and describe stacks feat: add --provenance flag to describe component and describe stacks Oct 3, 2025
- Update provenance legend: change "Defined at this level" to "Defined in parent stack"
- Add LongString type that encodes as YAML folded scalars (>-) for long strings
- Add WrapLongStrings function to automatically wrap long strings in YAML output
- Integrate line wrapping in provenance renderer to prevent horizontal scrolling
- Long values like atmos_component_description now wrap properly with provenance comments aligned

This improves readability of provenance output by ensuring long string values are wrapped
using proper YAML folded scalar syntax, keeping provenance comments aligned at the comment
column and preventing the need for horizontal scrolling.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@osterman osterman changed the title feat: add --provenance flag to describe component and describe stacks feat: add --provenance flag to describe component and describe stacks Oct 3, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
pkg/utils/yaml_utils.go (1)

339-339: Resolve the yaml module path mismatch.

The build failure at Line 339 occurs because &node is typed as *go.yaml.in/yaml/v3.Node but ExtractYAMLPositions expects *gopkg.in/yaml.v3.Node. This indicates inconsistent imports across the codebase.

As noted in the previous review, run the following script to identify all yaml.v3 imports and standardize them to gopkg.in/yaml.v3:

#!/bin/bash
# Find all yaml.v3 import paths in Go files
rg -nP '^\s*"(gopkg\.in/yaml\.v3|go\.yaml\.in/yaml/v3)"' --type=go

Update all imports to use the same module path, update go.mod, and run go mod tidy to resolve the conflict.

pkg/provenance/tree_renderer.go (1)

315-389: Array provenance missing for list items.

- key: entries still emit vars.items.name, but provenance is stored as vars.items[0].name, vars.items[1].name, etc., so inline comments vanish for arrays of maps. Please carry the per-level index into the key path when trimming the - prefix (and bump it afterwards) so the generated path matches storage.

Apply this diff to thread the index into the composed path:

-           if strings.HasPrefix(key, "- ") {
-               key = strings.TrimPrefix(key, "- ")
-               key = strings.TrimSpace(key)
-           }
-
-           // Build full path
-           currentPath := key
-           if len(pathStack) > 0 {
-               currentPath = strings.Join(append(pathStack, key), ".")
-           }
+           var currentPath string
+           if strings.HasPrefix(key, "- ") {
+               key = strings.TrimSpace(strings.TrimPrefix(key, "- "))
+
+               if len(pathStack) > 0 {
+                   parent := pathStack[len(pathStack)-1]
+                   idx := 0
+                   if len(arrayIndexStack) > 0 {
+                       idx = arrayIndexStack[len(arrayIndexStack)-1]
+                       arrayIndexStack[len(arrayIndexStack)-1]++
+                   } else {
+                       arrayIndexStack = append(arrayIndexStack, 1)
+                   }
+                   currentPath = fmt.Sprintf("%s[%d].%s", parent, idx, key)
+               } else {
+                   currentPath = key
+               }
+           } else {
+               currentPath = key
+               if len(pathStack) > 0 {
+                   currentPath = strings.Join(append(pathStack, key), ".")
+               }
+           }
🧹 Nitpick comments (1)
pkg/utils/yaml_utils.go (1)

165-177: Consider adding perf tracking to MarshalYAML.

The coding guidelines require defer perf.Track(...) in all public functions. While this method is very lightweight, adding tracking would align with the guidelines. You could pass nil for atmosConfig since it's not available in this context.

Apply this diff if you choose to add tracking:

 func (s LongString) MarshalYAML() (interface{}, error) {
+	defer perf.Track(nil, "utils.LongString.MarshalYAML")()
+
 	node := &yaml.Node{
 		Kind:  yaml.ScalarNode,
 		Style: yaml.FoldedStyle, // Use > style for folded scalar
 		Value: string(s),
 	}
 	return node, nil
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 71d98a5 and 7bc8d59.

📒 Files selected for processing (2)
  • pkg/provenance/tree_renderer.go (1 hunks)
  • pkg/utils/yaml_utils.go (2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/utils/yaml_utils.go
  • pkg/provenance/tree_renderer.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All Go comments must end with periods. Enforced by golangci-lint's godot.
Organize imports into three groups (stdlib, third-party, Atmos) separated by blank lines; sort alphabetically within each group; maintain existing aliases.
Add defer perf.Track(...) to all public functions and critical private functions, with a blank line after the call and package-prefixed name (e.g., "exec.ProcessComponent"). Use atmosConfig if available, otherwise nil.
Wrap all errors using static errors defined in errors/errors.go; never return dynamic errors directly.
Use the error wrapping pattern: fmt.Errorf("%w: details", errUtils.ErrStaticError, ...) with %w to preserve error chains and add context after the static error.
Bind environment variables with viper.BindEnv() and provide ATMOS_ alternatives for every env var (e.g., viper.BindEnv("ATMOS_GITHUB_TOKEN", "GITHUB_TOKEN")).
Ensure cross-platform compatibility: prefer SDKs over invoking binaries, use filepath.Join, os.PathSeparator/PathListSeparator, and runtime.GOOS when necessary.

Files:

  • pkg/utils/yaml_utils.go
  • pkg/provenance/tree_renderer.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Files:

  • pkg/utils/yaml_utils.go
  • pkg/provenance/tree_renderer.go
{cmd,internal,pkg}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

{cmd,internal,pkg}/**/*.go: Do not use logging for UI output. Send prompts/status/progress and actionable errors to stderr; send data/results to stdout; keep logging for system/debug with structured fields.
Most text UI must go to stderr; only data/results go to stdout. Prefer utils.PrintfMessageToTUI for UI messages.
For non-standard execution paths, capture telemetry using telemetry.CaptureCmd(...) or telemetry.CaptureCmdString(...); never capture user data.

Files:

  • pkg/utils/yaml_utils.go
  • pkg/provenance/tree_renderer.go
{internal/exec,pkg}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

All new configs must support Go templating using FuncMap() from internal/exec/template_funcs.go.

Files:

  • pkg/utils/yaml_utils.go
  • pkg/provenance/tree_renderer.go
🧬 Code graph analysis (2)
pkg/utils/yaml_utils.go (3)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/schema/schema.go (1)
  • AtmosConfiguration (27-64)
pkg/utils/yaml_position.go (2)
  • PositionMap (14-14)
  • ExtractYAMLPositions (19-27)
pkg/provenance/tree_renderer.go (6)
pkg/merge/merge_context.go (1)
  • MergeContext (13-33)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/merge/provenance_entry.go (6)
  • ProvenanceTypeComputed (22-22)
  • ProvenanceEntry (30-49)
  • ProvenanceTypeInline (16-16)
  • ProvenanceTypeOverride (19-19)
  • ProvenanceTypeImport (13-13)
  • ProvenanceTypeDefault (25-25)
pkg/ui/theme/colors.go (7)
  • ColorSelectedItem (22-22)
  • ColorCyan (12-12)
  • ColorDarkGray (15-15)
  • ColorGreen (11-11)
  • ColorYellow (17-17)
  • ColorOrange (18-18)
  • ColorRed (16-16)
pkg/utils/yaml_utils.go (2)
  • ConvertToYAML (216-232)
  • WrapLongStrings (181-214)
pkg/utils/highlight_utils.go (1)
  • HighlightCodeWithConfig (81-122)
🪛 GitHub Check: Build (macos-latest, macos)
pkg/utils/yaml_utils.go

[failure] 339-339:
cannot use &node (value of type *"go.yaml.in/yaml/v3".Node) as *"gopkg.in/yaml.v3".Node value in argument to ExtractYAMLPositions

🪛 GitHub Check: Build (ubuntu-latest, linux)
pkg/utils/yaml_utils.go

[failure] 339-339:
cannot use &node (value of type *"go.yaml.in/yaml/v3".Node) as *"gopkg.in/yaml.v3".Node value in argument to ExtractYAMLPositions

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: Run pre-commit hooks
  • GitHub Check: Summary
🔇 Additional comments (2)
pkg/utils/yaml_utils.go (2)

179-214: LGTM on the long string wrapping logic.

The function correctly handles recursive traversal of maps and slices, and the decision to wrap only single-line strings longer than maxLength is sound. The early return for maxLength <= 0 and the exclusion of multi-line strings are both sensible.


317-353: Approve the provenance tracking logic.

The implementation correctly integrates position extraction when atmosConfig.TrackProvenance is enabled, and the function signature with PositionMap return aligns well with the PR objectives. Once the yaml module path issue is resolved, this function should work as intended.

Verify that all call sites of this function properly handle the PositionMap return value and that the positions are correctly propagated to downstream provenance consumers.

@aknysh aknysh changed the title Add --provenance flag to describe component Add --provenance flag to atmos describe component Oct 6, 2025
@aknysh
Copy link
Member

aknysh commented Oct 6, 2025

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 6, 2025

✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
pkg/merge/merge_with_provenance_test.go (2)

161-196: Consider verifying provenance details for both base and override.

The test merges two inputs but only checks that provenance exists for the override value. Consider verifying:

  • Override provenance has correct line/column from positions
  • Base provenance exists with 0 line/column (no positions provided)

This would make the test more comprehensive and better document the expected behavior when merging inputs with partial position data.


354-359: Clarify scalar-array merge comment
Update the test’s comment to reflect that “merge” (WithSliceDeepCopy) preserves the base slice for scalar arrays (ignoring override), rather than saying it “behaves like replace.”

pkg/provenance/text_utils.go (1)

244-250: Consider built-in max (Go 1.21+).

If the project uses Go 1.21 or later, you can replace this with the built-in max function.

-// max returns the maximum of two integers.
-func max(a, b int) int {
-	if a > b {
-		return a
-	}
-	return b
-}

Then use max(a, b) directly at line 163.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c4d40ee and 5cfee16.

📒 Files selected for processing (10)
  • docs/prd/import-provenance.md (1 hunks)
  • pkg/merge/merge_with_provenance_test.go (1 hunks)
  • pkg/provenance/provenance_helpers_test.go (1 hunks)
  • pkg/provenance/text_utils.go (1 hunks)
  • pkg/provenance/text_utils_test.go (1 hunks)
  • pkg/provenance/tree_renderer.go (1 hunks)
  • pkg/provenance/yaml_parser.go (1 hunks)
  • pkg/provenance/yaml_parser_arrays_test.go (1 hunks)
  • pkg/provenance/yaml_parser_multiline_test.go (1 hunks)
  • website/docs/cli/commands/describe/describe-component.mdx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • website/docs/cli/commands/describe/describe-component.mdx
  • docs/prd/import-provenance.md
  • pkg/provenance/text_utils_test.go
  • pkg/provenance/provenance_helpers_test.go
🧰 Additional context used
📓 Path-based instructions (5)
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/provenance/text_utils.go
  • pkg/provenance/yaml_parser_multiline_test.go
  • pkg/provenance/yaml_parser.go
  • pkg/provenance/tree_renderer.go
  • pkg/merge/merge_with_provenance_test.go
  • pkg/provenance/yaml_parser_arrays_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All comments in Go code must end with periods; enforced by golangci-lint's godot.
Organize imports into three groups (stdlib, 3rd-party, Atmos) separated by blank lines; sort alphabetically within each group; maintain existing import aliases.
Add defer perf.Track() to all public functions and critical private functions, with a blank line after the call; use package-qualified names (e.g., "exec.ProcessComponent"); pass atmosConfig if available, else nil.
Error handling: wrap errors using static errors from errors/errors.go; prefer errors.Join for multiple errors; add context with fmt.Errorf("%w", ...); use errors.Is for checks; never compare error strings or return dynamic errors directly.
Always bind environment variables with viper.BindEnv; every env var must have an ATMOS_ alternative (e.g., viper.BindEnv("ATMOS_GITHUB_TOKEN", "GITHUB_TOKEN")).
Use structured logging for system/debug info and direct UI output to stderr; never use logging for UI elements; data/results intended for piping must go to stdout.
Most text UI must go to stderr (e.g., utils.PrintfMessageToTUI or fmt.Fprintf(os.Stderr,...)); only data/results go to stdout.
Ensure cross-platform compatibility: prefer SDKs over shelling out to binaries, use filepath/os utilities, and guard OS-specific logic with build constraints or runtime.GOOS when necessary.

Files:

  • pkg/provenance/text_utils.go
  • pkg/provenance/yaml_parser_multiline_test.go
  • pkg/provenance/yaml_parser.go
  • pkg/provenance/tree_renderer.go
  • pkg/merge/merge_with_provenance_test.go
  • pkg/provenance/yaml_parser_arrays_test.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Files:

  • pkg/provenance/text_utils.go
  • pkg/provenance/yaml_parser.go
  • pkg/provenance/tree_renderer.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Test quality: test behavior not implementation; avoid testing stubs or tautologies; use DI to avoid hard deps (os.Exit, CheckErrorPrintAndExit); remove always-skipped tests; table-driven tests must use real scenarios.
Always use t.Skipf with a clear reason instead of t.Skip; never call t.Skipf without a reason.
Co-locate test files alongside implementations using *_test.go naming.

Files:

  • pkg/provenance/yaml_parser_multiline_test.go
  • pkg/merge/merge_with_provenance_test.go
  • pkg/provenance/yaml_parser_arrays_test.go
pkg/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

Place unit tests under pkg/ as *_test.go files (co-located with implementation).

Files:

  • pkg/provenance/yaml_parser_multiline_test.go
  • pkg/merge/merge_with_provenance_test.go
  • pkg/provenance/yaml_parser_arrays_test.go
🧠 Learnings (2)
📚 Learning: 2025-10-06T02:10:05.491Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-06T02:10:05.491Z
Learning: Applies to **/*.go : All comments in Go code must end with periods; enforced by golangci-lint's godot.

Applied to files:

  • pkg/provenance/tree_renderer.go
📚 Learning: 2025-10-06T02:10:05.491Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-06T02:10:05.491Z
Learning: Applies to **/*.go : Add `defer perf.Track()` to all public functions and critical private functions, with a blank line after the call; use package-qualified names (e.g., "exec.ProcessComponent"); pass atmosConfig if available, else nil.

Applied to files:

  • pkg/provenance/tree_renderer.go
🧬 Code graph analysis (3)
pkg/provenance/yaml_parser.go (3)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/provenance/tree_renderer.go (1)
  • YAMLLineInfo (56-60)
pkg/utils/jsonpath.go (1)
  • AppendJSONPathIndex (50-56)
pkg/provenance/tree_renderer.go (7)
pkg/merge/merge_context.go (1)
  • MergeContext (16-36)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/merge/provenance_entry.go (6)
  • ProvenanceTypeComputed (23-23)
  • ProvenanceEntry (31-50)
  • ProvenanceTypeInline (17-17)
  • ProvenanceTypeOverride (20-20)
  • ProvenanceTypeImport (14-14)
  • ProvenanceTypeDefault (26-26)
pkg/ui/theme/colors.go (6)
  • ColorSelectedItem (22-22)
  • ColorCyan (12-12)
  • ColorGreen (11-11)
  • ColorOrange (18-18)
  • ColorDarkGray (15-15)
  • ColorRed (16-16)
pkg/logger/log.go (1)
  • Debug (24-26)
pkg/utils/yaml_utils.go (4)
  • ConvertToYAML (216-232)
  • WrapLongStrings (181-214)
  • DefaultYAMLIndent (29-29)
  • YAMLOptions (161-163)
pkg/utils/highlight_utils.go (1)
  • HighlightCodeWithConfig (82-126)
pkg/merge/merge_with_provenance_test.go (6)
pkg/schema/schema.go (3)
  • AtmosConfiguration (27-65)
  • Settings (684-688)
  • AtmosSettings (251-271)
pkg/merge/merge_context.go (2)
  • NewMergeContext (39-43)
  • MergeContext (16-36)
pkg/merge/merge_with_provenance.go (1)
  • MergeWithProvenance (21-52)
pkg/utils/yaml_position.go (1)
  • PositionMap (14-14)
pkg/merge/provenance_entry.go (2)
  • ProvenanceTypeInline (17-17)
  • ProvenanceTypeImport (14-14)
pkg/merge/merge.go (3)
  • ListMergeStrategyReplace (16-16)
  • ListMergeStrategyAppend (17-17)
  • ListMergeStrategyMerge (18-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: website-deploy-preview
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: Run pre-commit hooks
  • GitHub Check: Summary
🔇 Additional comments (13)
pkg/merge/merge_with_provenance_test.go (7)

13-37: LGTM!

The test correctly verifies that provenance tracking is skipped when disabled both in config and context.


39-82: LGTM!

Comprehensive test covering basic provenance tracking with proper verification of all provenance details.


84-121: LGTM!

Test correctly verifies provenance tracking for nested map structures.


123-159: LGTM!

Test properly verifies provenance tracking for array elements using index notation.


198-234: LGTM!

Test correctly verifies import depth tracking with parent context chain and proper provenance type assignment.


236-262: LGTM!

Test correctly verifies that provenance tracking works gracefully when position information is unavailable.


264-314: LGTM!

Well-structured table-driven test with comprehensive coverage of import depth calculation scenarios.

pkg/provenance/text_utils.go (6)

1-11: LGTM! Clean setup.

Package declaration and imports are properly structured. The unicode/utf8 import correctly addresses the rune-counting requirements flagged in previous reviews.


22-54: Nice fix on flush-at-limit.

The logic correctly flushes when reaching maxWidth before writing the next printable rune, addressing the previous overflow issue with whitespace-free lines. The ANSI sequence handling looks solid.


56-99: Solid rune-aware wrapping.

The switch from byte length to utf8.RuneCountInString at line 64 correctly fixes the multi-byte character width issues from earlier reviews. The fallback to hardWrapWithANSI handles edge cases cleanly.


101-131: ANSI-aware wrapping works as intended.

The implementation correctly keeps ANSI escape sequences with their styled text by counting only printable runes for width calculations. This addresses the previous issue where sequences were split from their payload.


133-190: Padding guard prevents panic.

The negative padding check at lines 152-154 correctly prevents the strings.Repeat panic when leftWidth is small, addressing the previous issue. The two-column layout logic is clean.


223-242: stripANSI SGR-only stripping is sufficient
Provenance rendering exclusively uses lipgloss-generated SGR color/bold codes, so handling only sequences ending in “m” covers all current use cases.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
pkg/merge/merge.go (1)

186-194: List-merge strategy not passed to provenance path.

The provenance-aware branch (line 190) calls MergeWithProvenance(atmosConfig, inputs, context, context.Positions) without passing the appendSlice or sliceDeepCopy options derived from ListMergeStrategy. This means provenance-aware merges may not honor the configured strategy (replace/append/merge) while the standard path does.

This duplicates the concern raised in the past review comment at lines 186-195. The issue remains: ensure MergeWithProvenance respects ListMergeStrategy by either accepting and applying these options or deriving them internally from atmosConfig.Settings.ListMergeStrategy.

pkg/merge/merge_with_provenance_test.go (1)

443-448: Still need an assertion for the count field.

Same gap as last round: the comment says the base count should be dropped, but the test never checks it. Please assert the actual behavior (or fix the comment if count must survive) so regressions can’t sneak in.

 		assert.Equal(t, "override", merged["name"], "Override value should win")
 		assert.Equal(t, "field", merged["extra"], "New field from override should be present")
-		// Note: "count" from base is NOT preserved with mergo's SliceDeepCopy - it replaces the element
+		// Note: "count" from base is NOT preserved with mergo's SliceDeepCopy - it replaces the element
+		_, hasCount := merged["count"]
+		assert.False(t, hasCount, "count should not be preserved when the element is replaced")
 
 		// Verify provenance was still tracked.
 		assert.True(t, ctx.HasProvenance("vars.items"), "Provenance should be tracked for vars.items")
🧹 Nitpick comments (7)
errors/errors.go (1)

39-39: LGTM! Clean consolidation.

The declaration is correct and the move to the top-level block makes sense.

As a minor organizational note: you might consider grouping this with other command-related errors (ErrNoCommandSpecified, ErrCommandNotFound) around lines 241-242 for better discoverability, though the current placement in the general section works fine.

pkg/utils/highlight_utils.go (1)

85-89: Unify terminal-detection logic across both highlighters.

  • Extract the stdout & stderr checks into a single helper (e.g. isTerminal()) and invoke it from both HighlightCode and HighlightCodeWithConfig.
  • Optionally cache the stderr check if highlighting is performance-sensitive.
  • Add a doc comment clarifying the intended TUI vs CLI behavior.
pkg/ui/theme/colors.go (2)

17-17: Update the comment to reflect actual usage.

The comment says "Available for future use," but evidence from the previous review indicates ColorYellow is already used in pkg/provenance/tree_renderer.go (lines 213, 304). Update the comment to describe its actual purpose or remove the "future use" clause if it's actively in use.

Additionally, the parenthetical readability concern is valid—consider documenting this in user-facing theme docs or providing an adaptive color alternative for better accessibility across terminal backgrounds.


17-18: Remove or document unused ColorYellow
ColorYellow in pkg/ui/theme/colors.go:17 has no references; delete it or annotate its reserved-for-future-use status.

internal/exec/describe_affected_test.go (1)

22-104: LGTM! Good test refactoring.

The createExpectedAffectedResults helper eliminates duplication and makes test expectations more maintainable. The parameterization for template-processed vs unprocessed results is clear and correct.

Minor observation: The parameter name templatesProcessed might be slightly confusing since true means templates were NOT processed (i.e., raw template strings remain). Consider a comment or rename for clarity:

// createExpectedAffectedResults creates the expected affected results for testing.
// When rawTemplates is true, returns results with unprocessed template strings ({{ ... }}).
// When rawTemplates is false, returns results with processed/resolved values.
func createExpectedAffectedResults(componentPath string, rawTemplates bool) []schema.Affected {
cmd/describe_component_test.go (2)

58-67: Check flag Set errors in tests.

PersistentFlags().Set returns an error; ignoring it can hide regressions when flags are renamed or removed. Please wrap each Set with require.NoError(t, ...) so the test fails fast if the flag lookup breaks.


97-104: Use t.TempDir for unique temp files.

Hard-coding filepath.Join(os.TempDir(), "test-provenance-output.yaml") can collide with parallel runs or leftovers from previous runs. Prefer tmp := t.TempDir(); file := filepath.Join(tmp, "output.yaml") (or os.CreateTemp) so each test instance owns its workspace and cleanup is automatic.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 96a7852 and 5cfee16.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (53)
  • cmd/describe_component.go (3 hunks)
  • cmd/describe_component_test.go (2 hunks)
  • docs/prd/import-provenance.md (1 hunks)
  • errors/errors.go (1 hunks)
  • go.mod (2 hunks)
  • internal/exec/describe_affected_test.go (3 hunks)
  • internal/exec/describe_component.go (8 hunks)
  • internal/exec/describe_component_provenance_test.go (1 hunks)
  • internal/exec/describe_component_test.go (2 hunks)
  • internal/exec/describe_stacks.go (1 hunks)
  • internal/exec/stack_processor_utils.go (13 hunks)
  • internal/tui/templates/templater.go (1 hunks)
  • internal/tui/utils/utils.go (1 hunks)
  • pkg/hooks/store_cmd.go (1 hunks)
  • pkg/merge/integration_test.go (1 hunks)
  • pkg/merge/merge.go (1 hunks)
  • pkg/merge/merge_context.go (5 hunks)
  • pkg/merge/merge_context_test.go (1 hunks)
  • pkg/merge/merge_with_provenance.go (1 hunks)
  • pkg/merge/merge_with_provenance_test.go (1 hunks)
  • pkg/merge/provenance_benchmark_test.go (1 hunks)
  • pkg/merge/provenance_entry.go (1 hunks)
  • pkg/merge/provenance_entry_test.go (1 hunks)
  • pkg/merge/provenance_storage.go (1 hunks)
  • pkg/merge/provenance_storage_test.go (1 hunks)
  • pkg/merge/provenance_tracker.go (1 hunks)
  • pkg/merge/provenance_tracker_test.go (1 hunks)
  • pkg/provenance/data_transform.go (1 hunks)
  • pkg/provenance/data_transform_test.go (1 hunks)
  • pkg/provenance/import_provenance_test.go (1 hunks)
  • pkg/provenance/provenance_helpers_test.go (1 hunks)
  • pkg/provenance/text_utils.go (1 hunks)
  • pkg/provenance/text_utils_test.go (1 hunks)
  • pkg/provenance/tree_renderer.go (1 hunks)
  • pkg/provenance/tree_renderer_test.go (1 hunks)
  • pkg/provenance/yaml_indent_test.go (1 hunks)
  • pkg/provenance/yaml_parser.go (1 hunks)
  • pkg/provenance/yaml_parser_arrays_test.go (1 hunks)
  • pkg/provenance/yaml_parser_multiline_test.go (1 hunks)
  • pkg/schema/schema.go (1 hunks)
  • pkg/ui/theme/colors.go (1 hunks)
  • pkg/utils/highlight_utils.go (2 hunks)
  • pkg/utils/jsonpath.go (1 hunks)
  • pkg/utils/jsonpath_test.go (1 hunks)
  • pkg/utils/yaml_include_by_extension.go (1 hunks)
  • pkg/utils/yaml_include_by_extension_regression_test.go (1 hunks)
  • pkg/utils/yaml_position.go (1 hunks)
  • pkg/utils/yaml_position_test.go (1 hunks)
  • pkg/utils/yaml_utils.go (3 hunks)
  • pkg/utils/yq_utils.go (1 hunks)
  • pkg/utils/yq_utils_test.go (1 hunks)
  • website/docs/cli/commands/describe/describe-component.mdx (2 hunks)
  • website/docs/cli/commands/describe/describe-stacks.mdx (1 hunks)
🧰 Additional context used
🧠 Learnings (14)
📚 Learning: 2025-10-06T02:10:05.491Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-06T02:10:05.491Z
Learning: Applies to **/*.go : All comments in Go code must end with periods; enforced by golangci-lint's godot.

Applied to files:

  • pkg/merge/merge_with_provenance.go
  • pkg/provenance/tree_renderer.go
📚 Learning: 2025-05-22T19:58:32.988Z
Learnt from: samtholiya
PR: cloudposse/atmos#1255
File: cmd/describe_affected.go:122-123
Timestamp: 2025-05-22T19:58:32.988Z
Learning: The "pager" flag is defined as a PersistentFlag at the describe command level in cmd/describe.go, making it available to all subcommands including describeAffectedCmd without needing to redeclare it.

Applied to files:

  • cmd/describe_component_test.go
📚 Learning: 2025-06-07T19:27:40.807Z
Learnt from: samtholiya
PR: cloudposse/atmos#1266
File: pkg/utils/highlight_utils.go:0-0
Timestamp: 2025-06-07T19:27:40.807Z
Learning: In pkg/utils/highlight_utils.go, the global variable `isTermPresent` that caches terminal detection at package initialization is an intentional design choice and should not be changed to per-call detection.

Applied to files:

  • pkg/utils/highlight_utils.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
PR: cloudposse/atmos#1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/utils/yaml_utils.go
📚 Learning: 2025-10-06T02:10:05.491Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-06T02:10:05.491Z
Learning: Applies to pkg/ui/theme/**/*.go : Use consistent Atmos theme colors from pkg/ui/theme/colors.go via theme.Styles/theme.Colors for UI elements.

Applied to files:

  • pkg/ui/theme/colors.go
📚 Learning: 2024-10-31T19:25:41.298Z
Learnt from: osterman
PR: cloudposse/atmos#727
File: internal/exec/terraform_clean.go:233-235
Timestamp: 2024-10-31T19:25:41.298Z
Learning: When specifying color values in functions like `confirmDeleteTerraformLocal` in `internal/exec/terraform_clean.go`, avoid hardcoding color values. Instead, use predefined color constants or allow customization through configuration settings to improve accessibility and user experience across different terminals and themes.

Applied to files:

  • pkg/ui/theme/colors.go
📚 Learning: 2025-09-23T02:30:42.362Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests

Applied to files:

  • pkg/merge/provenance_entry_test.go
  • pkg/utils/jsonpath_test.go
📚 Learning: 2025-10-06T02:10:05.491Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-06T02:10:05.491Z
Learning: Applies to **/*.go : Add `defer perf.Track()` to all public functions and critical private functions, with a blank line after the call; use package-qualified names (e.g., "exec.ProcessComponent"); pass atmosConfig if available, else nil.

Applied to files:

  • pkg/provenance/tree_renderer.go
  • internal/exec/stack_processor_utils.go
  • internal/exec/describe_component.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
PR: cloudposse/atmos#764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.

Applied to files:

  • internal/exec/describe_stacks.go
📚 Learning: 2025-10-06T02:10:05.491Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-06T02:10:05.491Z
Learning: Applies to pkg/**/*_test.go : Place unit tests under pkg/ as *_test.go files (co-located with implementation).

Applied to files:

  • pkg/utils/jsonpath_test.go
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
PR: cloudposse/atmos#795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-11-10T18:37:10.032Z
Learnt from: osterman
PR: cloudposse/atmos#768
File: internal/exec/vendor_component_utils.go:354-360
Timestamp: 2024-11-10T18:37:10.032Z
Learning: In the vendoring process, a TTY can exist without being interactive. If the process does not prompt the user, we should not require interactive mode to display the TUI. The `CheckTTYSupport` function should check TTY support on stdout rather than stdin.

Applied to files:

  • internal/exec/describe_component.go
📚 Learning: 2025-09-29T02:20:11.636Z
Learnt from: aknysh
PR: cloudposse/atmos#1540
File: internal/exec/validate_component.go:117-118
Timestamp: 2025-09-29T02:20:11.636Z
Learning: The ValidateComponent function in internal/exec/validate_component.go had its componentSection parameter type refined from `any` to `map[string]any` without adding new parameters. This is a type safety improvement, not a signature change requiring call site updates.

Applied to files:

  • internal/exec/describe_component.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
PR: cloudposse/atmos#1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.

Applied to files:

  • internal/exec/describe_component.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Acceptance Tests (windows-latest, windows)
  • GitHub Check: Acceptance Tests (macos-latest, macos)
  • GitHub Check: Acceptance Tests (ubuntu-latest, linux)
  • GitHub Check: Summary
🔇 Additional comments (59)
pkg/utils/highlight_utils.go (1)

12-16: LGTM! Clean migration to chroma v2.

The import updates are correct and consistent with the chroma v2 API.

internal/tui/utils/utils.go (1)

9-15: Confirm chroma v2 migration and review changelog for behavioral changes.
All chroma imports across the repository now use v2; ensure no API or output changes in v2 affect syntax highlighting.

pkg/utils/yq_utils.go (1)

14-14: LGTM! Import path standardization.

The switch to the canonical gopkg.in/yaml.v3 import with a local alias is correct and maintains consistency across the codebase.

pkg/utils/yaml_include_by_extension_regression_test.go (1)

9-9: LGTM! Consistent import path update.

The import change aligns with the standardization across the codebase.

internal/exec/describe_stacks.go (2)

68-68: LGTM! More specific performance tracking label.

The updated label exec.DescribeStacksExec.Execute provides better granularity for performance monitoring.


110-121: Verify removal of performance tracking.

The perf.Track defer call appears to have been removed from ExecuteDescribeStacks. This function is substantial (800+ lines) and processes stack manifests extensively. Removing performance tracking here reduces observability for this critical path.

Confirm whether the removal was intentional. If so, consider re-adding tracking to maintain visibility into performance characteristics:

 func ExecuteDescribeStacks(
 	atmosConfig *schema.AtmosConfiguration,
 	filterByStack string,
 	components []string,
 	componentTypes []string,
 	sections []string,
 	ignoreMissingFiles bool,
 	processTemplates bool,
 	processYamlFunctions bool,
 	includeEmptyStacks bool,
 	skip []string,
 ) (map[string]any, error) {
+	defer perf.Track(atmosConfig, "exec.ExecuteDescribeStacks")()
+
 	stacksMap, _, err := FindStacksMap(atmosConfig, ignoreMissingFiles)
pkg/utils/yaml_include_by_extension.go (1)

10-10: LGTM! Consistent import standardization.

The canonical import path aligns with the broader YAML library standardization effort.

internal/tui/templates/templater.go (1)

10-12: LGTM! Explicit dependency declarations.

Making these direct imports explicit improves clarity and aligns with Go best practices, especially since the file directly uses types from these packages.

pkg/utils/yq_utils_test.go (1)

7-7: LGTM! Test import alignment.

The import change maintains consistency with production code changes.

go.mod (2)

194-194: LGTM! Transitive dependency update.

The regexp2 patch bump from v1.11.0 to v1.11.5 is a transitive dependency of chroma with no known breaking changes.


15-15: Verify Chroma v2 upgrade compatibility. In pkg/utils/highlight_utils.go, review getLexer (line 129) and getFormatter (line 153)—exercise syntax highlighting across languages and output formats to confirm no breaking changes in lexers.Get, formatters.TTY256 or style defaults in v2.20.0.

internal/exec/describe_affected_test.go (2)

311-311: LGTM! Cleaner test expectations.

Using the helper function improves readability and maintainability.


333-333: LGTM! Consistent helper usage.

The helper provides consistent expected data across test scenarios.

pkg/provenance/text_utils.go (1)

1-250: LGTM!

The ANSI-aware text utilities look solid after the fixes from previous reviews. The rune-safe wrapping, ANSI sequence preservation, and panic prevention all work correctly now. The implementation handles the core use cases well.

pkg/provenance/text_utils_test.go (1)

1-340: Excellent test coverage!

The test suite thoroughly validates ANSI handling, wrapping behavior, and layout rendering. Good use of table-driven tests and edge case coverage.

pkg/merge/provenance_entry.go (1)

1-148: LGTM!

The provenance entry model is well-structured with proper deterministic hashing via json.Marshal. The 8-byte hash truncation is appropriate for configuration change detection.

pkg/merge/provenance_storage.go (1)

1-174: LGTM!

The provenance storage is well-implemented with proper thread-safety, defensive copies, and nil-safety. Good use of read/write locks and sorted output for consistency.

pkg/utils/yaml_utils.go (2)

165-214: Clean implementation of long string wrapping.

The LongString type and WrapLongStrings function handle YAML folded scalars nicely. The recursive walk creates new data structures (no side effects), and the logic correctly identifies long single-line strings.


317-353: Good integration of provenance tracking.

The new UnmarshalYAMLFromFileWithPositions function conditionally extracts position data based on atmosConfig.TrackProvenance, which keeps the overhead minimal when provenance is disabled.

website/docs/cli/commands/describe/describe-stacks.mdx (1)

93-95: Clear documentation note.

The provenance tracking note appropriately guides users to the component-level command for provenance details.

pkg/merge/merge_context_test.go (1)

281-583: Comprehensive provenance test coverage.

The provenance tests thoroughly validate enabling, recording, retrieval, cloning, and type inference. Good coverage of nil-safety and the shared storage semantics via WithFile.

cmd/describe_component.go (1)

64-80: Clean flag integration.

The provenance flag handling follows the established pattern and integrates cleanly with the existing command structure.

website/docs/cli/commands/describe/describe-component.mdx (2)

62-63: LGTM!

The example usage clearly demonstrates the --provenance flag and follows the established pattern for other command examples.


96-121: Excellent provenance documentation.

The flag documentation comprehensively covers all output formats (YAML TTY, YAML non-TTY, JSON) with clear explanations of symbols, depth indicators, and color coding. The distinction between TTY and non-TTY behavior is well-articulated, and the JSON structure is clearly defined.

pkg/schema/schema.go (1)

64-64: LGTM!

The TrackProvenance field is cleanly integrated into the AtmosConfiguration struct with proper tags for YAML/JSON/mapstructure serialization. The field name is clear and the optional nature (omitempty) is appropriate for a feature flag.

docs/prd/import-provenance.md (1)

1-601: Excellent PRD documentation.

This comprehensive PRD provides clear context for the import provenance tracking system, covering architecture, design decisions, implementation phases, and testing strategy. The document effectively explains the rationale for key decisions (inline YAML comments, ProvenanceTracker interface, data structure purity) and includes practical use cases. All previous review comments have been addressed.

pkg/utils/jsonpath_test.go (1)

1-477: Comprehensive test coverage for JSONPath utilities.

This test file provides excellent coverage for all JSONPath helper functions with clear table-driven tests. The inclusion of round-trip tests (lines 409-436) and parent-child relationship tests (lines 438-477) validates the correctness of bidirectional operations. Edge cases like empty strings, invalid formats, and array indices are well-covered.

pkg/provenance/yaml_parser_multiline_test.go (2)

10-71: Thorough multiline scalar indicator tests.

The test covers all valid YAML multiline scalar indicators (literal |, folded >, with chomping and indent indicators) plus comprehensive edge cases and invalid formats. The test cases are well-named and clearly document expected behavior.


74-131: Context test validates multiline scalar handling.

This test verifies that buildYAMLPathMap correctly handles multiline YAML scalars by identifying key lines and continuation lines. The note at line 124 documents a known limitation where lines starting with # inside multiline scalars are filtered as comments—an acceptable trade-off for the current implementation.

pkg/utils/yaml_position_test.go (1)

1-384: Comprehensive YAML position extraction tests.

This test file thoroughly validates YAML position extraction across a wide range of scenarios: simple maps, nested structures, arrays, arrays of maps, complex configurations, and edge cases (disabled extraction, nil nodes, empty structures). The inclusion of a real-world Atmos stack configuration test (lines 345-384) ensures practical applicability. The ordering assertions verify parent-child relationships, and all tests validate both line and column precision.

pkg/provenance/tree_renderer_test.go (3)

10-130: Comprehensive multiline YAML path mapping tests.

The table-driven tests cover all major YAML multiline scenarios: literal scalars (|), folded scalars (>), chomping indicators (-, +), and nested multiline values. The tests validate that buildYAMLPathMap correctly identifies key lines vs continuation lines, which is essential for accurate provenance rendering.


132-171: Path normalization tests cover key scenarios.

The tests validate that normalizeProvenancePath correctly strips components.terraform.* and terraform.* prefixes while handling edge cases like already-normalized paths and paths that reduce to empty strings. The test cases are clear and cover the expected usage patterns.


173-179: Default comment column test is reasonable.

The test validates that getCommentColumn returns a sensible default value in non-TTY environments (which includes test runs). The range check (40-200) ensures the column position is neither too small nor unreasonably large.

internal/exec/stack_processor_utils.go (7)

35-44: LGTM!

Clean per-stack provenance storage with proper mutex protection. The dual storage (per-stack + deprecated last-context) maintains backward compatibility while enabling the new per-stack workflow.


46-101: LGTM!

All public context management functions properly instrumented with perf.Track and use correct mutex patterns. Clean API surface for per-stack provenance storage.


147-153: LGTM!

Excellent fix - each goroutine now creates its own MergeContext, eliminating the data race. Clean per-goroutine provenance tracking.


213-217: LGTM!

Proper per-stack context storage with backward-compatible mirroring. The note about potential race on lastMergeContext is accurate and acceptable for the deprecated path.


278-309: LGTM!

Clean refactor that adds provenance support to single-file operations while maintaining backward compatibility. Context creation and storage are properly handled.


540-569: LGTM!

Import provenance recording correctly uses GetImportDepth() for consistent depth calculation. Clean key format and first-occurrence logic.


725-747: LGTM!

Metadata provenance recording also uses GetImportDepth() for consistent depth tracking. Good pattern matching with the import provenance logic.

internal/exec/describe_component.go (8)

80-120: LGTM!

Clean routing to provenance-enabled path when requested. Proper context retrieval, computed-field filtering, and backward-compatible fallback to standard execution.


133-140: LGTM!

Proper validation before provenance rendering - checks context availability and data type. Clean error message if validation fails.


221-248: LGTM!

Helper functions correctly use raw file writes (not YAML marshaling) for provenance output. Clean separation of file vs. stdout handling.


250-267: LGTM!

Safe type assertion with proper ok check prevents panics. Clean handling of both []any and []string cases with graceful skip of non-string entries.


269-362: LGTM!

Well-structured import provenance helpers with clear fallback logic. Clean separation between metadata lookups, YAML position enhancement, and all-paths search.


364-426: LGTM!

Clean component type detection with proper fallback chain (Terraform → Helmfile → Packer). Well-structured parameter types and processing helpers.


429-486: LGTM!

Comprehensive context-aware implementation with proper cleanup (ClearMergeContexts), type detection, per-stack context retrieval with fallback, and import provenance recording.


488-515: LGTM!

Clean filtering of computed fields - keeps only stack-defined fields (vars, settings, env, backend, metadata, overrides, providers, imports) for provenance display.

pkg/provenance/tree_renderer.go (11)

1-40: LGTM!

Clean package setup with well-organized constants and clear documentation. Good separation of rendering constants and string constants.


42-60: LGTM!

Clean type definitions with proper doc comments ending in periods. Types clearly represent provenance rendering concepts.


62-84: LGTM!

Clean tree rendering with proper null/disabled checks and clear separation of build and render phases.


86-135: LGTM!

Proper perf.Track instrumentation and clean file grouping logic. Takes first (most recent) entry and produces sorted results.


137-224: LGTM!

Clean tree rendering with box drawing characters, symbol mapping, and lipgloss styling. Good color coding by symbol type.


226-259: LGTM!

Clean side-by-side rendering with panic recovery, highlighting with fallback, and proper YAML conversion.


261-283: LGTM!

Clean provenance lookup with path normalization and first-match logic.


285-367: LGTM!

Clean provenance comment formatting with depth-based color coding and terminal-aware column calculation. Good lipgloss integration.


375-409: LGTM!

Proper perf.Track instrumentation and graceful highlight failure handling. Clean YAML preparation with import renaming, filtering, wrapping, and indentation.


411-498: LGTM!

Clean line rendering with ANSI stripping for length calculation, proper padding/wrapping, legend rendering, and smart skip logic for continuations and non-key lines.


500-545: LGTM!

Comprehensive inline provenance rendering with proper perf.Track, panic recovery, legend rendering, YAML preparation, and line-by-line processing.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
pkg/merge/merge_with_provenance_test.go (1)

191-191: Consider adding a clarifying comment.

Since positions only contains data for override.yaml (not the base), a brief comment explaining this would help future readers understand why provenance for base values isn't being tracked in this particular test.

 	ctx.EnableProvenance()
 
 	atmosConfig := &schema.AtmosConfiguration{
 		TrackProvenance: true,
 	}
 
+	// Note: positions only contains data for override.yaml, not base.
 	_, err := MergeWithProvenance(atmosConfig, []map[string]any{base, override}, ctx, positions)
pkg/provenance/yaml_parser_arrays_test.go (1)

132-147: Consider adding assertions to the debug test.

This test only logs the path map without verifying behavior. While debug output can be helpful during development, tests should assert expected outcomes.

Either add assertions like the other tests or convert this to a test helper function if the logging is genuinely useful for future debugging:

 func TestSimpleArrayDebug(t *testing.T) {
 	yaml := `vars:
   items:
     - name: widget
       color: blue`
 
 	lines := strings.Split(yaml, "\n")
 	pathMap := buildYAMLPathMap(lines)
 
-	t.Log("\n=== PATH MAP ===")
-	for i := 0; i < len(lines); i++ {
-		if info, ok := pathMap[i]; ok {
-			t.Logf("Line %d: %q -> Path: %q", i, strings.TrimSpace(lines[i]), info.Path)
-		}
-	}
+	// Verify array element paths are indexed
+	if info, ok := pathMap[2]; ok {
+		assert.Equal(t, "vars.items[0].name", info.Path)
+		assert.True(t, info.IsKeyLine)
+	} else {
+		t.Fatal("Line 2 not found in path map")
+	}
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5cfee16 and d7924c7.

📒 Files selected for processing (3)
  • pkg/merge/merge_with_provenance_test.go (1 hunks)
  • pkg/provenance/yaml_parser.go (1 hunks)
  • pkg/provenance/yaml_parser_arrays_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/provenance/yaml_parser_arrays_test.go
  • pkg/provenance/yaml_parser.go
  • pkg/merge/merge_with_provenance_test.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Test quality: test behavior not implementation; avoid testing stubs or tautologies; use DI to avoid hard deps (os.Exit, CheckErrorPrintAndExit); remove always-skipped tests; table-driven tests must use real scenarios.
Always use t.Skipf with a clear reason instead of t.Skip; never call t.Skipf without a reason.
Co-locate test files alongside implementations using *_test.go naming.

Files:

  • pkg/provenance/yaml_parser_arrays_test.go
  • pkg/merge/merge_with_provenance_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All comments in Go code must end with periods; enforced by golangci-lint's godot.
Organize imports into three groups (stdlib, 3rd-party, Atmos) separated by blank lines; sort alphabetically within each group; maintain existing import aliases.
Add defer perf.Track() to all public functions and critical private functions, with a blank line after the call; use package-qualified names (e.g., "exec.ProcessComponent"); pass atmosConfig if available, else nil.
Error handling: wrap errors using static errors from errors/errors.go; prefer errors.Join for multiple errors; add context with fmt.Errorf("%w", ...); use errors.Is for checks; never compare error strings or return dynamic errors directly.
Always bind environment variables with viper.BindEnv; every env var must have an ATMOS_ alternative (e.g., viper.BindEnv("ATMOS_GITHUB_TOKEN", "GITHUB_TOKEN")).
Use structured logging for system/debug info and direct UI output to stderr; never use logging for UI elements; data/results intended for piping must go to stdout.
Most text UI must go to stderr (e.g., utils.PrintfMessageToTUI or fmt.Fprintf(os.Stderr,...)); only data/results go to stdout.
Ensure cross-platform compatibility: prefer SDKs over shelling out to binaries, use filepath/os utilities, and guard OS-specific logic with build constraints or runtime.GOOS when necessary.

Files:

  • pkg/provenance/yaml_parser_arrays_test.go
  • pkg/provenance/yaml_parser.go
  • pkg/merge/merge_with_provenance_test.go
pkg/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

Place unit tests under pkg/ as *_test.go files (co-located with implementation).

Files:

  • pkg/provenance/yaml_parser_arrays_test.go
  • pkg/merge/merge_with_provenance_test.go
**/!(*_test).go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Document all exported functions, types, and methods with Go doc comments

Files:

  • pkg/provenance/yaml_parser.go
🧬 Code graph analysis (2)
pkg/provenance/yaml_parser.go (3)
pkg/perf/perf.go (1)
  • Track (58-86)
pkg/provenance/tree_renderer.go (1)
  • YAMLLineInfo (56-60)
pkg/utils/jsonpath.go (1)
  • AppendJSONPathIndex (50-56)
pkg/merge/merge_with_provenance_test.go (6)
pkg/schema/schema.go (3)
  • AtmosConfiguration (27-65)
  • Settings (684-688)
  • AtmosSettings (251-271)
pkg/merge/merge_context.go (2)
  • NewMergeContext (39-43)
  • MergeContext (16-36)
pkg/merge/merge_with_provenance.go (1)
  • MergeWithProvenance (21-52)
pkg/utils/yaml_position.go (1)
  • PositionMap (14-14)
pkg/merge/provenance_entry.go (2)
  • ProvenanceTypeInline (17-17)
  • ProvenanceTypeImport (14-14)
pkg/merge/merge.go (3)
  • ListMergeStrategyReplace (16-16)
  • ListMergeStrategyAppend (17-17)
  • ListMergeStrategyMerge (18-18)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Analyze (go)
  • GitHub Check: Lint (golangci)
  • GitHub Check: website-deploy-preview
  • GitHub Check: Summary
🔇 Additional comments (20)
pkg/merge/merge_with_provenance_test.go (3)

447-448: Past review comment addressed.

The comment and assertion for the count field behavior have been updated correctly. The comment now accurately states that count IS preserved with mergo's SliceDeepCopy, and the assertion on line 448 verifies this behavior.


13-453: Comprehensive test coverage.

The test suite thoroughly covers provenance tracking scenarios including disabled provenance, simple/nested structures, arrays, multiple inputs, import depth, missing positions, and list merge strategies. The use of table-driven tests for TestGetImportDepth and subtests in TestMergeWithProvenance_HonorsListMergeStrategy follows Go best practices.


354-359: <!-- [scratchpad]
[task review_merge_with_provenance_test.inspection_1/1]
[observations]

  • The test file under review is pkg/merge/merge_with_provenance_test.go.
  • Relevant snippet shows two test cases:
    1. Before line 354: expectedTags: []any{"base-tag-1", "base-tag-2", "override-tag-1"}.
    2. Test at lines 354-359: expectedTags: []any{"base-tag-1", "base-tag-2"}.
  • Merge implementation uses mergo.WithSliceDeepCopy for ListMergeStrategyMerge, which makes slices replace behavior (src overrides dst).
    [analysis]
  • If override map provides a tags slice, merge strategy should replace base tags with override tags.
  • The first test case likely has override tags; the second test case's override map might omit tags, leading to base tags preserved.
    [pending]
  • Confirm whether the override map in the second test case omits the tags field.
    [actions]
  • Print the test case definitions, focusing on the maps for base and override entries in the "merge strategy - scalars behave like replace" scenario.
    [/scratchpad]
pkg/provenance/yaml_parser.go (10)

1-13: LGTM!

Package declaration, imports, and constants are properly structured. Imports follow the three-group convention (stdlib → third-party → Atmos), and the YAML array prefix constant is clearly defined.


15-36: Normalization logic is sound.

The function correctly strips common component prefixes while preserving the essential path structure. Performance tracking is properly applied with nil atmosConfig.


38-63: Multiline indicator detection is comprehensive.

Correctly handles literal (|) and folded (>) styles with optional chomping (+/-) and indent indicators (0-9). Based on learnings from past reviews, this now covers all valid YAML multiline scalar indicators.


65-85: Helper functions are clean and focused.

extractYAMLKey properly strips array prefixes and colons. buildYAMLPath correctly joins path components with the separator. Both handle edge cases appropriately.


87-102: Array index tracking is correct.

The function initializes and increments indices properly, returning both the current index and the updated stack for the next element.


104-116: Stack unwinding logic handles root-level edge cases.

Line 111's condition (indent > 0 || len(pathStack) > 0) correctly preserves the root counter while popping nested scopes, addressing the regression mentioned in past reviews.


118-143: Array item handling supports both root and nested contexts.

Lines 123-125 correctly handle root-level sequences with utils.AppendJSONPathIndex("", arrayIndex), while lines 129-132 build full prefixes for nested arrays. This addresses the path prefix issue from past reviews.


173-242: Root-level array-of-maps indexing is correct.

buildRootArrayElementPath (lines 173-194) properly constructs [i].key paths, and buildArrayElementPath (lines 196-242) delegates to it when pathStack is empty. This fixes the root-level indexing issue mentioned in past reviews.


244-303: Key line processing handles all array scenarios.

Lines 253-257 delegate to buildArrayElementPath for array elements regardless of nesting level, removing the len(pathStack) > 0 guard mentioned in past reviews. Lines 289-292 correctly track indent for root-level array elements.


383-400: Main entry point is well-structured.

Performance tracking is correctly applied. The line-by-line loop with persistent state cleanly models YAML structure. The implementation addresses all array indexing, root-level, and multiline issues flagged in previous reviews.

pkg/provenance/yaml_parser_arrays_test.go (7)

10-54: Solid test for array-of-maps indexing.

Validates that - name: widget produces vars.items[0].name instead of the incorrect vars.items.name. Clear assertions and error messages.


56-97: Nested array indexing is thoroughly tested.

Confirms double-indexed paths like config.servers[0].ports[0].port. Good coverage of the nesting scenarios.


99-130: Arrays with nested objects are validated.

Tests that nested object fields maintain the correct array index through multiple levels. Well-structured.


149-191: Root-level scalar arrays are properly tested.

Validates that - item1 produces [0] rather than dropping the index. The debug logging is helpful context.


193-242: Root-level array-of-maps coverage is thorough.

Confirms that - key: value1 produces [0].key at the document root. Clear assertions on both the leading and nested keys.


244-290: Regression test for nested scalar arrays is valuable.

Lines 245-246 explain this tests the bug where handleArrayItemLine only used the last stack element. Verifies the full prefix is now included.


292-364: Regression test for root array counters is critical.

Lines 293-294 document the bug where arrayIndexStack wasn't popped correctly at root level, causing siblings to collapse onto [0]. This test ensures indices advance correctly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
pkg/utils/jsonpath_test.go (4)

122-161: Consider testing negative indices.

The function accepts an int parameter, so negative indices are technically possible. Consider adding a test case to document expected behavior (e.g., whether AppendJSONPathIndex("items", -1) produces "items[-1]" or is considered invalid).

Example test case:

+		{
+			name:     "negative index",
+			basePath: "items",
+			index:    -1,
+			expected: "items[-1]",
+		},

163-217: Consider testing malformed bracket handling.

The implementation in pkg/utils/jsonpath.go (lines 78-120) has explicit handling for malformed paths with unclosed brackets. Adding a test case would document this behavior and prevent regressions.

Example test case:

+		{
+			name:     "malformed path - unclosed bracket",
+			path:     "vars[0",
+			expected: []string{"vars[0"},
+		},

219-279: Consider testing negative indices.

Similar to TestAppendJSONPathIndex, adding a test case for negative indices would document expected behavior (e.g., whether "[-1]" is considered a valid index).

Example test case:

+		{
+			name:          "negative index",
+			component:     "[-1]",
+			expectedIndex: -1,
+			expectedOk:    true,
+		},

281-315: Consider testing negative indices.

Consistent with the prior functions, adding a negative index test case would complete the edge case coverage.

Example test case:

+		{
+			name:      "negative index",
+			component: "[-1]",
+			expected:  true,
+		},
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d7924c7 and 9753e52.

📒 Files selected for processing (3)
  • pkg/merge/merge_with_provenance.go (1 hunks)
  • pkg/utils/jsonpath.go (1 hunks)
  • pkg/utils/jsonpath_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/merge/merge_with_provenance.go
  • pkg/utils/jsonpath.go
🧰 Additional context used
📓 Path-based instructions (4)
pkg/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

Place business logic in pkg rather than in cmd

Files:

  • pkg/utils/jsonpath_test.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests
Test both happy paths and error conditions
Use table-driven tests for multiple scenarios

**/*_test.go: Test quality: test behavior not implementation; avoid testing stubs or tautologies; use DI to avoid hard deps (os.Exit, CheckErrorPrintAndExit); remove always-skipped tests; table-driven tests must use real scenarios.
Always use t.Skipf with a clear reason instead of t.Skip; never call t.Skipf without a reason.
Co-locate test files alongside implementations using *_test.go naming.

Files:

  • pkg/utils/jsonpath_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: All code must pass golangci-lint checks
Follow Go error handling idioms and use meaningful error messages
Wrap errors with context using fmt.Errorf("context: %w", err)
Consider custom error types for domain-specific errors
Follow standard Go coding style; run gofmt and goimports
Use snake_case for environment variables
Document complex logic with inline comments

**/*.go: All comments in Go code must end with periods; enforced by golangci-lint's godot.
Organize imports into three groups (stdlib, 3rd-party, Atmos) separated by blank lines; sort alphabetically within each group; maintain existing import aliases.
Add defer perf.Track() to all public functions and critical private functions, with a blank line after the call; use package-qualified names (e.g., "exec.ProcessComponent"); pass atmosConfig if available, else nil.
Error handling: wrap errors using static errors from errors/errors.go; prefer errors.Join for multiple errors; add context with fmt.Errorf("%w", ...); use errors.Is for checks; never compare error strings or return dynamic errors directly.
Always bind environment variables with viper.BindEnv; every env var must have an ATMOS_ alternative (e.g., viper.BindEnv("ATMOS_GITHUB_TOKEN", "GITHUB_TOKEN")).
Use structured logging for system/debug info and direct UI output to stderr; never use logging for UI elements; data/results intended for piping must go to stdout.
Most text UI must go to stderr (e.g., utils.PrintfMessageToTUI or fmt.Fprintf(os.Stderr,...)); only data/results go to stdout.
Ensure cross-platform compatibility: prefer SDKs over shelling out to binaries, use filepath/os utilities, and guard OS-specific logic with build constraints or runtime.GOOS when necessary.

Files:

  • pkg/utils/jsonpath_test.go
pkg/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

Place unit tests under pkg/ as *_test.go files (co-located with implementation).

Files:

  • pkg/utils/jsonpath_test.go
🧠 Learnings (3)
📚 Learning: 2025-09-23T02:30:42.362Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to **/*_test.go : Every new feature must include comprehensive unit tests

Applied to files:

  • pkg/utils/jsonpath_test.go
📚 Learning: 2025-10-06T02:10:05.491Z
Learnt from: CR
PR: cloudposse/atmos#0
File: CLAUDE.md:0-0
Timestamp: 2025-10-06T02:10:05.491Z
Learning: Applies to pkg/**/*_test.go : Place unit tests under pkg/ as *_test.go files (co-located with implementation).

Applied to files:

  • pkg/utils/jsonpath_test.go
📚 Learning: 2025-09-23T02:30:42.362Z
Learnt from: CR
PR: cloudposse/atmos#0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-09-23T02:30:42.362Z
Learning: Applies to **/*_test.go : Use table-driven tests for multiple scenarios

Applied to files:

  • pkg/utils/jsonpath_test.go
🧬 Code graph analysis (1)
pkg/utils/jsonpath_test.go (1)
pkg/utils/jsonpath.go (8)
  • BuildJSONPath (15-43)
  • AppendJSONPathKey (50-58)
  • AppendJSONPathIndex (65-71)
  • SplitJSONPath (79-121)
  • ParseJSONPathIndex (129-141)
  • IsJSONPathIndex (148-151)
  • GetJSONPathParent (159-180)
  • GetJSONPathLeaf (188-199)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Build (windows-latest, windows)
  • GitHub Check: Build (macos-latest, macos)
  • GitHub Check: Build (ubuntu-latest, linux)
  • GitHub Check: website-deploy-preview
  • GitHub Check: Run pre-commit hooks
  • GitHub Check: Lint (golangci)
  • GitHub Check: Analyze (go)
  • GitHub Check: Summary
🔇 Additional comments (7)
pkg/utils/jsonpath_test.go (7)

9-73: Comprehensive coverage for BuildJSONPath.

Excellent table-driven test covering empty components, single/nested paths, array indices, and mixed constructs. Edge cases like filtering empty components are well-tested.


75-120: Solid coverage for AppendJSONPathKey.

Tests handle empty paths, empty keys, and nested combinations well.


317-371: Thorough coverage for GetJSONPathParent.

Tests handle empty paths, root levels, nested structures, and array indices well. The edge cases are well-represented.


373-427: Excellent coverage for GetJSONPathLeaf.

Tests handle all major path structures including empty paths, single components, nested paths, and array indices.


429-472: Solid round-trip verification.

Testing that BuildJSONPath and SplitJSONPath are inverse operations is a smart approach to catching inconsistencies.


474-513: Good parent-child relationship verification.

Reconstructing the original path from parent and leaf components validates the consistency of GetJSONPathParent and GetJSONPathLeaf. The switch-based reconstruction logic correctly handles root paths, array indices, and regular keys.


430-430: Add period to comment.

Comments must end with periods per coding guidelines (godot rule).

Apply this diff:

-	// Test that building and splitting are inverse operations.
+	// Test that building and splitting are inverse operations.

Wait, the comment already has a period. Let me re-check... Yes, line 430 has // Test that building and splitting are inverse operations. which ends with a period. This is correct. I was mistaken.

@aknysh aknysh merged commit 8ccdd85 into main Oct 7, 2025
53 checks passed
@aknysh aknysh deleted the osterman/component-provenance branch October 7, 2025 00:00
osterman added a commit that referenced this pull request Oct 7, 2025
* feat: add --show-provenance flag to describe component and describe stacks

Add provenance tracking display that shows the source file and line number
for each configuration value in component and stack descriptions.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* docs: revert broken provenance implementation, add comprehensive PRD

- Reverted incomplete provenance implementation from pkg/ui/provenance/
- Removed --show-provenance flags from describe component and describe stacks commands
- Created comprehensive PRD for proper line-level provenance system at docs/prd/line-level-provenance.md

The initial provenance implementation had fundamental limitations:
- Only tracked top-level section keys (vars.*, settings.*), not nested values
- Two-column rendering was broken and couldn't align with complex YAML structures
- No line number tracking, only file paths
- Not reusable across different Atmos config types (stacks, atmos.yaml, vendor, workflows)
- Output polluted with 750+ lines of raw sources data
- Tests didn't catch critical bugs

- PRD: docs/prd/line-level-provenance.md
- Extends existing MergeContext system (pkg/merge/merge_context.go)
- Uses gopkg.in/yaml.v3 Node API for line tracking
- Estimated 3-4 weeks for proper implementation
- Backward compatible deprecation of current sources system

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* docs: rename PRD from line-level-provenance to import-provenance

Renamed PRD to better reflect that we're tracking import/inheritance chains
rather than just line-level granularity. 'Import provenance' more accurately
describes tracking where values come from through the import system.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* feat: complete provenance tracking implementation for nested imports

- Implement MergeWithProvenance function to track provenance during YAML merging
- Add provenance storage and entry management with thread-safe operations
- Create tree renderer for inline provenance visualization with depth indicators
- Add YAML position extraction utilities for accurate line/column tracking
- Fix nested import provenance tracking in stack processor
- Record provenance metadata using merge context's current file
- Handle []any type for imports array in describe component output
- Add comprehensive test suite for provenance tracking functionality
- Support JSONPath addressing for nested configuration values
- Add benchmarks for provenance operations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* feat: improve provenance display with line wrapping and updated legend

- Update provenance legend: change "Defined at this level" to "Defined in parent stack"
- Add LongString type that encodes as YAML folded scalars (>-) for long strings
- Add WrapLongStrings function to automatically wrap long strings in YAML output
- Integrate line wrapping in provenance renderer to prevent horizontal scrolling
- Long values like atmos_component_description now wrap properly with provenance comments aligned

This improves readability of provenance output by ensuring long string values are wrapped
using proper YAML folded scalar syntax, keeping provenance comments aligned at the comment
column and preventing the need for horizontal scrolling.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* fix: address CodeRabbit review feedback for provenance tracking

- Fix file output with --provenance flag by writing raw YAML to file
- Add perf.Track instrumentation to merge context helper functions
- Replace manual depth calculations with GetImportDepth() method
- Fix goroutine data race by using per-goroutine MergeContext
- Fix linting issues (godot comment capitalization, gosec file permissions)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* feat: add ProvenanceTracker interface and describe stacks provenance

- Create generic ProvenanceTracker interface for extensibility
- Add --provenance flag to describe stacks command
- Update MergeContext to document ProvenanceTracker implementation
- Add comprehensive unit tests for interface with mock implementation
- Update PRD to reflect actual implementation status and design decisions
- Document display format rationale (valid YAML output)
- Document symbol and color scheme with Unicode codes
- Document backward compatibility with sources system

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

* fix: resolve yaml package type conflicts and address code review

- Add explicit yaml alias to gopkg.in/yaml.v3 imports to prevent type conflicts with go.yaml.in/yaml/v3 used by yqlib dependency
- Add missing perf.Track instrumentation to public functions in describe_component.go per coding guidelines
- Stabilize provenance value hashing by using json.Marshal for deterministic serialization instead of fmt.Sprintf

Fixes the CI build failure caused by YAML package type mismatch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* refactor: reduce cognitive complexity in provenance code

* fix: resolve all golangci-lint errors and warnings

- Extract constants for magic numbers and string literals
- Refactor all functions with >5 params to use config structs
- Fix getSymbolColor() to return different colors per symbol
- Split tree_renderer.go into multiple files (under 500 lines)
- Pass heavy params by pointer to avoid memory copying
- Extract helper functions to reduce cyclomatic complexity
- Fix all comment formatting (godot linter)
- Fix nilerr issues
- Fix nestif complexity in test by inverting conditions

All golangci-lint issues resolved for PR #1584

* fix: resolve provenance tracking bug and linting issues

- Fixed bug where __import__: and __import_meta__: provenance entries weren't being recorded for direct imports
- Resolved race condition in parallel stack processing that caused wrong merge contexts to be stored
- Added per-stack merge context storage to replace single global variable
- Fixed comment formatting to end with periods (godot linter)
- Resolved code duplication in describe_affected_test.go
- Added "imports" to allowed fields in test

- Provenance tracking is critical for showing users where configuration values come from
- The bug prevented proper tracking of imports defined directly in stack files
- Race conditions in parallel processing caused provenance to be attributed to wrong stack files
- Pre-commit hooks enforce code quality standards

1. Added merge context initialization in ProcessYAMLConfigFileWithContext when nil
2. Created mergeContexts map to store contexts per stack file instead of single global
3. Added SetMergeContextForStack() and GetMergeContextForStack() functions
4. Updated ProcessYAMLConfigFiles to store each stack's context separately
5. Modified ExecuteDescribeComponentWithContext to retrieve stack-specific context
6. Maintained backward compatibility by keeping deprecated functions
7. Fixed all godot linter warnings in cmd files

- TestDescribeComponent_DirectImportProvenance passes
- TestDescribeComponent_NestedImportProvenance passes
- TestDescribeComponentWithProvenance passes
- All describe component tests pass
- All linting checks pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: address CodeRabbit review comments

- **pkg/provenance/data_transform.go**: Fix nil context handling to preserve sections when provenance tracking is disabled
  - Initialize `hasProvenance := ctx == nil` to keep all keys when no provenance tracking
  - Prevents data loss when provenance is disabled

- **internal/exec/describe_component.go**: Fix TTY detection
  - Check `os.Stderr.Fd()` instead of `os.Stdout.Fd()` (correct stream)
  - Require both empty file and TTY to prevent spam to pipes/redirects

- **internal/exec/describe_component.go**: Add safe type assertion for imports
  - Use safe `if impStr, ok := imp.(string)` instead of panic-prone `imp.(string)`
  - Skip non-string values gracefully

- **pkg/provenance/text_utils.go**: Fix rune-safe text wrapping
  - Convert to `[]rune` before slicing to preserve multi-byte UTF-8 characters
  - Prevents corruption of ANSI sequences and Unicode text

- **pkg/provenance/tree_renderer.go**: Handle highlight failures gracefully
  - Fall back to plain YAML on highlight error instead of propagating error
  - Ensures users always see YAML output

- **docs/prd/import-provenance.md**: Add language identifiers to fenced code blocks
  - Change ` ``` ` to ` ```text ` for legend and architecture diagram
  - Fixes markdownlint warnings

All fixes verified with:
- Build: ✅ Passes
- Linting: ✅ 0 issues
- Tests: ✅ All pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* refactor: remove incomplete RenderInline() and consolidate to production implementation

- **Removed `RenderInline()` function** - Incomplete placeholder that only returned plain YAML
- **Updated tests** to use `RenderInlineProvenanceWithStackFile()` production implementation
- **Renamed files** for clarity:
  - `inline.go` → `provenance_helpers.go` (now only contains helper utilities)
  - `inline_test.go` → `provenance_helpers_test.go`
- **Kept `FormatProvenanceComment()`** - Useful helper for formatting provenance entries

CodeRabbit correctly identified that `RenderInline()` was incomplete (just returned YAML without provenance comments).

The PR already has a complete implementation in `RenderInlineProvenanceWithStackFile()` that:
- Adds provenance legend
- Parses YAML structure and builds path mapping
- Looks up provenance for each key
- Adds inline comments with file:line:column
- Used in production code (describe_component.go:135)

`RenderInline()` was only used in 2 unit tests and created confusion. Consolidating to a single implementation eliminates duplication and makes the codebase clearer.

- ✅ Build passes
- ✅ All tests pass (updated to use production function)
- ✅ Linting passes (0 issues)
- ✅ Single source of truth for inline provenance rendering

Addresses CodeRabbit review: #1584 (comment)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* perf: add performance tracking to FormatProvenanceComment

- Added `perf` import to `pkg/provenance/provenance_helpers.go`
- Added `defer perf.Track(nil, "provenance.FormatProvenanceComment")()` to track performance

All exported functions should have performance tracking for observability and profiling. This was missing from `FormatProvenanceComment()`.

- ✅ Build passes
- ✅ Tests pass
- ✅ Linting passes (0 issues)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: remove unnecessary perf tracking from unused test helper

- Removed `perf.Track()` call from `FormatProvenanceComment()`
- Removed unused `perf` import

`FormatProvenanceComment()` is only used in test code, not in production. Adding performance tracking to a test-only helper function provides no value and was causing CI failures on macOS and Windows platforms.

- Commit `2374f64de` added perf tracking and caused CI failures
- Linux: ✅ PASS
- macOS: ❌ FAIL
- Windows: ❌ FAIL

The function is unused in production code - only called in its own test. Performance tracking on an unused helper is unnecessary and introduced platform-specific failures.

- ✅ Build passes
- ✅ Tests pass locally
- ✅ Linting passes (0 issues)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* refactor: move formatProvenanceComment to test file

- Moved `FormatProvenanceComment()` from `provenance_helpers.go` (production code) to `provenance_helpers_test.go` (test code)
- Made function unexported (`formatProvenanceComment`) since it's test-only
- Deleted `provenance_helpers.go` as it's now empty

The function was only used in tests, not in production code. Having an exported function in production files that's only used in tests is misleading and was the reason CodeRabbit flagged it as an incomplete implementation.

**Original Context:**
- `FormatProvenanceComment()` was originally part of the incomplete `RenderInline()` implementation
- When we removed `RenderInline()` (commit 99f4bb9), we kept this helper thinking it might be useful
- But it's never actually used in production - only in its own test

**Proper Organization:**
- Test-only helpers belong in `_test.go` files
- Should be unexported (lowercase) to indicate internal test usage
- Keeps production code clean and focused

- ✅ Build passes
- ✅ All tests pass
- ✅ Linting passes (0 issues)
- ✅ No production code affected

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: ensure deterministic provenance tracking by sorting map keys

Provenance tracking was non-deterministic due to Go's random map iteration order.
This caused test failures on macOS CI where `TestDescribeComponentWithProvenance`
expected to find specific paths like `vars.enabled` or `vars.name`, but map iteration
could skip them depending on iteration order.

Changes:
- Sort map keys before iterating in `recordMapProvenance()`
- Ensures consistent provenance path recording across all platforms
- Fixes flaky test failures on macOS CI

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: address CodeRabbit review comments on provenance tracking

CodeRabbit identified three issues with provenance implementation and tests:

1. **ValueHash not populated**: ProvenanceEntry.ValueHash field was empty
   - Added `value` parameter to provenanceEntryParams
   - Updated recordProvenanceEntry to compute and set ValueHash using hashValue()
   - Pass actual values through all recordProvenanceEntry calls
   - Changed params to pointer to satisfy gocritic hugeParam linter

2. **Missing negative assertions**: Test didn't verify provenance absence
   - Added assertions to ensure no provenance comments when ctx is nil
   - Test now checks for absence of "# from:" and "# Provenance Legend:"

3. **Weak provenance format assertions**: Test only checked for presence
   - Added exact format checks for provenance comments ("# ● [0] config.yaml:10")
   - Added legend symbol verification (●, ○, ∴)
   - Fixed bug where legend was always shown even when ctx is nil

These changes ensure provenance entries have complete metadata for change
detection and that tests properly verify both positive and negative cases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: improve provenance display with parent stack header and depth 1 symbol

Changes the provenance rendering to be more intuitive:

1. **Added parent stack header**: Shows which stack file is being described
   - Displays "# Stack: {filename}" before the YAML output
   - Helps users understand the context

2. **Fixed symbol logic**: Changed from depth 0 to depth 1 for parent stack
   - ● [1] now shows values defined in the parent stack
   - ○ [2+] shows values inherited from imports
   - Depth 0 never occurred in practice (parent stack is always depth 1)

3. **Updated legend text**: Reflects new depth numbering
   - "● [1] Defined in parent stack"
   - "○ [N] Inherited/imported (N=2+ levels deep)"

4. **Adjusted color coding**: Makes depths 1-2 green
   - Depth 1-2: green (parent + first import)
   - Depth 3: yellow (getting far)
   - Depth 4+: red (very far)

5. **Updated all tests**: Changed test expectations from depth 0 to depth 1

6. **Refactored legend rendering**: Extracted into helper function to reduce cyclomatic complexity

This makes provenance output more intuitive and useful for understanding
where configuration values come from.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* test: add comprehensive provenance output validation tests

Add tests to validate complete provenance rendering output:
- TestProvenanceOutputFormat: validates legend, stack header, symbols, and depth formatting for all depth levels
- TestProvenanceComputedType: validates computed values show ∴ symbol regardless of depth

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: respect indent configuration when rendering YAML with provenance

When rendering YAML with provenance comments, now respects the indent
configuration from atmosConfig.Settings.Terminal.TabWidth instead of
always using the default indent of 2. This ensures folded YAML scalars
(like atmos_component_description with >-) are indented correctly
according to the user's configuration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* test: add tests to validate YAML indent configuration for folded scalars

Add comprehensive tests to verify that YAML folded scalar indentation
respects the tab_width configuration:
- TestYAMLIndentRespected: Validates indent=2 (default) produces 6 spaces
- TestYAMLIndentWithIndent4: Validates indent=4 produces 12 spaces

These tests ensure that the fix in tree_renderer.go correctly respects
the TabWidth configuration when rendering YAML with provenance.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: disable syntax highlighting for provenance to fix folded scalar indentation

The Chroma syntax highlighter was adding extra indentation (6 spaces) to
YAML folded scalar continuation lines, causing them to display with 12
spaces instead of the correct 6 spaces.

Root cause: When highlighting YAML with folded scalars (>-), the Chroma
lexer/formatter adds duplicate indentation to continuation lines:
- Original: "      Vpc-Flow-Logs-Bucket..."  (6 spaces)
- After highlighting: "      \x1b[0m      Vpc-Flow..." (6 + 6 = 12 spaces)

Solution: Disable syntax highlighting for provenance output. The YAML
structure is already clear with provenance comments, and this avoids
the indentation duplication issue.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: preserve syntax highlighting while fixing folded scalar indentation

The Chroma syntax highlighter was duplicating indentation for YAML folded
scalar continuation lines by inserting ANSI color codes within whitespace.
This resulted in visual duplication (e.g., 6 spaces + color codes + 6 more spaces).

Added post-processing that:
- Compares original and highlighted YAML line-by-line
- Counts leading spaces in both (handling ANSI codes in highlighted version)
- Strips duplicate spaces when highlighted has >2x original indentation
- Preserves all ANSI color codes for syntax highlighting

Extracted helper functions to maintain code quality:
- countLeadingSpaces() - counts spaces in plain strings
- countLeadingSpacesWithANSI() - counts spaces while skipping ANSI codes
- stripLeadingSpaces() - removes N spaces while preserving ANSI codes

Also fixed unrelated linting issues:
- Added static error ErrCommandNil for templater.go
- Removed unused processHelp function and help.go file
- Removed unused workflowMarkdown variable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* chore: upgrade Chroma from v0.10.0 to v2.20.0

Upgraded to Chroma v2.20.0 which includes the fix for YAML multiline
whitespace issues (fixed in v2.15.0 via PR #993).

Changes:
- Updated all Chroma imports from v0 to v2
- Updated go.mod dependencies
- Removed old v0.10.0 dependency

The v2.15.0 release includes "Don't output extra whitespace in YAML
multiline" fix by @Gusted which should resolve the folded scalar
indentation duplication issue.

Kept the fixHighlightedIndentation() workaround as a safety net in case
the upstream fix doesn't cover all edge cases.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* cleanup: remove workaround for Chroma YAML indentation bug

Removed the fixHighlightedIndentation() workaround and helper functions
since the Chroma v2.20.0 upgrade fixed the YAML multiline indentation
issue.

The upstream fix in Chroma v2.15.0 (PR #993) properly handles YAML
folded scalars without adding duplicate whitespace, making our
post-processing workaround unnecessary.

Kept the stderr terminal detection enhancement as it's still needed
to ensure syntax highlighting works when provenance output goes to
stderr instead of stdout.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* fix: send provenance output to stdout for piping

Changed provenance output from stderr to stdout to enable piping:
  atmos describe component vpc --stack dev --provenance | grep pattern

Changes:
- Provenance output now goes to stdout (fmt.Print)
- Simplified output logic: write to file if specified, else stdout
- Removed unused golang.org/x/term import
- Refactored to reduce complexity (extracted renderProvenance method)
- Added type assertion with static error for provenance rendering

This aligns with Unix philosophy and Atmos design: data goes to stdout,
UI messages go to stderr.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Address CodeRabbit review comments for provenance feature

- Fix comment punctuation in tree_renderer.go (add missing period)
- Add performance tracking to buildFileTree function
- Fix null value handling in merge provenance recording
- Add comprehensive error condition tests
- Enhance test assertions for provenance rendering

- Ensures compliance with golangci-lint godot rules (all comments must end with periods)
- Adds performance tracking to critical functions per coding guidelines
- Fixes bug where nil values were not tracked in provenance (now treats nil as a scalar)
- Improves test coverage with error conditions: nil atmosConfig, malformed entries, null values, nested structures, and different provenance types
- Makes test assertions more specific and thorough, verifying exact comment formats and legend text

- Addresses 6 unresolved CodeRabbit review comments on PR #1584
- Follows project guidelines in CLAUDE.md for comments, perf tracking, and test quality

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Fix data race in ProcessYAMLConfigFiles goroutines

- Add mutex protection for errorResult variable accessed by multiple goroutines

- CodeRabbit identified potential data race where multiple goroutines write to errorResult without synchronization
- Lines 173, 205, and 222 all write to errorResult from different goroutines
- Without synchronization, this could lead to race conditions and undefined behavior

- Add errorLock sync.Mutex to protect errorResult writes
- Wrap all errorResult assignments with errorLock.Lock()/Unlock()
- Maintains existing processYAMLConfigFilesLock for map/slice access

- Addresses CodeRabbit review comment on PR #1584

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* Fix godot linter issue in merge_with_provenance.go parameter comments

- Add periods to parameter comment lines that were ending with colons

- golangci-lint godot rule requires all comments to end with periods
- Parameter descriptions like "atmosConfig: ..." should end with "flag." not "flag"

- Addresses linting issue identified in PR #1584 review

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

* updates

* updates

* updates

* updates

* updates

* updates

---------

Co-authored-by: Claude <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: aknysh <[email protected]>
@coderabbitai coderabbitai bot mentioned this pull request Oct 8, 2025
@github-actions
Copy link

github-actions bot commented Oct 8, 2025

These changes were released in v1.194.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-release Do not create a new release (wait for additional code changes) size/xl Extra large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants