--- id: CANP-WP-0005 type: workplan title: "Document and detect inclusion diamonds" domain: agents repo: canned-prompts status: finished owner: codex topic_slug: practice created: "2026-09-06" updated: "2026-09-06" state_hub_workstream_id: "773f08a3-f899-53fc-87c8-037f8ffbd24d" --- # Document and detect inclusion diamonds Residual from `CANP-WP-0004` (`origin: residual`, `origin_ref: CANP-WP-0004`). ## Warn about repeated inclusion ```task id: CANP-WP-0005-T01 status: done priority: medium state_hub_task_id: "74234a7a-c3bd-5bf7-a40d-21ddf208cfb5" ``` CPF inclusion (§ 10.4) does not deduplicate: when one package reaches the same dependency by two paths, the included text renders once per path. This was found by building a real collection — `helix/repo-advance` rendered its conventions block twice — and worked around downstream by factoring the shared routine into its own fragment. § 10.4 says nothing about it, so an author meets the behaviour only by reading the output carefully. That silence is the defect. Two questions, and the second depends on the first: 1. **Document it.** State in § 10.4 that inclusion is textual and repeated, not deduplicated, and give the factoring pattern that avoids a diamond. 2. **Detect it.** Decide whether validation should warn when a package reaches the same dependency by more than one path. A warning is cheap and catches the mistake at `add` time. Silently deduplicating is a different proposition entirely — it would mean choosing which occurrence survives, and deciding what happens when two paths resolve *different versions* of the same dependency. That is resolver behaviour, and § 10.4 keeps composition declarative on purpose. Leaning: document it now, warn at validation time, and do not deduplicate. ## Outcome Done as leaned, with one correction found by testing. **The documented mechanism was wrong at first.** § 10.4 was written describing a dependency "reached by two paths" through two `include` chains, and the detector counted composer calls to match. Tested against the real case that motivated the task — `helix/repo-advance` — and it did not fire, even though the conventions block still rendered twice. The actual mechanism is different and more subtle. `helix/commit-sync` declares its own `conventions` input; when composed, resolution passes the including package's already-resolved values down by name (§ 10.4 inheritance), so it *inherits* the outer text rather than resolving its own include — and renders it a second time. Nothing was included twice. The text appeared twice regardless. Both mechanisms are now documented with worked diagrams, and `duplicate_inclusions` detects both: included values that are equal, and an included value contained within another. `resolve`, `render` and `eval` warn; nothing is deduplicated. Verified by reintroducing the diamond in a scratch copy of `repo-advance` — it warns — and confirming the shipped factored collection stays silent. Tests 90 → 95.