---
id: TASK-15.1
title: Implement recursive config interpolation
status: Done
assignee:
  - '@codex'
created_date: '2026-02-19 15:48'
updated_date: '2026-02-19 15:55'
labels: []
dependencies: []
references:
  - lua/zync/lib/utils.lua
  - lua/zync/api/configurator.lua
  - lua/zync/api/configurator/sandbox.lua
parent_task_id: TASK-15
---

## Description

<!-- SECTION:DESCRIPTION:BEGIN -->
Add recursive interpolation of config fields so ${key} placeholders resolve using the config table as the source map, including nested tables. Ensure interpolation avoids infinite loops and handles non-string values safely.
<!-- SECTION:DESCRIPTION:END -->

## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 Config values with ${key} placeholders are interpolated recursively across nested tables.
- [x] #2 Non-string values are preserved without errors during interpolation.
- [x] #3 Interpolation handles cyclic references or repeated tables without crashing.
<!-- AC:END -->

## Implementation Plan

<!-- SECTION:PLAN:BEGIN -->
1) Inspect Utils.interpolate for behavior and edge cases.
2) Implement recursive interpolation helper that walks tables, applies Utils.interpolate to strings, preserves non-strings, and handles cycles/shared tables safely.
3) Integrate helper into config processing (configurator.lua) so loaded config is interpolated after validation.
<!-- SECTION:PLAN:END -->

## Implementation Notes

<!-- SECTION:NOTES:BEGIN -->
Added Utils.interpolate_recursive with an interpolation map that resolves placeholders via existing Utils.interpolate, handles nested tables and cycle detection, and ignores non-scalar placeholder values. Wired Configurator.init_conf to call utils.interpolate_recursive after resolved fields (build_dir/project_dir/zephyr paths) are set. Tests not run (per instruction).
<!-- SECTION:NOTES:END -->

## Final Summary

<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Implemented recursive config interpolation using Utils.interpolate. Added Utils.interpolate_recursive with cycle-safe traversal and a lazy interpolation map to resolve ${key} placeholders from the config table. Wired Configurator.init_conf to run interpolation after computed fields (build_dir/project_dir/zephyr paths) are set. Tests not run (per instruction).
<!-- SECTION:FINAL_SUMMARY:END -->
