feat(plan): add polyphony plan derive-ancestor-chain verb (Phase 3 P7a) - #82
Merged
Merged
Conversation
…P7a)
Helper verb that walks the work-item parent chain from --item-id up to (but
not past) --root-id and emits the inputs the Phase 3 plan-PR verbs need:
* --root-id — echo of the input
* --parent-item-id — immediate plan-tree parent (null for root plan and
direct children of root, where the parent is implicit)
* --ancestor-ids — comma-separated chain (immediate parent first),
with the literal "root" token in place of the root
work-item id; empty for the root plan
The workflow consumer (`plan-level.yaml`, P7b) only needs to know root_id +
work_item_id; the helper derives parent_item_id and ancestor_ids by walking
WorkItem.ParentId. This shifts the chain-construction logic out of brittle
Jinja templates and into testable C#.
The verb is a routing-style script: always exits 0, surfaces errors via the
`error` field. Error paths covered:
* --root-id / --item-id non-positive
* Item not found in the local cache
* Item is not a descendant of root (parent chain dead-ends)
* Ancestor in the chain is missing from the local cache
* Cycle detected in parent chain (de-dup set)
* Walk exceeds 50 steps (cycle suspected, defensive)
Tests: 11 new unit tests covering the root-plan special case, direct child
of root, grandchild, great-grandchild, and all error paths. Full suite:
1772/1772 passing (was 1761; +11). Type-agnostic lint passes.
Phase 3 P7a — preparation for the `plan-level.yaml` rewrite (P7b). Follows
P7-pre identity-decision (option 2: LLM advisory + human approval).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 3 P7a — preparation step for the upcoming
plan-level.yamlrewrite (P7b).Adds a small routing-style verb that walks the work-item parent chain from a
given
--item-idup to (but not past) the run's--root-id, and emits theinputs the Phase 3 plan-PR verbs (
branch ensure-plan,pr open-plan-pr,pr merge-plan-pr) need:root_id--root-id(echo)is_root_plantruewhenitem_id == root_idparent_item_id--parent-item-idnullfor root plan + direct children of root; else parent's idancestor_ids--ancestor-ids(CSV string)"root". Empty for rootancestor_chainancestor_idsbut asstring[]deptherrornullon successWhy a verb instead of Jinja
plan-level.yamlonly knowswork_item_id(echo ofworkflow.input.work_item_id)and — once P7b lands —
root_id(propagated throughfor_each). Computingparent_item_id+ancestor_idsfrom those two requires walkingWorkItem.ParentIdrepeatedly, which is brittle in Jinja and impossible tounit-test.
This verb does it in ~120 lines of C# with full test coverage. The workflow
becomes:
(The
pr open-plan-prverb already treats--parent-item-id 0as "omit",matching the convention from
branch ensure-planandpr merge-plan-pr.)What's covered
11 unit tests (
PlanCommandsDeriveAncestorChainTests.cs):--root-id <= 0,--item-id <= 0item_id == root_id→ root-plan special case (empty chain)parent_item_idisnull, chain is["root"])[parent, "root"])[parent, grandparent, "root"])Plus type-agnostic lint passing and full suite green: 1772/1772 (was 1761; +11).
What's NOT in this PR
plan-level.yamlrewrite) — that's P7b, whichfollows separately. P7a was split out so the verb can ship + be reviewed
independently of the larger workflow change.
"root"token convention is inherited frompr open-plan-pr's existing--ancestor-idscontract (seePrCommands.OpenPlanPr.csXML doc); this PR doesn't change that.Phase 3 progress
PRs P0–P6 merged. P7-pre decision applied (option 2: LLM advisory + human approval).
This is P7a. Next: P7b (the
plan-level.yamlrewrite itself), thenP8 (scope renegotiation), P9 (ancestor cascade), P10 (operator UX).